From 326a3c5932c2fac3c9e217be03ea7a9482257f43 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 3 Dec 2013 19:26:11 -0800 Subject: [PATCH 0001/1608] Fix typo in test description and reduce sauce test timeouts. --- test/saucelabs.js | 2 +- test/test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index ea80422834..4b91026e70 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -248,7 +248,7 @@ 'build': build, 'framework': 'qunit', 'idle-timeout': 300, - 'max-duration': 600, + 'max-duration': 480, 'name': sessionName, 'public': 'public', 'platforms': platforms, diff --git a/test/test.js b/test/test.js index f7d722665e..70ca1c41d5 100644 --- a/test/test.js +++ b/test/test.js @@ -8143,7 +8143,7 @@ deepEqual(actual, [['barney', 36, undefined], ['fred', 40, false]]); }); - test('should support consuming it\'s return value', 1, function() { + test('should support consuming its return value', 1, function() { var expected = [['barney', 'fred'], [36, 40]]; deepEqual(_.zip(_.zip(_.zip(_.zip(expected)))), expected); }); From 783c16520189885e272c96ba3d094618fd8ffeba Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 3 Dec 2013 20:40:15 -0800 Subject: [PATCH 0002/1608] Add doc note to `_.zip` about unzipping values. [ci skip] [closes #418] --- doc/README.md | 83 ++++++++++++++++++++++++++------------------------- lodash.js | 12 +++++--- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/doc/README.md b/doc/README.md index a506ac3c8c..a6fef06cc3 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1002,9 +1002,9 @@ _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); ### `_.zip([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5429 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5433 "View in source") [Ⓣ][1] -Creates an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on. +Creates an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on. If a zipped value is provided its corresponding unzipped value will be returned. #### Aliases *_.unzip* @@ -1019,6 +1019,9 @@ Creates an array of grouped elements, the first of which contains the first elem ```js _.zip(['fred', 'barney'], [30, 40], [true, false]); // => [['fred', 30, true], ['barney', 40, false]] + +_.unzip([['fred', 30, true], ['barney', 40, false]]); +// => [['fred', 'barney'], [30, 40], [true, false]] ``` * * * @@ -1029,7 +1032,7 @@ _.zip(['fred', 'barney'], [30, 40], [true, false]); ### `_.zipObject(keys, [values=[]])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5459 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5463 "View in source") [Ⓣ][1] Creates an object composed from arrays of `keys` and `values`. Provide either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` or two arrays, one of `keys` and one of corresponding `values`. @@ -1119,7 +1122,7 @@ _.isArray(squares.value()); ### `_.chain(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6788 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6792 "View in source") [Ⓣ][1] Creates a `lodash` object that wraps the given value with explicit method chaining enabled. @@ -1153,7 +1156,7 @@ var youngest = _.chain(characters) ### `_.tap(value, interceptor)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6814 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6818 "View in source") [Ⓣ][1] Invokes `interceptor` with the `value` as the first argument and then returns `value`. The purpose of this method is to "tap into" a method chain in order to perform operations on intermediate results within the chain. @@ -1181,7 +1184,7 @@ _([1, 2, 3, 4]) ### `_.prototype.chain()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6844 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6848 "View in source") [Ⓣ][1] Enables explicit method chaining on the wrapper object. @@ -1215,7 +1218,7 @@ _(characters).chain() ### `_.prototype.toString()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6861 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6865 "View in source") [Ⓣ][1] Produces the `toString` result of the wrapped value. @@ -1236,7 +1239,7 @@ _([1, 2, 3]).toString(); ### `_.prototype.valueOf()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6878 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6882 "View in source") [Ⓣ][1] Extracts the wrapped value. @@ -2221,7 +2224,7 @@ _.where(characters, { 'pets': ['dino'] }); ### `_.after(n, func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5504 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5508 "View in source") [Ⓣ][1] Creates a function that executes `func`, with the `this` binding and arguments of the created function, only after being called `n` times. @@ -2254,7 +2257,7 @@ _.forEach(saves, function(type) { ### `_.bind(func, [thisArg], [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5537 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5541 "View in source") [Ⓣ][1] Creates a function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends any additional `bind` arguments to those provided to the bound function. @@ -2285,7 +2288,7 @@ func(); ### `_.bindAll(object, [methodName])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5567 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5571 "View in source") [Ⓣ][1] Binds methods of an object to the object itself, overwriting the existing method. Method names may be specified as individual arguments or as arrays of method names. If no method names are provided all the function properties of `object` will be bound. @@ -2316,7 +2319,7 @@ jQuery('#docs').on('click', view.onClick); ### `_.bindKey(object, key, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5613 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5617 "View in source") [Ⓣ][1] Creates a function that, when called, invokes the method at `object[key]` and prepends any additional `bindKey` arguments to those provided to the bound function. This method differs from `_.bind` by allowing bound functions to reference methods that will be redefined or don't yet exist. See http://michaux.ca/articles/lazy-function-definition-pattern. @@ -2357,7 +2360,7 @@ func(); ### `_.compose([func])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5649 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5653 "View in source") [Ⓣ][1] Creates a function that is the composition of the provided functions, where each function consumes the return value of the function that follows. For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. Each function is executed with the `this` binding of the composed function. @@ -2395,7 +2398,7 @@ welcome('pebbles'); ### `_.curry(func, [arity=func.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5697 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5701 "View in source") [Ⓣ][1] Creates a function which accepts one or more arguments of `func` that when invoked either executes `func` returning its result, if all `func` arguments have been provided, or returns a function that accepts one or more of the remaining `func` arguments, and so on. The arity of `func` can be specified if `func.length` is not sufficient. @@ -2430,7 +2433,7 @@ curried(1, 2, 3); ### `_.debounce(func, wait, [options], [options.maxWait])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5741 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5745 "View in source") [Ⓣ][1] Creates a function that will delay the execution of `func` until after `wait` milliseconds have elapsed since the last time it was invoked. 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 will return the result of the last `func` call. @@ -2474,7 +2477,7 @@ source.addEventListener('message', _.debounce(batchLog, 250, { ### `_.defer(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5857 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5861 "View in source") [Ⓣ][1] Defers executing the `func` function until the current call stack has cleared. Additional arguments will be provided to `func` when it is invoked. @@ -2499,7 +2502,7 @@ _.defer(function(text) { console.log(text); }, 'deferred'); ### `_.delay(func, wait, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5881 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5885 "View in source") [Ⓣ][1] Executes the `func` function after `wait` milliseconds. Additional arguments will be provided to `func` when it is invoked. @@ -2525,7 +2528,7 @@ _.delay(function(text) { console.log(text); }, 1000, 'later'); ### `_.memoize(func, [resolver])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5926 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5930 "View in source") [Ⓣ][1] Creates a function that memoizes the result of `func`. If `resolver` is provided it will be used to determine the cache key for storing the result based on the arguments provided to the memoized function. By default, the first argument provided to the memoized function is used as the cache key. The `func` is executed with the `this` binding of the memoized function. The result cache is exposed as the `cache` property on the memoized function. @@ -2568,7 +2571,7 @@ get('pebbles'); ### `_.once(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5959 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5963 "View in source") [Ⓣ][1] Creates a function that is restricted to execute `func` once. Repeat calls to the function will return the value of the first call. The `func` is executed with the `this` binding of the created function. @@ -2594,7 +2597,7 @@ initialize(); ### `_.partial(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5997 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6001 "View in source") [Ⓣ][1] Creates a function that, when called, invokes `func` with any additional `partial` arguments prepended to those provided to the new function. This method is similar to `_.bind` except it does **not** alter the `this` binding. @@ -2621,7 +2624,7 @@ hi('fred'); ### `_.partialRight(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6028 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6032 "View in source") [Ⓣ][1] This method is like `_.partial` except that `partial` arguments are appended to those provided to the new function. @@ -2658,7 +2661,7 @@ options.imports ### `_.throttle(func, wait, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6063 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6067 "View in source") [Ⓣ][1] Creates a function that, when executed, will only call the `func` function at most once per every `wait` milliseconds. 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 will return the result of the last `func` call. @@ -2694,7 +2697,7 @@ jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { ### `_.wrap(value, wrapper)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6104 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6108 "View in source") [Ⓣ][1] Creates a function that provides `value` to the wrapper function as its first argument. Additional arguments provided to the function are appended to those provided to the wrapper function. The wrapper is executed with the `this` binding of the created function. @@ -3988,7 +3991,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 }); ### `_.now` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6351 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6355 "View in source") [Ⓣ][1] *(unknown)*: Gets the number of milliseconds that have elapsed since the Unix epoch *(1 January `1970 00`:00:00 UTC)*. @@ -4007,7 +4010,7 @@ _.defer(function() { console.log(_.now() - stamp); }); ### `_.constant(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6125 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6129 "View in source") [Ⓣ][1] Creates a function that returns `value`. @@ -4033,7 +4036,7 @@ getter() === object; ### `_.createCallback([func=identity], [thisArg], [argCount])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6162 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6166 "View in source") [Ⓣ][1] Produces a callback bound to an optional `thisArg`. If `func` is a property name the created callback will return the property value for a given element. If `func` is an object the created callback will return `true` for elements that contain the equivalent object properties, otherwise it will return `false`. @@ -4072,7 +4075,7 @@ _.filter(characters, 'age__gt38'); ### `_.escape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6211 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6215 "View in source") [Ⓣ][1] Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding HTML entities. @@ -4096,7 +4099,7 @@ _.escape('Fred, Wilma, & Pebbles'); ### `_.identity(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6229 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6233 "View in source") [Ⓣ][1] This method returns the first argument provided to it. @@ -4121,7 +4124,7 @@ _.identity(object) === object; ### `_.mixin([object=lodash], source, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6261 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6265 "View in source") [Ⓣ][1] Adds function properties of a source object to the destination object. If `object` is a function methods will be added to its prototype as well. @@ -4157,7 +4160,7 @@ _('fred').capitalize(); ### `_.noConflict()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6317 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6321 "View in source") [Ⓣ][1] Reverts the '_' variable to its previous value and returns a reference to the `lodash` function. @@ -4177,7 +4180,7 @@ var lodash = _.noConflict(); ### `_.noop()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6334 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6338 "View in source") [Ⓣ][1] A no-operation function. @@ -4196,7 +4199,7 @@ _.noop(object) === undefined; ### `_.parseInt(value, [radix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6374 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6378 "View in source") [Ⓣ][1] Converts the given value into an integer of the specified radix. If `radix` is `undefined` or `0` a `radix` of `10` is used unless the `value` is a hexadecimal, in which case a `radix` of `16` is used. @@ -4223,7 +4226,7 @@ _.parseInt('08'); ### `_.property(key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6403 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6407 "View in source") [Ⓣ][1] Creates a "_.pluck" style function, which returns the `key` value of a given object. @@ -4257,7 +4260,7 @@ _.sortBy(characters, getName); ### `_.random([min=0], [max=1], [floating=false])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6436 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6440 "View in source") [Ⓣ][1] Produces a random number between `min` and `max` *(inclusive)*. If only one argument is provided a number between `0` and the given number will be returned. If `floating` is truey or either `min` or `max` are floats a floating-point number will be returned instead of an integer. @@ -4292,7 +4295,7 @@ _.random(1.2, 5.2); ### `_.result(object, key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6494 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6498 "View in source") [Ⓣ][1] Resolves the value of property `key` on `object`. If `key` is a function it will be invoked with the `this` binding of `object` and its result returned, else the property value is returned. If `object` is falsey then `undefined` is returned. @@ -4345,7 +4348,7 @@ Create a new `lodash` function using the given context object. ### `_.template(text, data, [options], [options.escape], [options.evaluate], [options.imports], [options.interpolate], [sourceURL], [variable])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6587 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6591 "View in source") [Ⓣ][1] A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code. @@ -4439,7 +4442,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\ ### `_.times(n, callback, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6710 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6714 "View in source") [Ⓣ][1] Executes the callback `n` times, returning an array of the results of each callback execution. The callback is bound to `thisArg` and invoked with one argument; *(index)*. @@ -4471,7 +4474,7 @@ _.times(3, function(n) { this.cast(n); }, mage); ### `_.unescape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6737 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6741 "View in source") [Ⓣ][1] The inverse of `_.escape` this method converts the HTML entities `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding characters. @@ -4495,7 +4498,7 @@ _.unescape('Fred, Barney & Pebbles'); ### `_.uniqueId([prefix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6757 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6761 "View in source") [Ⓣ][1] Generates a unique ID. If `prefix` is provided the ID will be appended to it. @@ -4548,7 +4551,7 @@ A reference to the `lodash` function. ### `_.VERSION` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7078 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7082 "View in source") [Ⓣ][1] *(string)*: The semantic version number. diff --git a/lodash.js b/lodash.js index 5b3790361d..b24fe86a7d 100644 --- a/lodash.js +++ b/lodash.js @@ -1803,7 +1803,7 @@ /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized, this method returns the custom method, otherwise it returns + * customized this method returns the custom method, otherwise it returns * the `baseIndexOf` function. * * @private @@ -5411,9 +5411,10 @@ } /** - * Creates an array of grouped elements, the first of which contains the first - * elements of the given arrays, the second of which contains the second - * elements of the given arrays, and so on. + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the second + * elements of the given arrays, and so on. If a zipped value is provided its + * corresponding unzipped value will be returned. * * @static * @memberOf _ @@ -5425,6 +5426,9 @@ * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip([['fred', 30, true], ['barney', 40, false]]); + * // => [['fred', 'barney'], [30, 40], [true, false]] */ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], From 250fd71e16944bd7379e28d6391b5e53dcd1ffdc Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 3 Dec 2013 22:38:02 -0800 Subject: [PATCH 0003/1608] Tweak readme layout of downloads and add not about 100% code coverage. [ci skip] --- README.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6f9598e8a9..b8f985f68d 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,9 @@ A utility library delivering consistency, [customization](http://lodash.com/cust Check out our [wiki]([https://github.com/lodash/lodash/wiki/build-differences]) for details over the differences between builds. -* Modern builds perfect for newer browsers/environments:
-[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) & -[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js) - -* Compatibility builds for older environment support too:
-[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) & -[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js) - -* Underscore builds to use as a drop-in replacement:
-[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) & -[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js) +* [Modern build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js)) perfect for new environments +* [Compatibility build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js)) for old environments too +* [Underscore build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js)) as a drop-in replacement CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash). For smaller file sizes, create [custom builds](http://lodash.com/custom-builds) with only the features needed. @@ -23,7 +15,7 @@ Love modules? We’ve got you covered with [lodash-amd](https://npmjs.org/packag ## Dive in -There’s plenty of **[documentation](http://lodash.com/docs)**, [unit tests](http://lodash.com/tests), & [benchmarks](http://lodash.com/benchmarks).
+There’s plenty of **[API documentation](http://lodash.com/docs)**, [unit tests](http://lodash.com/tests), & [benchmarks](http://lodash.com/benchmarks).
Check out DevDocs as a fast, organized, & searchable interface for our documentation. The full changelog for this release is available on our [wiki](https://github.com/lodash/lodash/wiki/Changelog).
@@ -31,6 +23,7 @@ A list of upcoming features is available on our [roadmap](https://github.com/lod ## Features *not* in Underscore + * 100% [code coverage](https://coveralls.io/r/lodash) * AMD loader support ([curl](https://github.com/cujojs/curl), [dojo](http://dojotoolkit.org/), [requirejs](http://requirejs.org/), etc.) * [_(…)](http://lodash.com/docs#_) supports intuitive chaining * [_.at](http://lodash.com/docs#at) for cherry-picking collection values From c2972fcaa0a1dddfbf9a980041e2752693ffeaf7 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 4 Dec 2013 22:09:32 -0800 Subject: [PATCH 0004/1608] Avoid adding `Function.prototype` additions to `_`. --- dist/lodash.compat.js | 14 +++++++---- dist/lodash.compat.min.js | 12 +++++----- dist/lodash.js | 14 +++++++---- dist/lodash.min.js | 2 +- dist/lodash.underscore.js | 14 +++++++---- dist/lodash.underscore.min.js | 2 +- lodash.js | 2 +- test/index.html | 10 +++++--- test/saucelabs.js | 2 +- test/test.js | 44 ++++++++++++++++++++++------------- 10 files changed, 72 insertions(+), 44 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 23798ba853..c2750e42c5 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -1786,7 +1786,7 @@ /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized, this method returns the custom method, otherwise it returns + * customized this method returns the custom method, otherwise it returns * the `baseIndexOf` function. * * @private @@ -5394,9 +5394,10 @@ } /** - * Creates an array of grouped elements, the first of which contains the first - * elements of the given arrays, the second of which contains the second - * elements of the given arrays, and so on. + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the second + * elements of the given arrays, and so on. If a zipped value is provided its + * corresponding unzipped value will be returned. * * @static * @memberOf _ @@ -5408,6 +5409,9 @@ * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip([['fred', 30, true], ['barney', 40, false]]); + * // => [['fred', 'barney'], [30, 40], [true, false]] */ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], @@ -6950,7 +6954,7 @@ lodash.unzip = zip; // add functions to `lodash.prototype` - mixin(lodash); + mixin(assign({}, lodash)); /*--------------------------------------------------------------------------*/ diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index d03b6ba6b9..4d948bc046 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -46,12 +46,12 @@ if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o return n},v.range=function(n,t,e){n=+n||0,e=typeof e=="number"?e:+e||1,null==t&&(t=n,n=0);var r=-1;t=Be(0,ye((t-n)/(e||1)));for(var u=Zt(t);++re?Be(0,r+e):Pe(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},v.mixin=Ut,v.noConflict=function(){return e._=ge,this},v.noop=Qt,v.now=ir,v.parseInt=lr,v.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Fe(),Pe(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):lt(n,t)},v.reduce=Rt,v.reduceRight=Ft,v.result=function(n,t){if(n){var e=n[t]; -return jt(e)?n[t]():e}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:We(n).length},v.some=$t,v.sortedIndex=Kt,v.template=function(n,t,e){var r=v.templateSettings;n=ie(n||""),e=Ze({},e,r);var u,o=Ze({},e.imports,r.imports),r=We(o),o=Et(o),i=0,l=e.interpolate||N,f="__p+='",l=ae((e.escape||N).source+"|"+l.source+"|"+(l===I?O:N).source+"|"+(e.evaluate||N).source+"|$","g");n.replace(l,function(t,e,r,o,l,c){return r||(r=o),f+=n.slice(i,c).replace(P,a),e&&(f+="'+__e("+e+")+'"),l&&(u=true,f+="';"+l+";\n__p+='"),r&&(f+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t +},v.xor=function(){for(var n=-1,t=arguments.length;++ne?Be(0,r+e):Pe(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},v.mixin=Ut,v.noConflict=function(){return e._=ge,this},v.noop=Qt,v.now=ir,v.parseInt=lr,v.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Fe(),Pe(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):lt(n,t) +},v.reduce=Rt,v.reduceRight=Ft,v.result=function(n,t){if(n){var e=n[t];return jt(e)?n[t]():e}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:We(n).length},v.some=$t,v.sortedIndex=Kt,v.template=function(n,t,e){var r=v.templateSettings;n=ie(n||""),e=Ze({},e,r);var u,o=Ze({},e.imports,r.imports),r=We(o),o=Et(o),i=0,l=e.interpolate||N,f="__p+='",l=ae((e.escape||N).source+"|"+l.source+"|"+(l===I?O:N).source+"|"+(e.evaluate||N).source+"|$","g");n.replace(l,function(t,e,r,o,l,c){return r||(r=o),f+=n.slice(i,c).replace(P,a),e&&(f+="'+__e("+e+")+'"),l&&(u=true,f+="';"+l+";\n__p+='"),r&&(f+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t }),f+="';",l=e=e.variable,l||(e="obj",f="with("+e+"){"+f+"}"),f=(u?f.replace(x,""):f).replace(C,"$1").replace(E,"$1;"),f="function("+e+"){"+(l?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var c=ee(r,"return "+f).apply(h,o)}catch(p){throw p.source=f,p}return t?c(t):(c.source=f,c)},v.unescape=function(n){return null==n?"":ie(n).replace(Ue,mt)},v.uniqueId=function(n){var t=++m;return ie(null==n?"":n)+t },v.all=St,v.any=$t,v.detect=It,v.findWhere=It,v.foldl=Rt,v.foldr=Ft,v.include=Ot,v.inject=Rt,Ut(function(){var n={};return tr(v,function(t,e){v.prototype[e]||(n[e]=t)}),n}(),false),v.first=Lt,v.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:h;return s(n,Be(0,u-r))},v.sample=function(n,t,e){return n&&typeof n.length!="number"?n=Et(n):Le.unindexedChars&&kt(n)&&(n=n.split("")),null==t||e?n?n[lt(0,n.length-1)]:h:(n=Tt(n),n.length=Pe(Be(0,t),n.length),n) },v.take=Lt,v.head=Lt,tr(v,function(n,t){var e="sample"!==t;v.prototype[t]||(v.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new y(o,u):o})}),v.VERSION="2.4.1",v.prototype.chain=function(){return this.__chain__=true,this},v.prototype.toString=function(){return ie(this.__wrapped__)},v.prototype.value=Yt,v.prototype.valueOf=Yt,Xe(["join","pop","shift"],function(n){var t=fe[n];v.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments); diff --git a/dist/lodash.js b/dist/lodash.js index d653e5aed7..779b157d83 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -1462,7 +1462,7 @@ /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized, this method returns the custom method, otherwise it returns + * customized this method returns the custom method, otherwise it returns * the `baseIndexOf` function. * * @private @@ -5044,9 +5044,10 @@ } /** - * Creates an array of grouped elements, the first of which contains the first - * elements of the given arrays, the second of which contains the second - * elements of the given arrays, and so on. + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the second + * elements of the given arrays, and so on. If a zipped value is provided its + * corresponding unzipped value will be returned. * * @static * @memberOf _ @@ -5058,6 +5059,9 @@ * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip([['fred', 30, true], ['barney', 40, false]]); + * // => [['fred', 'barney'], [30, 40], [true, false]] */ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], @@ -6600,7 +6604,7 @@ lodash.unzip = zip; // add functions to `lodash.prototype` - mixin(lodash); + mixin(assign({}, lodash)); /*--------------------------------------------------------------------------*/ diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 85a9626340..8ce51d1201 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -42,7 +42,7 @@ return l(o),l(i),n},J.min=function(n,t,e){var u=1/0,o=u;if(typeof t!="function"& }else t=J.createCallback(t,e,3),g(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},J.pluck=Ve,J.property=Jt,J.pull=function(n){for(var t=arguments,e=0,r=t.length,u=n?n.length:0;++e [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip([['fred', 30, true], ['barney', 40, false]]); + * // => [['fred', 'barney'], [30, 40], [true, false]] */ function zip() { var index = -1, @@ -4900,7 +4904,7 @@ /*--------------------------------------------------------------------------*/ // add functions to `lodash.prototype` - mixin(lodash); + mixin(assign({}, lodash)); /** * The semantic version number. diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index e659124478..2b242f5de6 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -35,5 +35,5 @@ for(r||!e||Cr(n[0])||(r=[]);++tt?Mr(0,e+t):$r(t,e-1))+1);e--;)if(n[e]===r)return e; return-1},u.mixin=Z,u.noConflict=function(){return mr._=Tr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Sr(Wr()*(r-n+1))},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return A(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Ur(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||or).source+"|"+(e.interpolate||or).source+"|"+(e.evaluate||or).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(ir,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r }),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+"").replace(Hr,d)},u.uniqueId=function(n){var r=++tr+"";return n?n+r:r},u.all=B,u.any=P,u.detect=q,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=k,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0; -if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:rr;return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=R(n)),null==r||t?n?n[0+Sr(Wr()*(n.length-1-0+1))]:rr:(n=C(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(u),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},D("pop push reverse shift sort splice unshift".split(" "),function(n){var r=jr[n]; +if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:rr;return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=R(n)),null==r||t?n?n[0+Sr(Wr()*(n.length-1-0+1))]:rr:(n=C(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},D("pop push reverse shift sort splice unshift".split(" "),function(n){var r=jr[n]; u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),zr.spliceObjects||0!==n.length||delete n[0],this}}),D(["concat","join","slice"],function(n){var r=jr[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(mr._=u, define(function(){return u})):_r&&dr?br?(dr.exports=u)._=u:_r._=u:mr._=u}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index b24fe86a7d..69b8770572 100644 --- a/lodash.js +++ b/lodash.js @@ -6971,7 +6971,7 @@ lodash.unzip = zip; // add functions to `lodash.prototype` - mixin(lodash); + mixin(assign({}, lodash)); /*--------------------------------------------------------------------------*/ diff --git a/test/index.html b/test/index.html index f0057617b2..2a40fa4463 100644 --- a/test/index.html +++ b/test/index.html @@ -18,6 +18,9 @@
- + \ No newline at end of file diff --git a/test/backbone.html b/test/backbone.html index 4f7b03aa83..38572c28df 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -73,4 +73,4 @@

Test

- + \ No newline at end of file diff --git a/test/index.html b/test/index.html index 40b06b4fb6..40463eeb2b 100644 --- a/test/index.html +++ b/test/index.html @@ -237,4 +237,4 @@ }; - + \ No newline at end of file diff --git a/test/underscore.html b/test/underscore.html index 8ae160616f..2be2271e97 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -202,4 +202,4 @@
  • <%= data %>
  • - + \ No newline at end of file From 14ed669ebaea020545a806012939890f3dcaf165 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 21 Dec 2013 10:05:07 -0600 Subject: [PATCH 0076/1608] Use a fixed version, 1.1.0, until sauce-tunnel fixes their corrupt 1.1.1 npm package. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c243375624..c38a82ef1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ branches: before_install: - "([ $BUILD == 'legacy' ] || [ $BUILD == 'mobile' ] || [ $BUILD == 'modern' ]) && MAKE=true || true" - "([ $BUILD == 'compat' ] || [ $BUILD == 'legacy' ]) && COMPAT=true || true" - - "[ $SAUCE_LABS == false ] || npm i ecstatic@\"~0.4.0\" request@\"~2.27.0\" sauce-tunnel@\"~1.1.0\"" + - "[ $SAUCE_LABS == false ] || npm i ecstatic@\"~0.4.0\" request@\"~2.27.0\" sauce-tunnel@\"1.1.0\"" - "[ $ISTANBUL == false ] || npm i -g coveralls@\"~2.5.0\" && npm i istanbul@\"~0.1.0\"" - "[ $BIN != 'narwhal' ] || (wget https://github.com/280north/narwhal/archive/v0.3.2.zip && sudo unzip v0.3.2 -d /opt/ && rm v0.3.2.zip)" - "[ $BIN != 'narwhal' ] || (sudo ln -s /opt/narwhal-0.3.2/bin/narwhal /usr/local/bin/narwhal && sudo chmod +x /usr/local/bin/narwhal)" From 8069853ddaeee4e8297e6896b74a8ebc73c0f9e1 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 21 Dec 2013 10:39:02 -0600 Subject: [PATCH 0077/1608] Fix `reEscapedHtml` for underscore builds. --- dist/lodash.underscore.js | 2 +- dist/lodash.underscore.min.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index fb7be599a5..914a456faf 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -27,7 +27,7 @@ reInterpolate = /<%=([\s\S]+?)%>/g; /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g, reUnescapedHtml = /[&<>"']/g; /** Used to ensure capturing order of template delimiters */ diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index c6947ea4ef..fc16953eb6 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -19,7 +19,7 @@ else r=X(r,t,3),$(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}functio return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o>>1,t(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;if(null==n||"function"==e)return a(n,r,t);if("object"!=e)return nr(n);var u=Kr(n);return function(r){for(var t=u.length,e=false;t--&&(e=r[u[t]]===n[u[t]]););return e}}function Y(n){return n}function Z(n){$(T(n),function(r){var t=u[r]=n[r];u.prototype[r]=function(){var n=[this.__wrapped__]; -return $r.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function nr(n){return function(r){return r[n]}}var rr,tr=0,er={},ur=+new Date+"",or=/&(?:amp|lt|gt|quot|#39);/g,ir=/[&<>"']/g,fr=/($^)/,ar=/['\n\r\t\u2028\u2029\\]/g,lr="[object Arguments]",cr="[object Array]",pr="[object Boolean]",sr="[object Date]",gr="[object Number]",hr="[object Object]",vr="[object RegExp]",yr="[object String]",mr={"&":"&","<":"<",">":">",'"':""","'":"'"},_r={"&":"&","<":"<",">":">",""":'"',"'":"'"},dr={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},br={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},wr=dr[typeof window]&&window||this,jr=dr[typeof exports]&&exports&&!exports.nodeType&&exports,xr=dr[typeof global]&&global; +return $r.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function nr(n){return function(r){return r[n]}}var rr,tr=0,er={},ur=+new Date+"",or=/&(?:amp|lt|gt|quot|#x27);/g,ir=/[&<>"']/g,fr=/($^)/,ar=/['\n\r\t\u2028\u2029\\]/g,lr="[object Arguments]",cr="[object Array]",pr="[object Boolean]",sr="[object Date]",gr="[object Number]",hr="[object Object]",vr="[object RegExp]",yr="[object String]",mr={"&":"&","<":"<",">":">",'"':""","'":"'"},_r={"&":"&","<":"<",">":">",""":'"',"'":"'"},dr={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},br={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},wr=dr[typeof window]&&window||this,jr=dr[typeof exports]&&exports&&!exports.nodeType&&exports,xr=dr[typeof global]&&global; !xr||xr.global!==xr&&xr.window!==xr||(wr=xr);var Tr=dr[typeof module]&&module&&!module.nodeType&&module,Ar=Tr&&Tr.exports===jr&&jr,Er=[],Or=Object.prototype,Sr=wr._,kr=Or.toString,Nr=RegExp("^"+(kr+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),qr=Math.ceil,Fr=Math.floor,Br=Function.prototype.toString,Rr=Or.hasOwnProperty,$r=Er.push,Dr=Or.propertyIsEnumerable,Ir=_(Ir=Object.create)&&Ir,Mr=_(Mr=Array.isArray)&&Mr,Wr=wr.isFinite,zr=wr.isNaN,Cr=_(Cr=Object.keys)&&Cr,Pr=Math.max,Ur=Math.min,Vr=Math.random; o.prototype=u.prototype;var Gr={};!function(){var n={0:1,length:1};Gr.spliceObjects=(Er.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Ir||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||wr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Rr.call(n,"callee")&&!Dr.call(n,"callee")||false});var Hr=Mr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&kr.call(n)==cr||false },Jr=function(n){var r=[];if(!n||!dr[typeof n])return r;for(var t in n)Rr.call(n,t)&&r.push(t);return r},Kr=Cr?function(n){return O(n)?Cr(n):[]}:Jr,Lr=function(n,r){if(!n||!dr[typeof n])return n;for(var t in n)if(r(n[t],t,n)===er)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==kr.call(n)});var Qr=h(function(n,r,t){Rr.call(n,t)?n[t]++:n[t]=1}),Xr=h(function(n,r,t){(Rr.call(n,t)?n[t]:n[t]=[]).push(r)}),Yr=h(function(n,r,t){n[t]=r}),Zr=I,nt=_(nt=Date.now)&&nt||function(){return(new Date).getTime() From ad0bcc7de952d68e1cddc96de4e3af513e3a1be7 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 22 Dec 2013 01:25:24 -0600 Subject: [PATCH 0078/1608] Add another `_.constant` test for falsey values. --- test/test.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index c8742a9c61..c88ff0da97 100644 --- a/test/test.js +++ b/test/test.js @@ -1126,12 +1126,30 @@ (function() { test('should create a function that always returns `value`', 1, function() { var object = { 'a': 1 }, - values = falsey.concat(1, 'a'), + values = falsey.concat(null, null, 1, 'a'), constant = _.constant(object), - expected = _.map(values, function() { return object; }); + expected = _.map(values, function() { return true; }); var actual = _.map(values, function(value, index) { - return index ? constant(value) : constant(); + if (index == 0) { + var result = constant(); + } else if (index == 1) { + result = constant.call({}); + } else { + result = constant(value); + } + return result === object; + }); + + deepEqual(actual, expected); + }); + + test('should work with falsey values', 1, function() { + var expected = _.map(falsey, function() { return true; }); + + var actual = _.map(falsey, function(value, index) { + var constant = index ? _.constant(value) : _.constant(); + return constant() === value || _.isNaN(value); }); deepEqual(actual, expected); From 99fac3ae1c01385591604ac71a86a99bafac89b2 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 22 Dec 2013 23:00:54 -0600 Subject: [PATCH 0079/1608] Go back to a version range in travis.yml now that sauce-tunnel has fixed its npm issues. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c38a82ef1d..c243375624 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ branches: before_install: - "([ $BUILD == 'legacy' ] || [ $BUILD == 'mobile' ] || [ $BUILD == 'modern' ]) && MAKE=true || true" - "([ $BUILD == 'compat' ] || [ $BUILD == 'legacy' ]) && COMPAT=true || true" - - "[ $SAUCE_LABS == false ] || npm i ecstatic@\"~0.4.0\" request@\"~2.27.0\" sauce-tunnel@\"1.1.0\"" + - "[ $SAUCE_LABS == false ] || npm i ecstatic@\"~0.4.0\" request@\"~2.27.0\" sauce-tunnel@\"~1.1.0\"" - "[ $ISTANBUL == false ] || npm i -g coveralls@\"~2.5.0\" && npm i istanbul@\"~0.1.0\"" - "[ $BIN != 'narwhal' ] || (wget https://github.com/280north/narwhal/archive/v0.3.2.zip && sudo unzip v0.3.2 -d /opt/ && rm v0.3.2.zip)" - "[ $BIN != 'narwhal' ] || (sudo ln -s /opt/narwhal-0.3.2/bin/narwhal /usr/local/bin/narwhal && sudo chmod +x /usr/local/bin/narwhal)" From 990e73fce6d5628127995250a8f8d8401ffb0434 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 22 Dec 2013 23:23:14 -0600 Subject: [PATCH 0080/1608] Add `_.match`. --- dist/lodash.compat.js | 100 +++++++---- dist/lodash.compat.min.js | 101 ++++++----- dist/lodash.js | 100 +++++++---- dist/lodash.min.js | 89 ++++----- dist/lodash.underscore.js | 76 +++++--- dist/lodash.underscore.min.js | 66 +++---- doc/README.md | 329 +++++++++++++++++++--------------- lodash.js | 100 +++++++---- test/test.js | 21 ++- 9 files changed, 574 insertions(+), 408 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 643a4bdc2d..afefae7f87 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -617,12 +617,13 @@ * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `map`, `mapValues`, `max`, `memoize`, `merge`, - * `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `pick`, `pluck`, `property`, `pull`, `push`, `range`, `reject`, `remove`, - * `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, - * `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `where`, `without`, `wrap`, `xor`, and `zip` + * `invert`, `invoke`, `keys`, `map`, `mapValues`, `match`, `max`, `memoize`, + * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, + * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, + * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, + * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, + * and `zip` * * The non-chainable wrapper functions are: * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, @@ -4452,8 +4453,8 @@ } /** - * Performs a deep comparison of each element in a `collection` to the given - * `properties` object, returning an array of all elements that have equivalent + * Performs a deep comparison between each element in `collection` and the + * `props` object, returning an array of all elements that have equivalent * property values. * * @static @@ -6205,34 +6206,8 @@ if (func == null || type == 'function') { return baseCreateCallback(func, thisArg, argCount); } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; - - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; - } - } - return result; - }; + // handle "_.pluck" and "_.where" style callback shorthands + return type != 'object' ? property(func) : match(func); } /** @@ -6274,6 +6249,58 @@ return value; } + /** + * Creates a "_.where" style function, which returns `true` for a given object + * if it has the equivalent property values of the `props` object, else `false`. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} props The object of property values to match. + * @returns {Function} Returns the new function. + * @example + * + * var characters = [ + * { 'name': 'fred', 'age': 40 }, + * { 'name': 'barney', 'age': 36 } + * ]; + * + * var matchAge = _.match({ 'age': 36 }); + * + * _.filter(characters, matchAge); + * // => [{ 'name': 'barney', 'age': 36 }] + * + * _.find(characters, matchAge); + * // => { 'name': 'barney', 'age': 36 } + */ + function match(source) { + source || (source = {}); + + var props = keys(source), + key = props[0], + a = source[key]; + + // fast path the common case of providing an object with a single + // property containing a primitive value + if (props.length == 1 && a === a && !isObject(a)) { + return function(object) { + var b = object[key]; + return a === b && (a !== 0 || (1 / a == 1 / b)); + }; + } + return function(object) { + var length = props.length, + result = false; + + while (length--) { + if (!(result = baseIsEqual(object[props[length]], source[props[length]], null, true))) { + break; + } + } + return result; + }; + } + /** * Adds function properties of a source object to the destination object. * If `object` is a function methods will be added to its prototype as well. @@ -6972,6 +6999,7 @@ lodash.keys = keys; lodash.map = map; lodash.mapValues = mapValues; + lodash.match = match; lodash.max = max; lodash.memoize = memoize; lodash.merge = merge; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index f362db195b..a3c11b4979 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -6,57 +6,56 @@ ;(function(){function n(n,t,r){r=(r||0)-1;for(var e=n?n.length:0;++ri||typeof a=="undefined")return 1;if(ar?0:r);++e=b&&a===n,l=[];if(f){var c=o(e);c?(a=t,e=c):f=false}for(;++ua(e,c)&&l.push(c); -return f&&p(e),l}function ft(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ut(t,r,3),typeof o=="number")for(Hr.unindexedChars&&Rt(u)&&(u=u.split(""));++e=b&&f===n,h=u||g?i():s;for(g&&(h=o(h),f=t);++af(h,y))&&((u||g)&&h.push(y),s.push(v))}return g?(c(h.g),p(h)):u&&c(h),s}function ht(n){return function(t,r,e){var u={};if(r=v.createCallback(r,e,3),Qr(t)){e=-1;for(var o=t.length;++eu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ut,K,mr,Ir,jt,dr,nt,Gr,H,br,jr) -}function mt(n){return Y[n]}function dt(){var t=(t=v.indexOf)===Gt?n:t;return t}function bt(n){return typeof n=="function"&&xr.test(Er.call(n))}function _t(n){var t,r;return!n||jr.call(n)!=U||(t=n.constructor,It(t)&&!(t instanceof t))||!Hr.argsClass&&jt(n)||!Hr.nodeClass&&l(n)?false:Hr.ownLast?(Zr(n,function(n,t,e){return r=Ir.call(e,t),false}),false!==r):(Zr(n,function(n,t){r=t}),typeof r=="undefined"||Ir.call(n,r))}function wt(n){return Z[n]}function jt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&jr.call(n)==B||false -}function xt(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!Qr(n)&&Rt(n))return $r?$r.call(n,t,r):-1r?zr(0,e+r):r)||0,-1o&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Qr(n)){var o=-1,a=n.length;for(u&&(r=n[++o]);++oarguments.length;return t=v.createCallback(t,e,4),Bt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ar(typeof r=="number"?r:0);return Ft(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;if(t=v.createCallback(t,r,3),Qr(n)){r=-1;for(var u=n.length;++re?zr(0,u+e):e||0}else if(e)return e=Jt(t,r),t[e]===r?e:-1;return n(t,r,e)}function Ht(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=v.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=h;m?(u&&(u=kr(u)),c=a,o=n.apply(i,e)):u||(u=Rr(y,h))}return m&&f?f=kr(f):f||t===p||(f=Rr(v,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function tr(n){return n}function rr(n,t,r){var e=true,u=t&&Et(t);t&&(r||u.length)||(null==r&&(r=t),o=y,t=n,n=v,u=Et(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain);var o=n,a=It(o);Ft(u,function(r){var u=n[r]=t[r];a&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,a=[r];if(Ar.apply(a,arguments),a=u.apply(n,a),e||t){if(r===a&&At(a))return this; -a=new o(a),a.__chain__=t}return a})})}function er(){}function ur(n){return function(t){return t[n]}}function or(){return this.__wrapped__}r=r?at.defaults(rt.Object(),r,at.pick(rt,q)):rt;var ar=r.Array,ir=r.Boolean,fr=r.Date,lr=r.Function,cr=r.Math,pr=r.Number,sr=r.Object,gr=r.RegExp,hr=r.String,vr=r.TypeError,yr=[],mr=r.Error.prototype,dr=sr.prototype,br=hr.prototype,_r=(_r=r.window)&&_r.document,wr=r._,jr=dr.toString,xr=gr("^"+hr(jr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Cr=cr.ceil,kr=r.clearTimeout,Or=cr.floor,Er=lr.prototype.toString,Sr=bt(Sr=sr.getPrototypeOf)&&Sr,Ir=dr.hasOwnProperty,Ar=yr.push,Nr=dr.propertyIsEnumerable,Rr=r.setTimeout,Tr=yr.splice,Pr=yr.unshift,Dr=function(){try{var n={},t=bt(t=sr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),$r=bt($r=br.contains)&&$r,qr=bt(qr=sr.create)&&qr,Fr=bt(Fr=ar.isArray)&&Fr,Br=r.isFinite,Lr=r.isNaN,Wr=bt(Wr=sr.keys)&&Wr,zr=cr.max,Kr=cr.min,Mr=r.parseInt,Vr=cr.random,Ur={};Ur[L]=ar,Ur[W]=ir,Ur[z]=fr,Ur[M]=lr,Ur[U]=sr,Ur[V]=pr,Ur[G]=gr,Ur[H]=hr;var Gr={};Gr[L]=Gr[z]=Gr[V]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Gr[W]=Gr[H]={constructor:true,toString:true,valueOf:true},Gr[K]=Gr[M]=Gr[G]={constructor:true,toString:true},Gr[U]={constructor:true},function(){for(var n=F.length;n--;){var t,r=F[n]; -for(t in Gr)Ir.call(Gr,t)&&!Ir.call(Gr[t],r)&&(Gr[t][r]=false)}}(),y.prototype=v.prototype;var Hr=v.support={};!function(){var n=function(){this.x=1},t={0:1,length:1},e=[];n.prototype={valueOf:1,y:1};for(var u in new n)e.push(u);for(u in arguments);Hr.argsClass=jr.call(arguments)==B,Hr.argsObject=arguments.constructor==sr&&!(arguments instanceof ar),Hr.enumErrorProps=Nr.call(mr,"message")||Nr.call(mr,"name"),Hr.enumPrototypes=Nr.call(n,"prototype"),Hr.funcDecomp=!bt(r.WinRTError)&&D.test(g),Hr.funcNames=typeof lr.name=="string",Hr.nonEnumArgs=0!=u,Hr.nonEnumShadows=!/valueOf/.test(e),Hr.ownLast="x"!=e[0],Hr.spliceObjects=(yr.splice.call(t,0,1),!t[0]),Hr.unindexedChars="xx"!="x"[0]+sr("x")[0]; -try{Hr.dom=11===_r.createDocumentFragment().nodeType}catch(o){Hr.dom=false}try{Hr.nodeClass=!(jr.call(undefined)==U&&!({toString:0}+""))}catch(a){Hr.nodeClass=true}}(1),v.templateSettings={escape:S,evaluate:I,interpolate:A,variable:"",imports:{_:v}},qr||(et=function(){function n(){}return function(t){if(At(t)){n.prototype=t;var e=new n;n.prototype=null}return e||r.Object()}}());var Jr=Dr?function(n,t){X.value=t,Dr(n,"__bindData__",X)}:er;Hr.argsClass||(jt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ir.call(n,"callee")&&!Nr.call(n,"callee")||false -});var Qr=Fr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&jr.call(n)==L||false},Xr=yt({a:"p",b:"[]",e:"",c:"s.push(l)",f:true}),Yr=Wr?function(n){return At(n)?Hr.enumPrototypes&&typeof n=="function"||Hr.nonEnumArgs&&n.length&&jt(n)?Xr(n):Wr(n):[]}:Xr,Zr=yt({a:"p,b,x",b:"p",e:"b=b&&typeof x=='undefined'?b:a(b,x,3)",c:"if(b(p[l],l,p)===false){return s}",f:false});Hr.dom||(St=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!ne(n)||false}),It(/x/)&&(It=function(n){return typeof n=="function"&&jr.call(n)==M -});var ne=Sr?function(n){if(!n||jr.call(n)!=U||!Hr.argsClass&&jt(n))return false;var t=n.valueOf,r=bt(t)&&(r=Sr(t))&&Sr(r);return r?n==r||Sr(n)==r:_t(n)}:_t,te=ht(function(n,t,r){Ir.call(n,r)?n[r]++:n[r]=1}),re=ht(function(n,t,r){(Ir.call(n,r)?n[r]:n[r]=[]).push(t)}),ee=ht(function(n,t,r){n[r]=t}),ue=Lt,oe=bt(oe=fr.now)&&oe||function(){return(new fr).getTime()},ae=8==Mr(w+"08")?Mr:function(n,t){return Mr(Rt(n)?n.replace(T,""):n,t||0)};return v.after=function(n,t){if(!It(t))throw new vr;return function(){return 1>--n?t.apply(this,arguments):void 0 -}},v.assign=xt,v.at=function(n){var t=arguments,r=-1,e=lt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ar(t);for(Hr.unindexedChars&&Rt(n)&&(n=n.split(""));++r=b&&o(e?r[e]:s)))}var l=r[0],h=-1,v=l?l.length:0,y=[];n:for(;++h(m?t(m,g):f(s,g))){for(e=u,(m||s).push(g);--e;)if(m=a[e],0>(m?t(m,g):f(r[e],g)))continue n;y.push(g) -}}for(;u--;)(m=a[u])&&p(m);return c(a),c(s),y},v.invert=function(n,t){for(var r=-1,e=Yr(n),u=e.length,o={};++rr?zr(0,e+r):Kr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},v.mixin=rr,v.noConflict=function(){return r._=wr,this},v.noop=er,v.now=oe,v.parseInt=ae,v.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(typeof n=="boolean"&&u?(r=n,n=1):u||typeof t!="boolean"||(r=t,u=true)),e&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Vr(),Kr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) -},v.reduce=zt,v.reduceRight=Kt,v.result=function(n,t){if(n){var r=n[t];return It(r)?n[t]():r}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Yr(n).length},v.some=Vt,v.sortedIndex=Jt,v.template=function(n,t,r){var e=v.templateSettings;n=hr(n||""),r=Ct({},r,e);var u,o=Ct({},r.imports,e.imports),e=Yr(o),o=Tt(o),i=0,f=r.interpolate||P,l="__p+='",f=gr((r.escape||P).source+"|"+f.source+"|"+(f===A?k:P).source+"|"+(r.evaluate||P).source+"|$","g");n.replace(f,function(t,r,e,o,f,c){return e||(e=o),l+=n.slice(i,c).replace($,a),r&&(l+="'+__e("+r+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t -}),l+="';",f=r=r.variable,f||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(j,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(f?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=lr(e,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},v.unescape=function(n){return null==n?"":(n=hr(n),0>n.indexOf(";")?n:n.replace(N,wt))},v.uniqueId=function(n){var t=++m; -return hr(null==n?"":n)+t},v.all=Dt,v.any=Vt,v.detect=qt,v.findWhere=qt,v.foldl=zt,v.foldr=Kt,v.include=Pt,v.inject=zt,rr(function(){var n={};return kt(v,function(t,r){v.prototype[r]||(n[r]=t)}),n}(),false),v.first=Ut,v.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:h;return s(n,zr(0,u-e))},v.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Tt(n):Hr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[st(0,n.length-1)]:h:(n=Mt(n),n.length=Kr(zr(0,t),n.length),n) -},v.take=Ut,v.head=Ut,kt(v,function(n,t){var r="sample"!==t;v.prototype[t]||(v.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new y(o,u):o})}),v.VERSION="2.4.1",v.prototype.chain=function(){return this.__chain__=true,this},v.prototype.toString=function(){return hr(this.__wrapped__)},v.prototype.value=or,v.prototype.valueOf=or,ft(["join","pop","shift"],function(n){var t=yr[n];v.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new y(r,n):r}}),ft(["push","reverse","sort","unshift"],function(n){var t=yr[n];v.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ft(["concat","slice","splice"],function(n){var t=yr[n];v.prototype[n]=function(){return new y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Hr.spliceObjects||ft(["pop","shift","splice"],function(n){var t=yr[n],r="splice"==n;v.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new y(u,n):u +return u}function g(r){function v(n){return n&&typeof n=="object"&&!Xr(n)&&Ar.call(n,"__wrapped__")?n:new y(n)}function y(n,t){this.__chain__=!!t,this.__wrapped__=n}function _(n){function t(){if(e){var n=s(e);Nr.apply(n,arguments)}if(this instanceof t){var o=et(r.prototype),n=r.apply(o,n||arguments);return At(n)?n:o}return r.apply(u,n||arguments)}var r=n[0],e=n[2],u=n[4];return Qr(t,n),t}function tt(n,t,r,e,u){if(r){var o=r(n);if(typeof o!="undefined")return o}if(!At(n))return n;var a=xr.call(n); +if(!J[a]||!Jr.nodeClass&&l(n))return n;var f=Gr[a];switch(a){case W:case z:return new f(+n);case V:case H:return new f(n);case G:return o=f(n.source,O.exec(n)),o.lastIndex=n.lastIndex,o}if(a=Xr(n),t){var p=!e;e||(e=i()),u||(u=i());for(var g=e.length;g--;)if(e[g]==n)return u[g];o=a?f(n.length):{}}else o=a?s(n):xt({},n);return a&&(Ar.call(n,"index")&&(o.index=n.index),Ar.call(n,"input")&&(o.input=n.input)),t?(e.push(n),u.push(o),(a?ft:kt)(n,function(n,a){o[a]=tt(n,t,r,e,u)}),p&&(c(e),c(u)),o):o}function et(n){return At(n)?Fr(n):{} +}function ut(n,t,r){if(typeof n!="function")return tr;if(typeof t=="undefined"||!("prototype"in n))return n;var e=n.__bindData__;if(typeof e=="undefined"&&(Jr.funcNames&&(e=!n.name),e=e||!Jr.funcDecomp,!e)){var u=Sr.call(n);Jr.funcNames||(e=!E.test(u)),e||(e=D.test(u),Qr(n,e))}if(false===e||true!==e&&1&e[1])return n;switch(r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,o){return n.call(t,r,e,u,o) +}}return Zt(n,t)}function ot(n){function t(){var n=f?a:this;if(u){var h=s(u);Nr.apply(h,arguments)}return(o||c)&&(h||(h=s(arguments)),o&&Nr.apply(h,o),c&&h.length=b&&a===n,l=[];if(f){var c=o(e);c?(a=t,e=c):f=false}for(;++ua(e,c)&&l.push(c); +return f&&p(e),l}function ft(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ut(t,r,3),typeof o=="number")for(Jr.unindexedChars&&Rt(u)&&(u=u.split(""));++e=b&&f===n,h=u||g?i():s;for(g&&(h=o(h),f=t);++af(h,y))&&((u||g)&&h.push(y),s.push(v))}return g?(c(h.g),p(h)):u&&c(h),s}function ht(n){return function(t,r,e){var u={};if(r=v.createCallback(r,e,3),Xr(t)){e=-1;for(var o=t.length;++eu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ut,K,dr,Ar,jt,br,nt,Hr,H,_r,xr) +}function mt(n){return Y[n]}function dt(){var t=(t=v.indexOf)===Gt?n:t;return t}function bt(n){return typeof n=="function"&&Cr.test(Sr.call(n))}function _t(n){var t,r;return!n||xr.call(n)!=U||(t=n.constructor,It(t)&&!(t instanceof t))||!Jr.argsClass&&jt(n)||!Jr.nodeClass&&l(n)?false:Jr.ownLast?(ne(n,function(n,t,e){return r=Ar.call(e,t),false}),false!==r):(ne(n,function(n,t){r=t}),typeof r=="undefined"||Ar.call(n,r))}function wt(n){return Z[n]}function jt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&xr.call(n)==B||false +}function xt(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!Xr(n)&&Rt(n))return qr?qr.call(n,t,r):-1r?Kr(0,e+r):r)||0,-1o&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Xr(n)){var o=-1,a=n.length;for(u&&(r=n[++o]);++oarguments.length;return t=v.createCallback(t,e,4),Bt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Ft(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;if(t=v.createCallback(t,r,3),Xr(n)){r=-1;for(var u=n.length;++re?Kr(0,u+e):e||0}else if(e)return e=Jt(t,r),t[e]===r?e:-1;return n(t,r,e)}function Ht(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=v.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=h;m?(u&&(u=Or(u)),c=a,o=n.apply(i,e)):u||(u=Tr(y,h))}return m&&f?f=Or(f):f||t===p||(f=Tr(v,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function tr(n){return n}function rr(n){n||(n={});var t=Zr(n),r=t[0],e=n[r];return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=ct(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function er(n,t,r){var e=true,u=t&&Et(t);t&&(r||u.length)||(null==r&&(r=t),o=y,t=n,n=v,u=Et(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain); +var o=n,a=It(o);Ft(u,function(r){var u=n[r]=t[r];a&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,a=[r];if(Nr.apply(a,arguments),a=u.apply(n,a),e||t){if(r===a&&At(a))return this;a=new o(a),a.__chain__=t}return a})})}function ur(){}function or(n){return function(t){return t[n]}}function ar(){return this.__wrapped__}r=r?at.defaults(rt.Object(),r,at.pick(rt,q)):rt;var ir=r.Array,fr=r.Boolean,lr=r.Date,cr=r.Function,pr=r.Math,sr=r.Number,gr=r.Object,hr=r.RegExp,vr=r.String,yr=r.TypeError,mr=[],dr=r.Error.prototype,br=gr.prototype,_r=vr.prototype,wr=(wr=r.window)&&wr.document,jr=r._,xr=br.toString,Cr=hr("^"+vr(xr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),kr=pr.ceil,Or=r.clearTimeout,Er=pr.floor,Sr=cr.prototype.toString,Ir=bt(Ir=gr.getPrototypeOf)&&Ir,Ar=br.hasOwnProperty,Nr=mr.push,Rr=br.propertyIsEnumerable,Tr=r.setTimeout,Pr=mr.splice,Dr=mr.unshift,$r=function(){try{var n={},t=bt(t=gr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),qr=bt(qr=_r.contains)&&qr,Fr=bt(Fr=gr.create)&&Fr,Br=bt(Br=ir.isArray)&&Br,Lr=r.isFinite,Wr=r.isNaN,zr=bt(zr=gr.keys)&&zr,Kr=pr.max,Mr=pr.min,Vr=r.parseInt,Ur=pr.random,Gr={};Gr[L]=ir,Gr[W]=fr,Gr[z]=lr,Gr[M]=cr,Gr[U]=gr,Gr[V]=sr,Gr[G]=hr,Gr[H]=vr;var Hr={};Hr[L]=Hr[z]=Hr[V]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Hr[W]=Hr[H]={constructor:true,toString:true,valueOf:true},Hr[K]=Hr[M]=Hr[G]={constructor:true,toString:true},Hr[U]={constructor:true},function(){for(var n=F.length;n--;){var t,r=F[n]; +for(t in Hr)Ar.call(Hr,t)&&!Ar.call(Hr[t],r)&&(Hr[t][r]=false)}}(),y.prototype=v.prototype;var Jr=v.support={};!function(){var n=function(){this.x=1},t={0:1,length:1},e=[];n.prototype={valueOf:1,y:1};for(var u in new n)e.push(u);for(u in arguments);Jr.argsClass=xr.call(arguments)==B,Jr.argsObject=arguments.constructor==gr&&!(arguments instanceof ir),Jr.enumErrorProps=Rr.call(dr,"message")||Rr.call(dr,"name"),Jr.enumPrototypes=Rr.call(n,"prototype"),Jr.funcDecomp=!bt(r.WinRTError)&&D.test(g),Jr.funcNames=typeof cr.name=="string",Jr.nonEnumArgs=0!=u,Jr.nonEnumShadows=!/valueOf/.test(e),Jr.ownLast="x"!=e[0],Jr.spliceObjects=(mr.splice.call(t,0,1),!t[0]),Jr.unindexedChars="xx"!="x"[0]+gr("x")[0]; +try{Jr.dom=11===wr.createDocumentFragment().nodeType}catch(o){Jr.dom=false}try{Jr.nodeClass=!(xr.call(undefined)==U&&!({toString:0}+""))}catch(a){Jr.nodeClass=true}}(1),v.templateSettings={escape:S,evaluate:I,interpolate:A,variable:"",imports:{_:v}},Fr||(et=function(){function n(){}return function(t){if(At(t)){n.prototype=t;var e=new n;n.prototype=null}return e||r.Object()}}());var Qr=$r?function(n,t){X.value=t,$r(n,"__bindData__",X)}:ur;Jr.argsClass||(jt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ar.call(n,"callee")&&!Rr.call(n,"callee")||false +});var Xr=Br||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&xr.call(n)==L||false},Yr=yt({a:"p",b:"[]",e:"",c:"s.push(l)",f:true}),Zr=zr?function(n){return At(n)?Jr.enumPrototypes&&typeof n=="function"||Jr.nonEnumArgs&&n.length&&jt(n)?Yr(n):zr(n):[]}:Yr,ne=yt({a:"p,b,x",b:"p",e:"b=b&&typeof x=='undefined'?b:a(b,x,3)",c:"if(b(p[l],l,p)===false){return s}",f:false});Jr.dom||(St=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!te(n)||false}),It(/x/)&&(It=function(n){return typeof n=="function"&&xr.call(n)==M +});var te=Ir?function(n){if(!n||xr.call(n)!=U||!Jr.argsClass&&jt(n))return false;var t=n.valueOf,r=bt(t)&&(r=Ir(t))&&Ir(r);return r?n==r||Ir(n)==r:_t(n)}:_t,re=ht(function(n,t,r){Ar.call(n,r)?n[r]++:n[r]=1}),ee=ht(function(n,t,r){(Ar.call(n,r)?n[r]:n[r]=[]).push(t)}),ue=ht(function(n,t,r){n[r]=t}),oe=Lt,ae=bt(ae=lr.now)&&ae||function(){return(new lr).getTime()},ie=8==Vr(w+"08")?Vr:function(n,t){return Vr(Rt(n)?n.replace(T,""):n,t||0)};return v.after=function(n,t){if(!It(t))throw new yr;return function(){return 1>--n?t.apply(this,arguments):void 0 +}},v.assign=xt,v.at=function(n){var t=arguments,r=-1,e=lt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ir(t);for(Jr.unindexedChars&&Rt(n)&&(n=n.split(""));++r=b&&o(e?r[e]:s)))}var l=r[0],h=-1,v=l?l.length:0,y=[];n:for(;++h(m?t(m,g):f(s,g))){for(e=u,(m||s).push(g);--e;)if(m=a[e],0>(m?t(m,g):f(r[e],g)))continue n;y.push(g)}}for(;u--;)(m=a[u])&&p(m);return c(a),c(s),y},v.invert=function(n,t){for(var r=-1,e=Zr(n),u=e.length,o={};++rr?Kr(0,e+r):Mr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},v.mixin=er,v.noConflict=function(){return r._=jr,this},v.noop=ur,v.now=ae,v.parseInt=ie,v.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(typeof n=="boolean"&&u?(r=n,n=1):u||typeof t!="boolean"||(r=t,u=true)),e&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Ur(),Mr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) +},v.reduce=zt,v.reduceRight=Kt,v.result=function(n,t){if(n){var r=n[t];return It(r)?n[t]():r}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Zr(n).length},v.some=Vt,v.sortedIndex=Jt,v.template=function(n,t,r){var e=v.templateSettings;n=vr(n||""),r=Ct({},r,e);var u,o=Ct({},r.imports,e.imports),e=Zr(o),o=Tt(o),i=0,f=r.interpolate||P,l="__p+='",f=hr((r.escape||P).source+"|"+f.source+"|"+(f===A?k:P).source+"|"+(r.evaluate||P).source+"|$","g");n.replace(f,function(t,r,e,o,f,c){return e||(e=o),l+=n.slice(i,c).replace($,a),r&&(l+="'+__e("+r+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t +}),l+="';",f=r=r.variable,f||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(j,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(f?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=cr(e,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},v.unescape=function(n){return null==n?"":(n=vr(n),0>n.indexOf(";")?n:n.replace(N,wt))},v.uniqueId=function(n){var t=++m; +return vr(null==n?"":n)+t},v.all=Dt,v.any=Vt,v.detect=qt,v.findWhere=qt,v.foldl=zt,v.foldr=Kt,v.include=Pt,v.inject=zt,er(function(){var n={};return kt(v,function(t,r){v.prototype[r]||(n[r]=t)}),n}(),false),v.first=Ut,v.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:h;return s(n,Kr(0,u-e))},v.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Tt(n):Jr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[st(0,n.length-1)]:h:(n=Mt(n),n.length=Mr(Kr(0,t),n.length),n) +},v.take=Ut,v.head=Ut,kt(v,function(n,t){var r="sample"!==t;v.prototype[t]||(v.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new y(o,u):o})}),v.VERSION="2.4.1",v.prototype.chain=function(){return this.__chain__=true,this},v.prototype.toString=function(){return vr(this.__wrapped__)},v.prototype.value=ar,v.prototype.valueOf=ar,ft(["join","pop","shift"],function(n){var t=mr[n];v.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new y(r,n):r}}),ft(["push","reverse","sort","unshift"],function(n){var t=mr[n];v.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ft(["concat","slice","splice"],function(n){var t=mr[n];v.prototype[n]=function(){return new y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Jr.spliceObjects||ft(["pop","shift","splice"],function(n){var t=mr[n],r="splice"==n;v.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new y(u,n):u }}),v}var h,v=[],y=[],m=0,d=+new Date+"",b=75,_=40,w=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",j=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,k=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,O=/\w*$/,E=/^\s*function[ \n\r\t]+\w/,S=/<%-([\s\S]+?)%>/g,I=/<%([\s\S]+?)%>/g,A=/<%=([\s\S]+?)%>/g,N=/&(?:amp|lt|gt|quot|#39);/g,R=/[&<>"']/g,T=RegExp("^["+w+"]*0+(?=.$)"),P=/($^)/,D=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),F="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),B="[object Arguments]",L="[object Array]",W="[object Boolean]",z="[object Date]",K="[object Error]",M="[object Function]",V="[object Number]",U="[object Object]",G="[object RegExp]",H="[object String]",J={}; J[M]=false,J[B]=J[L]=J[W]=J[z]=J[V]=J[U]=J[G]=J[H]=true;var Q={leading:false,maxWait:0,trailing:false},X={configurable:false,enumerable:false,value:null,writable:false},Y={"&":"&","<":"<",">":">",'"':""","'":"'"},Z={"&":"&","<":"<",">":">",""":'"',"'":"'"},nt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},tt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},rt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof global]&&global; !ut||ut.global!==ut&&ut.window!==ut||(rt=ut);var ot=(ut=nt[typeof module]&&module&&!module.nodeType&&module)&&ut.exports===et&&et,at=g();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(rt._=at, define(function(){return at})):et&&ut?ot?(ut.exports=at)._=at:et._=at:rt._=at}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 2a0895db87..b480dae339 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -572,12 +572,13 @@ * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `map`, `mapValues`, `max`, `memoize`, `merge`, - * `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `pick`, `pluck`, `property`, `pull`, `push`, `range`, `reject`, `remove`, - * `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, - * `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `where`, `without`, `wrap`, `xor`, and `zip` + * `invert`, `invoke`, `keys`, `map`, `mapValues`, `match`, `max`, `memoize`, + * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, + * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, + * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, + * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, + * and `zip` * * The non-chainable wrapper functions are: * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, @@ -4134,8 +4135,8 @@ } /** - * Performs a deep comparison of each element in a `collection` to the given - * `properties` object, returning an array of all elements that have equivalent + * Performs a deep comparison between each element in `collection` and the + * `props` object, returning an array of all elements that have equivalent * property values. * * @static @@ -5887,34 +5888,8 @@ if (func == null || type == 'function') { return baseCreateCallback(func, thisArg, argCount); } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; - - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; - } - } - return result; - }; + // handle "_.pluck" and "_.where" style callback shorthands + return type != 'object' ? property(func) : match(func); } /** @@ -5956,6 +5931,58 @@ return value; } + /** + * Creates a "_.where" style function, which returns `true` for a given object + * if it has the equivalent property values of the `props` object, else `false`. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} props The object of property values to match. + * @returns {Function} Returns the new function. + * @example + * + * var characters = [ + * { 'name': 'fred', 'age': 40 }, + * { 'name': 'barney', 'age': 36 } + * ]; + * + * var matchAge = _.match({ 'age': 36 }); + * + * _.filter(characters, matchAge); + * // => [{ 'name': 'barney', 'age': 36 }] + * + * _.find(characters, matchAge); + * // => { 'name': 'barney', 'age': 36 } + */ + function match(source) { + source || (source = {}); + + var props = keys(source), + key = props[0], + a = source[key]; + + // fast path the common case of providing an object with a single + // property containing a primitive value + if (props.length == 1 && a === a && !isObject(a)) { + return function(object) { + var b = object[key]; + return a === b && (a !== 0 || (1 / a == 1 / b)); + }; + } + return function(object) { + var length = props.length, + result = false; + + while (length--) { + if (!(result = baseIsEqual(object[props[length]], source[props[length]], null, true))) { + break; + } + } + return result; + }; + } + /** * Adds function properties of a source object to the destination object. * If `object` is a function methods will be added to its prototype as well. @@ -6654,6 +6681,7 @@ lodash.keys = keys; lodash.map = map; lodash.mapValues = mapValues; + lodash.match = match; lodash.max = max; lodash.memoize = memoize; lodash.merge = merge; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 2011c2f70a..5219a53b39 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -5,51 +5,52 @@ */ ;(function(){function n(n,t,e){e=(e||0)-1;for(var r=n?n.length:0;++ea||typeof i=="undefined")return 1;if(ie?0:e);++r=b&&i===n,l=[]; -if(f){var p=o(r);p?(i=t,r=p):f=false}for(;++ui(r,p)&&l.push(p);return f&&c(r),l}function at(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r=b&&f===n,g=u||v?a():s;for(v&&(g=o(g),f=t);++if(g,y))&&((u||v)&&g.push(y),s.push(h)) -}return v?(l(g.g),c(g)):u&&l(g),s}function st(n){return function(t,e,r){var u={};e=d.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r=r)return false;if(typeof n=="string"||!Ve(n)&&It(n))return Se?Se.call(n,t,e):-1e?Be(0,r+e):e)||0,-1e?0:e);++r=b&&i===n,l=[]; +if(f){var p=o(r);p?(i=t,r=p):f=false}for(;++ui(r,p)&&l.push(p);return f&&c(r),l}function at(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r=b&&f===n,v=u||h?a():s;for(h&&(v=o(v),f=t);++if(v,y))&&((u||h)&&v.push(y),s.push(g)) +}return h?(l(v.g),c(v)):u&&l(v),s}function st(n){return function(t,e,r){var u={};e=d.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r=r)return false;if(typeof n=="string"||!Ue(n)&&It(n))return Te?Te.call(n,t,e):-1e?qe(0,r+e):e)||0,-1o&&(o=a)}}else t=null==t&&It(n)?r:d.createCallback(t,e,3),$t(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Wt(n,t,e,r){if(!n)return e;var u=3>arguments.length;t=d.createCallback(t,r,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(e=n[++o]);++oarguments.length;return t=d.createCallback(t,r,4),Ft(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) -}),e}function Pt(n){var t=-1,e=n?n.length:0,r=re(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?Be(0,u+r):r||0}else if(r)return r=Ut(t,e),t[r]===e?r:-1;return n(t,e,r)}function Vt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=d.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=v;m?(i&&(i=we(i)),s=f,a=n.apply(l,o)):i||(i=Ee(r,v))}return m&&c?c=we(c):c||t===g||(c=Ee(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Yt(n){return n}function Zt(n,t,e){var r=true,u=t&&xt(t); -t&&(e||u.length)||(null==e&&(e=t),o=Y,t=n,n=d,u=xt(t)),false===e?r=false:Et(e)&&"chain"in e&&(r=e.chain);var o=n,i=Ot(o);$t(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(Oe.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&Et(i))return this;i=new o(i),i.__chain__=t}return i})})}function ne(){}function te(n){return function(t){return t[n]}}function ee(){return this.__wrapped__}e=e?rt.defaults(Z.Object(),e,rt.pick(Z,F)):Z;var re=e.Array,ue=e.Boolean,oe=e.Date,ie=e.Function,ae=e.Math,fe=e.Number,le=e.Object,ce=e.RegExp,pe=e.String,se=e.TypeError,ve=[],ge=le.prototype,he=pe.prototype,ye=(ye=e.window)&&ye.document,me=e._,be=ge.toString,de=ce("^"+pe(be).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),_e=ae.ceil,we=e.clearTimeout,je=ae.floor,ke=ie.prototype.toString,xe=yt(xe=le.getPrototypeOf)&&xe,Ce=ge.hasOwnProperty,Oe=ve.push,Ee=e.setTimeout,Ne=ve.splice,Ie=ve.unshift,Re=function(){try{var n={},t=yt(t=le.defineProperty)&&t,e=t(n,n,n)&&t -}catch(r){}return e}(),Se=yt(Se=he.contains)&&Se,Te=yt(Te=le.create)&&Te,Ae=yt(Ae=re.isArray)&&Ae,De=e.isFinite,$e=e.isNaN,Fe=yt(Fe=le.keys)&&Fe,Be=ae.max,qe=ae.min,We=e.parseInt,ze=ae.random,Pe={};Pe[q]=re,Pe[W]=ue,Pe[z]=oe,Pe[P]=ie,Pe[L]=le,Pe[K]=fe,Pe[M]=ce,Pe[V]=pe,Y.prototype=d.prototype;var Ke=d.support={};Ke.funcDecomp=!yt(e.WinRTError)&&D.test(s),Ke.funcNames=typeof ie.name=="string";try{Ke.dom=11===ye.createDocumentFragment().nodeType}catch(Le){Ke.dom=false}d.templateSettings={escape:E,evaluate:N,interpolate:I,variable:"",imports:{_:d}},Te||(et=function(){function n(){}return function(t){if(Et(t)){n.prototype=t; -var r=new n;n.prototype=null}return r||e.Object()}}());var Me=Re?function(n,t){H.value=t,Re(n,"__bindData__",H)}:ne,Ve=Ae||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&be.call(n)==q||false},Ue=Fe?function(n){return Et(n)?Fe(n):[]}:h;Ke.dom||(Ct=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!Ge(n)||false});var Ge=xe?function(n){if(!n||be.call(n)!=L)return false;var t=n.valueOf,e=yt(t)&&(e=xe(t))&&xe(e);return e?n==e||xe(n)==e:mt(n)}:mt,He=st(function(n,t,e){Ce.call(n,e)?n[e]++:n[e]=1 -}),Je=st(function(n,t,e){(Ce.call(n,e)?n[e]:n[e]=[]).push(t)}),Qe=st(function(n,t,e){n[e]=t}),Xe=Bt,Ye=yt(Ye=oe.now)&&Ye||function(){return(new oe).getTime()},Ze=8==We(_+"08")?We:function(n,t){return We(It(n)?n.replace(T,""):n,t||0)};return d.after=function(n,t){if(!Ot(t))throw new se;return function(){return 1>--n?t.apply(this,arguments):void 0}},d.assign=_t,d.at=function(n){for(var t=arguments,e=-1,r=at(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=re(t);++e=b&&o(r?e[r]:s))) -}var p=e[0],g=-1,h=p?p.length:0,y=[];n:for(;++g(m?t(m,v):f(s,v))){for(r=u,(m||s).push(v);--r;)if(m=i[r],0>(m?t(m,v):f(e[r],v)))continue n;y.push(v)}}for(;u--;)(m=i[u])&&c(m);return l(i),l(s),y},d.invert=function(n,t){for(var e=-1,r=Ue(n),u=r.length,o={};++ee?Be(0,r+e):qe(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},d.mixin=Zt,d.noConflict=function(){return e._=me,this},d.noop=ne,d.now=Ye,d.parseInt=Ze,d.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=ze(),qe(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t) -},d.reduce=Wt,d.reduceRight=zt,d.result=function(n,t){if(n){var e=n[t];return Ot(e)?n[t]():e}},d.runInContext=s,d.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Ue(n).length},d.some=Kt,d.sortedIndex=Ut,d.template=function(n,t,e){var r=d.templateSettings;n=pe(n||""),e=wt({},e,r);var u,o=wt({},e.imports,r.imports),r=Ue(o),o=Rt(o),a=0,f=e.interpolate||A,l="__p+='",f=ce((e.escape||A).source+"|"+f.source+"|"+(f===I?x:A).source+"|"+(e.evaluate||A).source+"|$","g");n.replace(f,function(t,e,r,o,f,c){return r||(r=o),l+=n.slice(a,c).replace($,i),e&&(l+="'+__e("+e+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t -}),l+="';",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(w,""):l).replace(j,"$1").replace(k,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=ie(r,"return "+l).apply(v,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},d.unescape=function(n){return null==n?"":(n=pe(n),0>n.indexOf(";")?n:n.replace(R,bt))},d.uniqueId=function(n){var t=++y; -return pe(null==n?"":n)+t},d.all=Tt,d.any=Kt,d.detect=Dt,d.findWhere=Dt,d.foldl=Wt,d.foldr=zt,d.include=St,d.inject=Wt,Zt(function(){var n={};return jt(d,function(t,e){d.prototype[e]||(n[e]=t)}),n}(),false),d.first=Lt,d.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=d.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:v;return p(n,Be(0,u-r))},d.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Rt(n)),null==t||e?n?n[ct(0,n.length-1)]:v:(n=Pt(n),n.length=qe(Be(0,t),n.length),n) -},d.take=Lt,d.head=Lt,jt(d,function(n,t){var e="sample"!==t;d.prototype[t]||(d.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new Y(o,u):o})}),d.VERSION="2.4.1",d.prototype.chain=function(){return this.__chain__=true,this},d.prototype.toString=function(){return pe(this.__wrapped__)},d.prototype.value=ee,d.prototype.valueOf=ee,$t(["join","pop","shift"],function(n){var t=ve[n];d.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments); -return n?new Y(e,n):e}}),$t(["push","reverse","sort","unshift"],function(n){var t=ve[n];d.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),$t(["concat","slice","splice"],function(n){var t=ve[n];d.prototype[n]=function(){return new Y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),d}var v,g=[],h=[],y=0,m=+new Date+"",b=75,d=40,_=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",w=/\b__p\+='';/g,j=/\b(__p\+=)''\+/g,k=/(__e\(.*?\)|\b__t\))\+'';/g,x=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,C=/\w*$/,O=/^\s*function[ \n\r\t]+\w/,E=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,R=/&(?:amp|lt|gt|quot|#39);/g,S=/[&<>"']/g,T=RegExp("^["+_+"]*0+(?=.$)"),A=/($^)/,D=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,F="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),B="[object Arguments]",q="[object Array]",W="[object Boolean]",z="[object Date]",P="[object Function]",K="[object Number]",L="[object Object]",M="[object RegExp]",V="[object String]",U={}; +}),e}function Pt(n){var t=-1,e=n?n.length:0,r=ue(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?qe(0,u+r):r||0}else if(r)return r=Ut(t,e),t[r]===e?r:-1;return n(t,e,r)}function Vt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=d.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=h;m?(i&&(i=je(i)),s=f,a=n.apply(l,o)):i||(i=Ne(r,h))}return m&&c?c=je(c):c||t===v||(c=Ne(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Yt(n){return n}function Zt(n){n||(n={});var t=Ge(n),e=t[0],r=n[e]; +return 1!=t.length||r!==r||Et(r)?function(e){for(var r=t.length,u=false;r--&&(u=ft(e[t[r]],n[t[r]],null,true)););return u}:function(n){return n=n[e],r===n&&(0!==r||1/r==1/n)}}function ne(n,t,e){var r=true,u=t&&xt(t);t&&(e||u.length)||(null==e&&(e=t),o=Y,t=n,n=d,u=xt(t)),false===e?r=false:Et(e)&&"chain"in e&&(r=e.chain);var o=n,i=Ot(o);$t(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(Ee.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&Et(i))return this; +i=new o(i),i.__chain__=t}return i})})}function te(){}function ee(n){return function(t){return t[n]}}function re(){return this.__wrapped__}e=e?rt.defaults(Z.Object(),e,rt.pick(Z,F)):Z;var ue=e.Array,oe=e.Boolean,ie=e.Date,ae=e.Function,fe=e.Math,le=e.Number,ce=e.Object,pe=e.RegExp,se=e.String,he=e.TypeError,ve=[],ge=ce.prototype,ye=se.prototype,me=(me=e.window)&&me.document,be=e._,de=ge.toString,_e=pe("^"+se(de).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),we=fe.ceil,je=e.clearTimeout,ke=fe.floor,xe=ae.prototype.toString,Ce=yt(Ce=ce.getPrototypeOf)&&Ce,Oe=ge.hasOwnProperty,Ee=ve.push,Ne=e.setTimeout,Ie=ve.splice,Re=ve.unshift,Se=function(){try{var n={},t=yt(t=ce.defineProperty)&&t,e=t(n,n,n)&&t +}catch(r){}return e}(),Te=yt(Te=ye.contains)&&Te,Ae=yt(Ae=ce.create)&&Ae,De=yt(De=ue.isArray)&&De,$e=e.isFinite,Fe=e.isNaN,Be=yt(Be=ce.keys)&&Be,qe=fe.max,We=fe.min,ze=e.parseInt,Pe=fe.random,Ke={};Ke[q]=ue,Ke[W]=oe,Ke[z]=ie,Ke[P]=ae,Ke[L]=ce,Ke[K]=le,Ke[M]=pe,Ke[V]=se,Y.prototype=d.prototype;var Le=d.support={};Le.funcDecomp=!yt(e.WinRTError)&&D.test(s),Le.funcNames=typeof ae.name=="string";try{Le.dom=11===me.createDocumentFragment().nodeType}catch(Me){Le.dom=false}d.templateSettings={escape:E,evaluate:N,interpolate:I,variable:"",imports:{_:d}},Ae||(et=function(){function n(){}return function(t){if(Et(t)){n.prototype=t; +var r=new n;n.prototype=null}return r||e.Object()}}());var Ve=Se?function(n,t){H.value=t,Se(n,"__bindData__",H)}:te,Ue=De||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&de.call(n)==q||false},Ge=Be?function(n){return Et(n)?Be(n):[]}:g;Le.dom||(Ct=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!He(n)||false});var He=Ce?function(n){if(!n||de.call(n)!=L)return false;var t=n.valueOf,e=yt(t)&&(e=Ce(t))&&Ce(e);return e?n==e||Ce(n)==e:mt(n)}:mt,Je=st(function(n,t,e){Oe.call(n,e)?n[e]++:n[e]=1 +}),Qe=st(function(n,t,e){(Oe.call(n,e)?n[e]:n[e]=[]).push(t)}),Xe=st(function(n,t,e){n[e]=t}),Ye=Bt,Ze=yt(Ze=ie.now)&&Ze||function(){return(new ie).getTime()},nr=8==ze(_+"08")?ze:function(n,t){return ze(It(n)?n.replace(T,""):n,t||0)};return d.after=function(n,t){if(!Ot(t))throw new he;return function(){return 1>--n?t.apply(this,arguments):void 0}},d.assign=_t,d.at=function(n){for(var t=arguments,e=-1,r=at(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=ue(t);++e=b&&o(r?e[r]:s)))}var p=e[0],v=-1,g=p?p.length:0,y=[];n:for(;++v(m?t(m,h):f(s,h))){for(r=u,(m||s).push(h);--r;)if(m=i[r],0>(m?t(m,h):f(e[r],h)))continue n;y.push(h) +}}for(;u--;)(m=i[u])&&c(m);return l(i),l(s),y},d.invert=function(n,t){for(var e=-1,r=Ge(n),u=r.length,o={};++ee?qe(0,r+e):We(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},d.mixin=ne,d.noConflict=function(){return e._=be,this},d.noop=te,d.now=Ze,d.parseInt=nr,d.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Pe(),We(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t) +},d.reduce=Wt,d.reduceRight=zt,d.result=function(n,t){if(n){var e=n[t];return Ot(e)?n[t]():e}},d.runInContext=s,d.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Ge(n).length},d.some=Kt,d.sortedIndex=Ut,d.template=function(n,t,e){var r=d.templateSettings;n=se(n||""),e=wt({},e,r);var u,o=wt({},e.imports,r.imports),r=Ge(o),o=Rt(o),a=0,f=e.interpolate||A,l="__p+='",f=pe((e.escape||A).source+"|"+f.source+"|"+(f===I?x:A).source+"|"+(e.evaluate||A).source+"|$","g");n.replace(f,function(t,e,r,o,f,c){return r||(r=o),l+=n.slice(a,c).replace($,i),e&&(l+="'+__e("+e+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t +}),l+="';",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(w,""):l).replace(j,"$1").replace(k,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=ae(r,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},d.unescape=function(n){return null==n?"":(n=se(n),0>n.indexOf(";")?n:n.replace(R,bt))},d.uniqueId=function(n){var t=++y; +return se(null==n?"":n)+t},d.all=Tt,d.any=Kt,d.detect=Dt,d.findWhere=Dt,d.foldl=Wt,d.foldr=zt,d.include=St,d.inject=Wt,ne(function(){var n={};return jt(d,function(t,e){d.prototype[e]||(n[e]=t)}),n}(),false),d.first=Lt,d.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=d.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:h;return p(n,qe(0,u-r))},d.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Rt(n)),null==t||e?n?n[ct(0,n.length-1)]:h:(n=Pt(n),n.length=We(qe(0,t),n.length),n) +},d.take=Lt,d.head=Lt,jt(d,function(n,t){var e="sample"!==t;d.prototype[t]||(d.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new Y(o,u):o})}),d.VERSION="2.4.1",d.prototype.chain=function(){return this.__chain__=true,this},d.prototype.toString=function(){return se(this.__wrapped__)},d.prototype.value=re,d.prototype.valueOf=re,$t(["join","pop","shift"],function(n){var t=ve[n];d.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments); +return n?new Y(e,n):e}}),$t(["push","reverse","sort","unshift"],function(n){var t=ve[n];d.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),$t(["concat","slice","splice"],function(n){var t=ve[n];d.prototype[n]=function(){return new Y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),d}var h,v=[],g=[],y=0,m=+new Date+"",b=75,d=40,_=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",w=/\b__p\+='';/g,j=/\b(__p\+=)''\+/g,k=/(__e\(.*?\)|\b__t\))\+'';/g,x=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,C=/\w*$/,O=/^\s*function[ \n\r\t]+\w/,E=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,R=/&(?:amp|lt|gt|quot|#39);/g,S=/[&<>"']/g,T=RegExp("^["+_+"]*0+(?=.$)"),A=/($^)/,D=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,F="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),B="[object Arguments]",q="[object Array]",W="[object Boolean]",z="[object Date]",P="[object Function]",K="[object Number]",L="[object Object]",M="[object RegExp]",V="[object String]",U={}; U[P]=false,U[B]=U[q]=U[W]=U[z]=U[K]=U[L]=U[M]=U[V]=true;var G={leading:false,maxWait:0,trailing:false},H={configurable:false,enumerable:false,value:null,writable:false},J={"&":"&","<":"<",">":">",'"':""","'":"'"},Q={"&":"&","<":"<",">":">",""":'"',"'":"'"},X={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},Y={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},Z=X[typeof window]&&window||this,nt=X[typeof exports]&&exports&&!exports.nodeType&&exports,tt=X[typeof global]&&global; !tt||tt.global!==tt&&tt.window!==tt||(Z=tt);var et=(tt=X[typeof module]&&module&&!module.nodeType&&module)&&tt.exports===nt&&nt,rt=s();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Z._=rt, define(function(){return rt})):nt&&tt?et?(tt.exports=rt)._=rt:nt._=rt:Z._=rt}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 914a456faf..3d19d71129 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -275,12 +275,13 @@ * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `map`, `mapValues`, `max`, `memoize`, `merge`, - * `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `pick`, `pluck`, `property`, `pull`, `push`, `range`, `reject`, `remove`, - * `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, - * `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `where`, `without`, `wrap`, `xor`, and `zip` + * `invert`, `invoke`, `keys`, `map`, `mapValues`, `match`, `max`, `memoize`, + * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, + * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, + * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, + * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, + * and `zip` * * The non-chainable wrapper functions are: * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, @@ -2880,8 +2881,8 @@ } /** - * Performs a deep comparison of each element in a `collection` to the given - * `properties` object, returning an array of all elements that have equivalent + * Performs a deep comparison between each element in `collection` and the + * `props` object, returning an array of all elements that have equivalent * property values. * * @static @@ -4256,22 +4257,8 @@ if (func == null || type == 'function') { return baseCreateCallback(func, thisArg, argCount); } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func); - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = object[props[length]] === func[props[length]])) { - break; - } - } - return result; - }; + // handle "_.pluck" and "_.where" style callback shorthands + return type != 'object' ? property(func) : match(func); } /** @@ -4313,6 +4300,47 @@ return value; } + /** + * Creates a "_.where" style function, which returns `true` for a given object + * if it has the equivalent property values of the `props` object, else `false`. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} props The object of property values to match. + * @returns {Function} Returns the new function. + * @example + * + * var characters = [ + * { 'name': 'fred', 'age': 40 }, + * { 'name': 'barney', 'age': 36 } + * ]; + * + * var matchAge = _.match({ 'age': 36 }); + * + * _.filter(characters, matchAge); + * // => [{ 'name': 'barney', 'age': 36 }] + * + * _.find(characters, matchAge); + * // => { 'name': 'barney', 'age': 36 } + */ + function match(source) { + source || (source = {}); + + var props = keys(source); + return function(object) { + var length = props.length, + result = false; + + while (length--) { + if (!(result = object[props[length]] === source[props[length]])) { + break; + } + } + return result; + }; + } + /** * Adds function properties of a source object to the destination object. * If `object` is a function methods will be added to its prototype as well. diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index fc16953eb6..f9dd4d27ee 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -3,37 +3,37 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js` */ -;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++tf||typeof i=="undefined")return 1;if(it?0:t);++ee(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(t&&f.push(l),i.push(a))}return i}function h(n){return function(r,t,e){var u={};t=X(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++eu&&(u=t); -else r=X(r,t,3),$(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function W(n,r,t,e){if(!n)return t;var u=3>arguments.length;r=X(r,e,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(t=n[++o]);++oarguments.length;return r=X(r,e,4),D(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return $(n,function(n){var t;t=++r,t=0+Fr(Vr()*(t-0+1)),e[r]=e[t],e[t]=n -}),e}function P(n,r,t){var e;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++te?Pr(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1; -return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o>>1,t(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;if(null==n||"function"==e)return a(n,r,t);if("object"!=e)return nr(n);var u=Kr(n);return function(r){for(var t=u.length,e=false;t--&&(e=r[u[t]]===n[u[t]]););return e}}function Y(n){return n}function Z(n){$(T(n),function(r){var t=u[r]=n[r];u.prototype[r]=function(){var n=[this.__wrapped__]; -return $r.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function nr(n){return function(r){return r[n]}}var rr,tr=0,er={},ur=+new Date+"",or=/&(?:amp|lt|gt|quot|#x27);/g,ir=/[&<>"']/g,fr=/($^)/,ar=/['\n\r\t\u2028\u2029\\]/g,lr="[object Arguments]",cr="[object Array]",pr="[object Boolean]",sr="[object Date]",gr="[object Number]",hr="[object Object]",vr="[object RegExp]",yr="[object String]",mr={"&":"&","<":"<",">":">",'"':""","'":"'"},_r={"&":"&","<":"<",">":">",""":'"',"'":"'"},dr={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},br={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},wr=dr[typeof window]&&window||this,jr=dr[typeof exports]&&exports&&!exports.nodeType&&exports,xr=dr[typeof global]&&global; -!xr||xr.global!==xr&&xr.window!==xr||(wr=xr);var Tr=dr[typeof module]&&module&&!module.nodeType&&module,Ar=Tr&&Tr.exports===jr&&jr,Er=[],Or=Object.prototype,Sr=wr._,kr=Or.toString,Nr=RegExp("^"+(kr+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),qr=Math.ceil,Fr=Math.floor,Br=Function.prototype.toString,Rr=Or.hasOwnProperty,$r=Er.push,Dr=Or.propertyIsEnumerable,Ir=_(Ir=Object.create)&&Ir,Mr=_(Mr=Array.isArray)&&Mr,Wr=wr.isFinite,zr=wr.isNaN,Cr=_(Cr=Object.keys)&&Cr,Pr=Math.max,Ur=Math.min,Vr=Math.random; -o.prototype=u.prototype;var Gr={};!function(){var n={0:1,length:1};Gr.spliceObjects=(Er.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Ir||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||wr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Rr.call(n,"callee")&&!Dr.call(n,"callee")||false});var Hr=Mr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&kr.call(n)==cr||false -},Jr=function(n){var r=[];if(!n||!dr[typeof n])return r;for(var t in n)Rr.call(n,t)&&r.push(t);return r},Kr=Cr?function(n){return O(n)?Cr(n):[]}:Jr,Lr=function(n,r){if(!n||!dr[typeof n])return n;for(var t in n)if(r(n[t],t,n)===er)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==kr.call(n)});var Qr=h(function(n,r,t){Rr.call(n,t)?n[t]++:n[t]=1}),Xr=h(function(n,r,t){(Rr.call(n,t)?n[t]:n[t]=[]).push(r)}),Yr=h(function(n,r,t){n[t]=r}),Zr=I,nt=_(nt=Date.now)&&nt||function(){return(new Date).getTime() +;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++tf||typeof i=="undefined")return 1;if(it?0:t);++ee(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(t&&f.push(l),i.push(a))}return i}function h(n){return function(r,t,e){var u={};t=X(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++eu&&(u=t); +else r=X(r,t,3),$(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function W(n,r,t,e){if(!n)return t;var u=3>arguments.length;r=X(r,e,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(t=n[++o]);++oarguments.length;return r=X(r,e,4),D(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return $(n,function(n){var t;t=++r,t=0+Br(Gr()*(t-0+1)),e[r]=e[t],e[t]=n +}),e}function P(n,r,t){var e;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++te?Ur(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1; +return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o>>1,t(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;return null==n||"function"==e?a(n,r,t):"object"!=e?rr(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var r=Lr(n);return function(t){for(var e=r.length,u=false;e--&&(u=t[r[e]]===n[r[e]]););return u}}function nr(n){$(T(n),function(r){var t=u[r]=n[r]; +u.prototype[r]=function(){var n=[this.__wrapped__];return Dr.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function rr(n){return function(r){return r[n]}}var tr,er=0,ur={},or=+new Date+"",ir=/&(?:amp|lt|gt|quot|#x27);/g,fr=/[&<>"']/g,ar=/($^)/,lr=/['\n\r\t\u2028\u2029\\]/g,cr="[object Arguments]",pr="[object Array]",sr="[object Boolean]",gr="[object Date]",hr="[object Number]",vr="[object Object]",yr="[object RegExp]",mr="[object String]",_r={"&":"&","<":"<",">":">",'"':""","'":"'"},dr={"&":"&","<":"<",">":">",""":'"',"'":"'"},br={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},wr={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},jr=br[typeof window]&&window||this,xr=br[typeof exports]&&exports&&!exports.nodeType&&exports,Tr=br[typeof global]&&global; +!Tr||Tr.global!==Tr&&Tr.window!==Tr||(jr=Tr);var Ar=br[typeof module]&&module&&!module.nodeType&&module,Er=Ar&&Ar.exports===xr&&xr,Or=[],Sr=Object.prototype,kr=jr._,Nr=Sr.toString,qr=RegExp("^"+(Nr+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Fr=Math.ceil,Br=Math.floor,Rr=Function.prototype.toString,$r=Sr.hasOwnProperty,Dr=Or.push,Ir=Sr.propertyIsEnumerable,Mr=_(Mr=Object.create)&&Mr,Wr=_(Wr=Array.isArray)&&Wr,zr=jr.isFinite,Cr=jr.isNaN,Pr=_(Pr=Object.keys)&&Pr,Ur=Math.max,Vr=Math.min,Gr=Math.random; +o.prototype=u.prototype;var Hr={};!function(){var n={0:1,length:1};Hr.spliceObjects=(Or.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Mr||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||jr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$r.call(n,"callee")&&!Ir.call(n,"callee")||false});var Jr=Wr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n)==pr||false +},Kr=function(n){var r=[];if(!n||!br[typeof n])return r;for(var t in n)$r.call(n,t)&&r.push(t);return r},Lr=Pr?function(n){return O(n)?Pr(n):[]}:Kr,Qr=function(n,r){if(!n||!br[typeof n])return n;for(var t in n)if(r(n[t],t,n)===ur)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nr.call(n)});var Xr=h(function(n,r,t){$r.call(n,t)?n[t]++:n[t]=1}),Yr=h(function(n,r,t){($r.call(n,t)?n[t]:n[t]=[]).push(r)}),Zr=h(function(n,r,t){n[t]=r}),nt=I,rt=_(rt=Date.now)&&rt||function(){return(new Date).getTime() };u.after=function(n,r){if(!E(r))throw new TypeError;return function(){return 1>--n?r.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var r=1i(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},u.invert=function(n,r){for(var t=-1,e=Kr(n),u=e.length,o={};++tr?0:r);++nt?Pr(0,e+t):Ur(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=Z,u.noConflict=function(){return wr._=Sr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Fr(Vr()*(r-n+1)) -},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return E(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Kr(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||fr).source+"|"+(e.interpolate||fr).source+"|"+(e.evaluate||fr).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(ar,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r -}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(or,d))},u.uniqueId=function(n){var r=++tr+"";return n?n+r:r},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0; -if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:rr;return e(n,Pr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=N(n)),null==r||t?n?n[0+Fr(Vr()*(n.length-1-0+1))]:rr:(n=C(n),n.length=Ur(Pr(0,r),n.length),n)},u.take=V,u.head=V,Z(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var r=Er[n]; -u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Gr.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var r=Er[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(wr._=u, define(function(){return u})):jr&&Tr?Ar?(Tr.exports=u)._=u:jr._=u:wr._=u}).call(this); \ No newline at end of file +return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}},u.countBy=Xr,u.debounce=Q,u.defaults=j,u.defer=function(n){if(!E(n))throw new TypeError;var r=e(arguments,1);return setTimeout(function(){n.apply(tr,r)},1)},u.delay=function(n,r){if(!E(n))throw new TypeError;var t=e(arguments,2);return setTimeout(function(){n.apply(tr,t)},r)},u.difference=function(n){return c(n,p(arguments,true,true,1))},u.filter=B,u.flatten=function(n,r){return p(n,r)},u.forEach=$,u.functions=T,u.groupBy=Yr,u.indexBy=Zr,u.initial=function(n,r,t){var u=0,o=n?n.length:0; +if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else u=null==r||t?1:r||u;return e(n,0,Vr(Ur(0,o-u),o))},u.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},u.invert=function(n,r){for(var t=-1,e=Lr(n),u=e.length,o={};++tr?0:r);++nt?Ur(0,e+t):Vr(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=nr,u.noConflict=function(){return jr._=kr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Br(Gr()*(r-n+1)) +},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return E(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Lr(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||ar).source+"|"+(e.interpolate||ar).source+"|"+(e.evaluate||ar).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(lr,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r +}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(ir,d))},u.uniqueId=function(n){var r=++er+"";return n?n+r:r},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0; +if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:tr;return e(n,Ur(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=N(n)),null==r||t?n?n[0+Br(Gr()*(n.length-1-0+1))]:tr:(n=C(n),n.length=Vr(Ur(0,r),n.length),n)},u.take=V,u.head=V,nr(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var r=Or[n]; +u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Hr.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var r=Or[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jr._=u, define(function(){return u})):xr&&Ar?Er?(Ar.exports=u)._=u:xr._=u:jr._=u}).call(this); \ No newline at end of file diff --git a/doc/README.md b/doc/README.md index 15c5da705f..f909998210 100644 --- a/doc/README.md +++ b/doc/README.md @@ -176,6 +176,7 @@ * `_.createCallback` * `_.escape` * `_.identity` +* `_.match` * `_.mixin` * `_.noConflict` * `_.noop` @@ -239,7 +240,7 @@ ### `_.compact(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4508 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4515 "View in source") [Ⓣ][1] Creates an array with all falsey values removed. The values `false`, `null`, `0`, `""`, `undefined`, and `NaN` are all falsey. @@ -263,7 +264,7 @@ _.compact([0, 1, false, 2, '', 3]); ### `_.difference(array, [values])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4538 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4545 "View in source") [Ⓣ][1] Creates an array excluding all values of the provided arrays using strict equality for comparisons, i.e. `===`. @@ -288,7 +289,7 @@ _.difference([1, 2, 3, 4, 5], [5, 2, 10]); ### `_.findIndex(array, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4583 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4590 "View in source") [Ⓣ][1] This method is like `_.find` except that it returns the index of the first element that passes the callback check, instead of the element itself. @@ -334,7 +335,7 @@ _.findIndex(characters, 'blocked'); ### `_.findLastIndex(array, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4637 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4644 "View in source") [Ⓣ][1] This method is like `_.findIndex` except that it iterates over elements of a `collection` from right to left. @@ -380,7 +381,7 @@ _.findLastIndex(characters, 'blocked'); ### `_.first(array, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4701 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4708 "View in source") [Ⓣ][1] Gets the first element or first `n` elements of an array. If a callback is provided elements at the beginning of the array are returned as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -437,7 +438,7 @@ _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); ### `_.flatten(array, [isShallow=false], [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4762 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4769 "View in source") [Ⓣ][1] Flattens a nested array *(the nesting can be to any depth)*. If `isShallow` is truey, the array will only be flattened a single level. If a callback is provided each element of the array is passed through the callback before flattening. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -481,7 +482,7 @@ _.flatten(characters, 'pets'); ### `_.indexOf(array, value, [fromIndex=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4801 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4808 "View in source") [Ⓣ][1] Gets the index at which the first occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If the array is already sorted providing `true` for `fromIndex` will run a faster binary search. @@ -515,7 +516,7 @@ _.indexOf([1, 1, 2, 2, 3, 3], 2, true); ### `_.initial(array, [callback=1], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4864 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4871 "View in source") [Ⓣ][1] Gets all but the last element or last `n` elements of an array. If a callback is provided elements at the end of the array are excluded from the result as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -569,7 +570,7 @@ _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); ### `_.intersection([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4894 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4901 "View in source") [Ⓣ][1] Creates an array of unique values present in all provided arrays using strict equality for comparisons, i.e. `===`. @@ -593,7 +594,7 @@ _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); ### `_.last(array, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4996 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5003 "View in source") [Ⓣ][1] Gets the last element or last `n` elements of an array. If a callback is provided elements at the end of the array are returned as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -647,7 +648,7 @@ _.last(characters, { 'employer': 'na' }); ### `_.lastIndexOf(array, value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5043 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5050 "View in source") [Ⓣ][1] Gets the index at which the last occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the offset from the end of the collection. @@ -681,7 +682,7 @@ _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); ### `_.pull(array, [value])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5073 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5080 "View in source") [Ⓣ][1] Removes all provided values from the given array using strict equality for comparisons, i.e. `===`. @@ -708,7 +709,7 @@ console.log(array); ### `_.range([start=0], end, [step=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5124 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5131 "View in source") [Ⓣ][1] Creates an array of numbers *(positive and/or negative)* progressing from `start` up to but not including `end`. If `start` is less than `stop` a zero-length range is created unless a negative `step` is specified. @@ -749,7 +750,7 @@ _.range(0); ### `_.remove(array, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5177 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5184 "View in source") [Ⓣ][1] Removes all elements from an array that the callback returns truey for and returns an array of removed elements. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -785,7 +786,7 @@ console.log(evens); ### `_.rest(array, [callback=1], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5248 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5255 "View in source") [Ⓣ][1] The opposite of `_.initial`; this method gets all but the first element or first `n` elements of an array. If a callback function is provided elements at the beginning of the array are excluded from the result as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -842,7 +843,7 @@ _.rest(characters, { 'employer': 'slate' }); ### `_.sortedIndex(array, value, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5314 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5321 "View in source") [Ⓣ][1] Uses a binary search to determine the smallest index at which a value should be inserted into a given sorted array in order to maintain the sort order of the array. If a callback is provided it will be executed for `value` and each element of `array` to compute their sort ranking. The callback is bound to `thisArg` and invoked with one argument; *(value)*. @@ -893,7 +894,7 @@ _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); ### `_.union([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5345 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5352 "View in source") [Ⓣ][1] Creates an array of unique values, in order, of the provided arrays using strict equality for comparisons, i.e. `===`. @@ -917,7 +918,7 @@ _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); ### `_.uniq(array, [isSorted=false], [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5396 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5403 "View in source") [Ⓣ][1] Creates a duplicate-value-free version of an array using strict equality for comparisons, i.e. `===`. If the array is sorted, providing `true` for `isSorted` will use a faster algorithm. If a callback is provided each element of `array` is passed through the callback before uniqueness is computed. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -967,7 +968,7 @@ _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); ### `_.without(array, [value])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5424 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5431 "View in source") [Ⓣ][1] Creates an array excluding all provided values using strict equality for comparisons, i.e. `===`. @@ -992,7 +993,7 @@ _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); ### `_.xor([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5445 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5452 "View in source") [Ⓣ][1] Creates an array that is the symmetric difference of the provided arrays. See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. @@ -1019,7 +1020,7 @@ _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); ### `_.zip([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5480 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5487 "View in source") [Ⓣ][1] Creates an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on. If a zipped value is provided its corresponding unzipped value will be returned. @@ -1049,7 +1050,7 @@ _.unzip([['fred', 30, true], ['barney', 40, false]]); ### `_.zipObject(keys, [values=[]])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5510 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5517 "View in source") [Ⓣ][1] Creates an object composed from arrays of `keys` and `values`. Provide either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` or two arrays, one of `keys` and one of corresponding `values`. @@ -1084,7 +1085,7 @@ _.zipObject(['fred', 'barney'], [30, 40]); ### `_(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L638 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L668 "View in source") [Ⓣ][1] Creates a `lodash` object which wraps the given value to enable intuitive method chaining. @@ -1094,7 +1095,7 @@ In addition to Lo-Dash methods, wrappers also have the following `Array` methods Chaining is supported in custom builds as long as the `value` method is implicitly or explicitly included in the build. The chainable wrapper functions are:
    -`after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `mapValues`, `max`, `memoize`, `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, and `zip` +`after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `mapValues`, `match`, `max`, `memoize`, `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, and `zip` The non-chainable wrapper functions are:
    `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `now`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`, `template`, `unescape`, `uniqueId`, and `value` @@ -1139,7 +1140,7 @@ _.isArray(squares.value()); ### `_.chain(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6851 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6884 "View in source") [Ⓣ][1] Creates a `lodash` object that wraps the given value with explicit method chaining enabled. @@ -1173,7 +1174,7 @@ var youngest = _.chain(characters) ### `_.tap(value, interceptor, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6878 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6911 "View in source") [Ⓣ][1] This method invokes `interceptor` and returns `value`. The interceptor is bound to `thisArg` and invoked with one argument; *(value)*. The purpose of this method is to "tap into" a method chain in order to perform operations on intermediate results within the chain. @@ -1202,7 +1203,7 @@ _([1, 2, 3, 4]) ### `_.prototype.chain()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6908 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6941 "View in source") [Ⓣ][1] Enables explicit method chaining on the wrapper object. @@ -1236,7 +1237,7 @@ _(characters).chain() ### `_.prototype.toString()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6925 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6958 "View in source") [Ⓣ][1] Produces the `toString` result of the wrapped value. @@ -1257,7 +1258,7 @@ _([1, 2, 3]).toString(); ### `_.prototype.valueOf()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6942 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6975 "View in source") [Ⓣ][1] Extracts the wrapped value. @@ -1288,7 +1289,7 @@ _([1, 2, 3]).valueOf(); ### `_.at(collection, [index])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3317 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3324 "View in source") [Ⓣ][1] Creates an array of elements from the specified indexes, or keys, of the `collection`. Indexes may be specified as individual arguments or as arrays of indexes. @@ -1316,7 +1317,7 @@ _.at(['fred', 'barney', 'pebbles'], 0, 2); ### `_.contains(collection, target, [fromIndex=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3360 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3367 "View in source") [Ⓣ][1] Checks if a given value is present in a collection using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the offset from the end of the collection. @@ -1354,7 +1355,7 @@ _.contains('pebbles', 'eb'); ### `_.countBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3423 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3430 "View in source") [Ⓣ][1] Creates an object composed of keys generated from the results of running each element of `collection` through the callback. The corresponding value of each key is the number of times the key was returned by the callback. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1390,7 +1391,7 @@ _.countBy(['one', 'two', 'three'], 'length'); ### `_.every(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3468 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3475 "View in source") [Ⓣ][1] Checks if the given callback returns truey value for **all** elements of a collection. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1436,7 +1437,7 @@ _.every(characters, { 'age': 36 }); ### `_.filter(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3529 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3536 "View in source") [Ⓣ][1] Iterates over elements of a collection, returning an array of all elements the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1482,7 +1483,7 @@ _.filter(characters, { 'age': 36 }); ### `_.find(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3596 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3603 "View in source") [Ⓣ][1] Iterates over elements of a collection, returning the first element that the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1531,7 +1532,7 @@ _.find(characters, 'blocked'); ### `_.findLast(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3641 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3648 "View in source") [Ⓣ][1] This method is like `_.find` except that it iterates over elements of a `collection` from right to left. @@ -1559,7 +1560,7 @@ _.findLast([1, 2, 3, 4], function(num) { ### `_.forEach(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3679 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3686 "View in source") [Ⓣ][1] Iterates over elements of a collection, executing the callback for each element. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -1593,7 +1594,7 @@ _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); ### `_.forEachRight(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3712 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3719 "View in source") [Ⓣ][1] This method is like `_.forEach` except that it iterates over elements of a `collection` from right to left. @@ -1622,7 +1623,7 @@ _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); ### `_.groupBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3773 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3780 "View in source") [Ⓣ][1] Creates an object composed of keys generated from the results of running each element of a collection through the callback. The corresponding value of each key is an array of the elements responsible for generating the key. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1659,7 +1660,7 @@ _.groupBy(['one', 'two', 'three'], 'length'); ### `_.indexBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3816 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3823 "View in source") [Ⓣ][1] Creates an object composed of keys generated from the results of running each element of the collection through the given callback. The corresponding value of each key is the last element responsible for generating the key. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1700,7 +1701,7 @@ _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String); ### `_.invoke(collection, methodName, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3842 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3849 "View in source") [Ⓣ][1] Invokes the method named by `methodName` on each element in the `collection` returning an array of the results of each invoked method. Additional arguments will be provided to each invoked method. If `methodName` is a function it will be invoked for, and `this` bound to, each element in the `collection`. @@ -1729,7 +1730,7 @@ _.invoke([123, 456], String.prototype.split, ''); ### `_.map(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3894 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3901 "View in source") [Ⓣ][1] Creates an array of values by running each element in the collection through the callback. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1774,7 +1775,7 @@ _.map(characters, 'name'); ### `_.max(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3952 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3959 "View in source") [Ⓣ][1] Retrieves the maximum value of a collection. If the collection is empty or falsey `-Infinity` is returned. If a callback is provided it will be executed for each value in the collection to generate the criterion by which the value is ranked. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, collection)*. @@ -1816,7 +1817,7 @@ _.max(characters, 'age'); ### `_.min(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4027 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4034 "View in source") [Ⓣ][1] Retrieves the minimum value of a collection. If the collection is empty or falsey `Infinity` is returned. If a callback is provided it will be executed for each value in the collection to generate the criterion by which the value is ranked. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, collection)*. @@ -1858,7 +1859,7 @@ _.min(characters, 'age'); ### `_.pluck(collection, property)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4082 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4089 "View in source") [Ⓣ][1] Retrieves the value of a specified property from all elements in the collection. @@ -1888,7 +1889,7 @@ _.pluck(characters, 'name'); ### `_.reduce(collection, [callback=identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4114 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4121 "View in source") [Ⓣ][1] Reduces a collection to a value which is the accumulated result of running each element in the collection through the callback, where each successive callback execution consumes the return value of the previous execution. If `accumulator` is not provided the first element of the collection will be used as the initial `accumulator` value. The callback is bound to `thisArg` and invoked with four arguments; *(accumulator, value, index|key, collection)*. @@ -1926,7 +1927,7 @@ var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { ### `_.reduceRight(collection, [callback=identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4157 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4164 "View in source") [Ⓣ][1] This method is like `_.reduce` except that it iterates over elements of a `collection` from right to left. @@ -1957,7 +1958,7 @@ var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); ### `_.reject(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4206 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4213 "View in source") [Ⓣ][1] The opposite of `_.filter`; this method returns the elements of a collection that the callback does **not** return truey for. @@ -2000,7 +2001,7 @@ _.reject(characters, { 'age': 36 }); ### `_.sample(collection, [n])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4232 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4239 "View in source") [Ⓣ][1] Retrieves a random element or `n` random elements from a collection. @@ -2028,7 +2029,7 @@ _.sample([1, 2, 3, 4], 2); ### `_.shuffle(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4260 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4267 "View in source") [Ⓣ][1] Creates an array of shuffled values, using a version of the Fisher-Yates shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) for more details. @@ -2052,7 +2053,7 @@ _.shuffle([1, 2, 3, 4, 5, 6]); ### `_.size(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4293 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4300 "View in source") [Ⓣ][1] Gets the size of the `collection` by returning `collection.length` for arrays and array-like objects or the number of own enumerable properties for objects. @@ -2082,7 +2083,7 @@ _.size('pebbles'); ### `_.some(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4340 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4347 "View in source") [Ⓣ][1] Checks if the callback returns a truey value for **any** element of a collection. The function returns as soon as it finds a passing value and does not iterate over the entire collection. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -2128,7 +2129,7 @@ _.some(characters, { 'age': 1 }); ### `_.sortBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4410 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4417 "View in source") [Ⓣ][1] Creates an array of elements, sorted in ascending order by the results of running each element in a collection through the callback. This method performs a stable sort, that is, it will preserve the original sort order of equal elements. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -2178,7 +2179,7 @@ _.map(_.sortBy(characters, ['name', 'age']), _.values); ### `_.toArray(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4456 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4463 "View in source") [Ⓣ][1] Converts the `collection` to an array. @@ -2202,9 +2203,9 @@ Converts the `collection` to an array. ### `_.where(collection, props)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4490 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4497 "View in source") [Ⓣ][1] -Performs a deep comparison of each element in a `collection` to the given `properties` object, returning an array of all elements that have equivalent property values. +Performs a deep comparison between each element in `collection` and the `props` object, returning an array of all elements that have equivalent property values. #### Arguments 1. `collection` *(Array|Object|string)*: The collection to iterate over. @@ -2242,7 +2243,7 @@ _.where(characters, { 'pets': ['dino'] }); ### `_.after(n, func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5555 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5562 "View in source") [Ⓣ][1] Creates a function that executes `func`, with the `this` binding and arguments of the created function, only after being called `n` times. @@ -2275,7 +2276,7 @@ _.forEach(saves, function(type) { ### `_.bind(func, [thisArg], [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5588 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5595 "View in source") [Ⓣ][1] Creates a function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends any additional `bind` arguments to those provided to the bound function. @@ -2306,7 +2307,7 @@ func(); ### `_.bindAll(object, [methodName])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5618 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5625 "View in source") [Ⓣ][1] Binds methods of an object to the object itself, overwriting the existing method. Method names may be specified as individual arguments or as arrays of method names. If no method names are provided all the function properties of `object` will be bound. @@ -2337,7 +2338,7 @@ jQuery('#docs').on('click', view.onClick); ### `_.bindKey(object, key, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5665 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5672 "View in source") [Ⓣ][1] Creates a function that, when called, invokes the method at `object[key]` and prepends any additional `bindKey` arguments to those provided to the bound function. This method differs from `_.bind` by allowing bound functions to reference methods that will be redefined or don't yet exist. See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) for more details. @@ -2378,7 +2379,7 @@ func(); ### `_.compose([func])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5701 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5708 "View in source") [Ⓣ][1] Creates a function that is the composition of the provided functions, where each function consumes the return value of the function that follows. For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. Each function is executed with the `this` binding of the composed function. @@ -2416,7 +2417,7 @@ welcome('pebbles'); ### `_.curry(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5749 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5756 "View in source") [Ⓣ][1] Creates a function which accepts one or more arguments of `func` that when invoked either executes `func` returning its result, if all `func` arguments have been provided, or returns a function that accepts one or more of the remaining `func` arguments, and so on. The arity of `func` can be specified if `func.length` is not sufficient. @@ -2451,7 +2452,7 @@ curried(1, 2, 3); ### `_.debounce(func, wait, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5793 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5800 "View in source") [Ⓣ][1] Creates a function that will delay the execution of `func` until after `wait` milliseconds have elapsed since the last time it was invoked. 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 will return the result of the last `func` call. @@ -2495,7 +2496,7 @@ source.addEventListener('message', _.debounce(batchLog, 250, { ### `_.defer(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5909 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5916 "View in source") [Ⓣ][1] Defers executing the `func` function until the current call stack has cleared. Additional arguments will be provided to `func` when it is invoked. @@ -2520,7 +2521,7 @@ _.defer(function(text) { console.log(text); }, 'deferred'); ### `_.delay(func, wait, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5933 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5940 "View in source") [Ⓣ][1] Executes the `func` function after `wait` milliseconds. Additional arguments will be provided to `func` when it is invoked. @@ -2546,7 +2547,7 @@ _.delay(function(text) { console.log(text); }, 1000, 'later'); ### `_.memoize(func, [resolver])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5978 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5985 "View in source") [Ⓣ][1] Creates a function that memoizes the result of `func`. If `resolver` is provided it will be used to determine the cache key for storing the result based on the arguments provided to the memoized function. By default, the first argument provided to the memoized function is used as the cache key. The `func` is executed with the `this` binding of the memoized function. The result cache is exposed as the `cache` property on the memoized function. @@ -2589,7 +2590,7 @@ get('pebbles'); ### `_.once(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6011 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6018 "View in source") [Ⓣ][1] Creates a function that is restricted to execute `func` once. Repeat calls to the function will return the value of the first call. The `func` is executed with the `this` binding of the created function. @@ -2615,7 +2616,7 @@ initialize(); ### `_.partial(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6049 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6056 "View in source") [Ⓣ][1] Creates a function that, when called, invokes `func` with any additional `partial` arguments prepended to those provided to the new function. This method is similar to `_.bind` except it does **not** alter the `this` binding. @@ -2642,7 +2643,7 @@ hi('fred'); ### `_.partialRight(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6080 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6087 "View in source") [Ⓣ][1] This method is like `_.partial` except that `partial` arguments are appended to those provided to the new function. @@ -2679,7 +2680,7 @@ options.imports ### `_.throttle(func, wait, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6115 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6122 "View in source") [Ⓣ][1] Creates a function that, when executed, will only call the `func` function at most once per every `wait` milliseconds. 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 will return the result of the last `func` call. @@ -2715,7 +2716,7 @@ jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { ### `_.wrap(value, wrapper)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6156 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6163 "View in source") [Ⓣ][1] Creates a function that provides `value` to the wrapper function as its first argument. Additional arguments provided to the function are appended to those provided to the wrapper function. The wrapper is executed with the `this` binding of the created function. @@ -2751,7 +2752,7 @@ p('Fred, Wilma, & Pebbles'); ### `_.assign(object, [source], [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2022 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2029 "View in source") [Ⓣ][1] Assigns own enumerable properties of source object(s) to the destination object. Subsequent sources will overwrite property assignments of previous sources. If a callback is provided it will be executed to produce the assigned values. The callback is bound to `thisArg` and invoked with two arguments; *(objectValue, sourceValue)*. @@ -2789,7 +2790,7 @@ defaults(object, { 'name': 'fred', 'employer': 'slate' }); ### `_.clone(value, [isDeep=false], [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2088 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2095 "View in source") [Ⓣ][1] Creates a clone of `value`. If `isDeep` is `true` nested objects will also be cloned, otherwise they will be assigned by reference. If a callback is provided it will be executed to produce the cloned values. If the callback returns `undefined` cloning will be handled by the method instead. The callback is bound to `thisArg` and invoked with one argument; *(value)*. @@ -2836,7 +2837,7 @@ clone.childNodes.length; ### `_.cloneDeep(value, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2141 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2148 "View in source") [Ⓣ][1] Creates a deep clone of `value`. If a callback is provided it will be executed to produce the cloned values. If the callback returns `undefined` cloning will be handled by the method instead. The callback is bound to `thisArg` and invoked with one argument; *(value)*. @@ -2882,7 +2883,7 @@ clone.node == view.node; ### `_.create(prototype, [properties])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2176 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2183 "View in source") [Ⓣ][1] Creates an object that inherits from the given `prototype` object. If a `properties` object is provided its own enumerable properties are assigned to the created object. @@ -2922,7 +2923,7 @@ circle instanceof Shape; ### `_.defaults(object, [source])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2200 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2207 "View in source") [Ⓣ][1] Assigns own enumerable properties of source object(s) to the destination object for all destination properties that resolve to `undefined`. Once a property is set, additional defaults of the same property will be ignored. @@ -2948,7 +2949,7 @@ _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); ### `_.findKey(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2264 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2271 "View in source") [Ⓣ][1] This method is like `_.findIndex` except that it returns the key of the first element that passes the callback check, instead of the element itself. @@ -2994,7 +2995,7 @@ _.findKey(characters, 'blocked'); ### `_.findLastKey(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2317 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2324 "View in source") [Ⓣ][1] This method is like `_.findKey` except that it iterates over elements of a `collection` in the opposite order. @@ -3040,7 +3041,7 @@ _.findLastKey(characters, 'blocked'); ### `_.forIn(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2360 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2367 "View in source") [Ⓣ][1] Iterates over own and inherited enumerable properties of an object, executing the callback for each property. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -3078,7 +3079,7 @@ _.forIn(new Shape, function(value, key) { ### `_.forInRight(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2396 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2403 "View in source") [Ⓣ][1] This method is like `_.forIn` except that it iterates over elements of a `collection` in the opposite order. @@ -3116,7 +3117,7 @@ _.forInRight(new Shape, function(value, key) { ### `_.forOwn(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2433 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2440 "View in source") [Ⓣ][1] Iterates over own enumerable properties of an object, executing the callback for each property. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -3144,7 +3145,7 @@ _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { ### `_.forOwnRight(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2466 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2473 "View in source") [Ⓣ][1] This method is like `_.forOwn` except that it iterates over elements of a `collection` in the opposite order. @@ -3172,7 +3173,7 @@ _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { ### `_.functions(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2495 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2502 "View in source") [Ⓣ][1] Creates a sorted array of property names of all enumerable properties, own and inherited, of `object` that have function values. @@ -3199,7 +3200,7 @@ _.functions(_); ### `_.has(object, key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2520 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2527 "View in source") [Ⓣ][1] Checks if the specified property name exists as a direct property of `object`, instead of an inherited property. @@ -3224,7 +3225,7 @@ _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); ### `_.invert(object, [multiValue=false])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2549 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2556 "View in source") [Ⓣ][1] Creates an object composed of the inverted keys and values of the given object. If the given object contains duplicate values, subsequent values will overwrite property assignments of previous values unless `multiValue` is `true`. @@ -3257,7 +3258,7 @@ _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); ### `_.isArguments(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1893 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1923 "View in source") [Ⓣ][1] Checks if `value` is an `arguments` object. @@ -3284,7 +3285,7 @@ _.isArguments([1, 2, 3]); ### `_.isArray(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1922 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1952 "View in source") [Ⓣ][1] Checks if `value` is an array. @@ -3311,7 +3312,7 @@ _.isArray([1, 2, 3]); ### `_.isBoolean(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2585 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2592 "View in source") [Ⓣ][1] Checks if `value` is a boolean value. @@ -3335,7 +3336,7 @@ _.isBoolean(null); ### `_.isDate(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2603 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2610 "View in source") [Ⓣ][1] Checks if `value` is a date. @@ -3359,7 +3360,7 @@ _.isDate(new Date); ### `_.isElement(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2620 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2627 "View in source") [Ⓣ][1] Checks if `value` is a DOM element. @@ -3383,7 +3384,7 @@ _.isElement(document.body); ### `_.isEmpty(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2653 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2660 "View in source") [Ⓣ][1] Checks if `value` is empty. Arrays, strings, or `arguments` objects with a length of `0` and objects with no own enumerable properties are considered "empty". @@ -3413,7 +3414,7 @@ _.isEmpty(''); ### `_.isEqual(a, b, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2710 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2717 "View in source") [Ⓣ][1] Performs a deep comparison between two values to determine if they are equivalent to each other. If a callback is provided it will be executed to compare values. If the callback returns `undefined` comparisons will be handled by the method instead. The callback is bound to `thisArg` and invoked with two arguments; *(a, b)*. @@ -3458,7 +3459,7 @@ _.isEqual(words, otherWords, function(a, b) { ### `_.isFinite(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2743 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2750 "View in source") [Ⓣ][1] Checks if `value` is, or can be coerced to, a finite number. @@ -3496,7 +3497,7 @@ _.isFinite(Infinity); ### `_.isFunction(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2760 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2767 "View in source") [Ⓣ][1] Checks if `value` is a function. @@ -3520,7 +3521,7 @@ _.isFunction(_); ### `_.isNaN(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2824 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2831 "View in source") [Ⓣ][1] Checks if `value` is `NaN`. @@ -3555,7 +3556,7 @@ _.isNaN(undefined); ### `_.isNull(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2846 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2853 "View in source") [Ⓣ][1] Checks if `value` is `null`. @@ -3582,7 +3583,7 @@ _.isNull(undefined); ### `_.isNumber(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2866 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2873 "View in source") [Ⓣ][1] Checks if `value` is a number. @@ -3608,7 +3609,7 @@ _.isNumber(8.4 * 5); ### `_.isObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2790 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2797 "View in source") [Ⓣ][1] Checks if `value` is the language type of Object. *(e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)* @@ -3638,7 +3639,7 @@ _.isObject(1); ### `_.isPlainObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2895 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2902 "View in source") [Ⓣ][1] Checks if `value` is an object created by the `Object` constructor. @@ -3673,7 +3674,7 @@ _.isPlainObject({ 'x': 0, 'y': 0 }); ### `_.isRegExp(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2920 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2927 "View in source") [Ⓣ][1] Checks if `value` is a regular expression. @@ -3697,7 +3698,7 @@ _.isRegExp(/fred/); ### `_.isString(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2937 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2944 "View in source") [Ⓣ][1] Checks if `value` is a string. @@ -3721,7 +3722,7 @@ _.isString('fred'); ### `_.isUndefined(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2955 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2962 "View in source") [Ⓣ][1] Checks if `value` is `undefined`. @@ -3745,7 +3746,7 @@ _.isUndefined(void 0); ### `_.keys(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1957 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1987 "View in source") [Ⓣ][1] Creates an array composed of the own enumerable property names of an object. @@ -3769,7 +3770,7 @@ _.keys({ 'one': 1, 'two': 2, 'three': 3 }); ### `_.mapValues(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2995 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3002 "View in source") [Ⓣ][1] Creates an object with the same keys as `object` and values generated by running each own enumerable property of `object` through the callback. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. @@ -3808,7 +3809,7 @@ _.mapValues(characters, 'age'); ### `_.merge(object, [source], [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3056 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3063 "View in source") [Ⓣ][1] Recursively merges own enumerable properties of the source object(s), that don't resolve to `undefined` into the destination object. Subsequent sources will overwrite property assignments of previous sources. If a callback is provided it will be executed to produce the merged values of the destination and source properties. If the callback returns `undefined` merging will be handled by the method instead. The callback is bound to `thisArg` and invoked with two arguments; *(objectValue, sourceValue)*. @@ -3864,7 +3865,7 @@ _.merge(food, otherFood, function(a, b) { ### `_.omit(object, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3112 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3119 "View in source") [Ⓣ][1] Creates a shallow clone of `object` excluding the specified properties. Property names may be specified as individual arguments or as arrays of property names. If a callback is provided it will be executed for each property of `object` omitting the properties the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. @@ -3895,7 +3896,7 @@ _.omit({ 'name': 'fred', 'age': 40 }, function(value) { ### `_.pairs(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3153 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3160 "View in source") [Ⓣ][1] Creates a two dimensional array of an object's key-value pairs, i.e. `[[key1, value1], [key2, value2]]`. @@ -3919,7 +3920,7 @@ _.pairs({ 'barney': 36, 'fred': 40 }); ### `_.pick(object, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3193 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3200 "View in source") [Ⓣ][1] Creates a shallow clone of `object` composed of the specified properties. Property names may be specified as individual arguments or as arrays of property names. If a callback is provided it will be executed for each property of `object` picking the properties the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. @@ -3950,7 +3951,7 @@ _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { ### `_.transform(object, [callback=identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3248 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3255 "View in source") [Ⓣ][1] An alternative to `_.reduce` this method transforms `object` to a new `accumulator` object which is the result of running each of its own enumerable properties through a callback, with each callback execution potentially mutating the `accumulator` object. The callback is bound to `thisArg` and invoked with four arguments; *(accumulator, value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -3987,7 +3988,7 @@ var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) ### `_.values(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3282 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3289 "View in source") [Ⓣ][1] Creates an array composed of the own enumerable property values of `object`. @@ -4018,7 +4019,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 }); ### `_.now` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6406 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6439 "View in source") [Ⓣ][1] *(unknown)*: Gets the number of milliseconds that have elapsed since the Unix epoch *(1 January `1970 00`:00:00 UTC)*. @@ -4037,7 +4038,7 @@ _.defer(function() { console.log(_.now() - stamp); }); ### `_.constant(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6177 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6184 "View in source") [Ⓣ][1] Creates a function that returns `value`. @@ -4063,7 +4064,7 @@ getter() === object; ### `_.createCallback([func=identity], [thisArg], [argCount])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6214 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6221 "View in source") [Ⓣ][1] Produces a callback bound to an optional `thisArg`. If `func` is a property name the created callback will return the property value for a given element. If `func` is an object the created callback will return `true` for elements that contain the equivalent object properties, otherwise it will return `false`. @@ -4102,7 +4103,7 @@ _.filter(characters, 'age__gt38'); ### `_.escape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6266 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6247 "View in source") [Ⓣ][1] Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding HTML entities. @@ -4128,7 +4129,7 @@ _.escape('Fred, Wilma, & Pebbles'); ### `_.identity(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6284 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6265 "View in source") [Ⓣ][1] This method returns the first argument provided to it. @@ -4150,10 +4151,44 @@ _.identity(object) === object; + + +### `_.match(props)` +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6293 "View in source") [Ⓣ][1] + +Creates a "_.where" style function, which returns `true` for a given object if it has the equivalent property values of the `props` object, else `false`. + +#### Arguments +1. `props` *(Object)*: The object of property values to match. + +#### Returns +*(Function)*: Returns the new function. + +#### Example +```js +var characters = [ + { 'name': 'fred', 'age': 40 }, + { 'name': 'barney', 'age': 36 } +]; + +var matchAge = _.match({ 'age': 36 }); + +_.filter(characters, matchAge); +// => [{ 'name': 'barney', 'age': 36 }] + +_.find(characters, matchAge); +// => { 'name': 'barney', 'age': 36 } +``` + +* * * + + + + ### `_.mixin([object=lodash], source, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6316 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6349 "View in source") [Ⓣ][1] Adds function properties of a source object to the destination object. If `object` is a function methods will be added to its prototype as well. @@ -4189,7 +4224,7 @@ _('fred').capitalize(); ### `_.noConflict()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6372 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6405 "View in source") [Ⓣ][1] Reverts the '_' variable to its previous value and returns a reference to the `lodash` function. @@ -4209,7 +4244,7 @@ var lodash = _.noConflict(); ### `_.noop()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6389 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6422 "View in source") [Ⓣ][1] A no-operation function. @@ -4228,7 +4263,7 @@ _.noop(object) === undefined; ### `_.parseInt(value, [radix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6430 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6463 "View in source") [Ⓣ][1] Converts the given value into an integer of the specified radix. If `radix` is `undefined` or `0` a `radix` of `10` is used unless the `value` is a hexadecimal, in which case a `radix` of `16` is used. @@ -4255,7 +4290,7 @@ _.parseInt('08'); ### `_.property(key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6459 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6492 "View in source") [Ⓣ][1] Creates a "_.pluck" style function, which returns the `key` value of a given object. @@ -4289,7 +4324,7 @@ _.sortBy(characters, getName); ### `_.random([min=0], [max=1], [floating=false])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6492 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6525 "View in source") [Ⓣ][1] Produces a random number between `min` and `max` *(inclusive)*. If only one argument is provided a number between `0` and the given number will be returned. If `floating` is truey or either `min` or `max` are floats a floating-point number will be returned instead of an integer. @@ -4324,7 +4359,7 @@ _.random(1.2, 5.2); ### `_.result(object, key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6550 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6583 "View in source") [Ⓣ][1] Resolves the value of property `key` on `object`. If `key` is a function it will be invoked with the `this` binding of `object` and its result returned, else the property value is returned. If `object` is falsey then `undefined` is returned. @@ -4359,7 +4394,7 @@ _.result(object, 'stuff'); ### `_.runInContext([context=root])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L456 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L485 "View in source") [Ⓣ][1] Create a new `lodash` function using the given context object. @@ -4377,7 +4412,7 @@ Create a new `lodash` function using the given context object. ### `_.template(text, data, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6643 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6676 "View in source") [Ⓣ][1] A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code. @@ -4469,7 +4504,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\ ### `_.times(n, callback, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6766 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6799 "View in source") [Ⓣ][1] Executes the callback `n` times, returning an array of the results of each callback execution. The callback is bound to `thisArg` and invoked with one argument; *(index)*. @@ -4501,7 +4536,7 @@ _.times(3, function(n) { this.cast(n); }, mage); ### `_.unescape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6796 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6829 "View in source") [Ⓣ][1] The inverse of `_.escape`; this method converts the HTML entities `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding characters. @@ -4527,7 +4562,7 @@ _.unescape('Fred, Barney & Pebbles'); ### `_.uniqueId([prefix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6820 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6853 "View in source") [Ⓣ][1] Generates a unique ID. If `prefix` is provided the ID will be appended to it. @@ -4561,7 +4596,7 @@ _.uniqueId(); ### `_.templateSettings.imports._` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L870 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L900 "View in source") [Ⓣ][1] A reference to the `lodash` function. @@ -4580,7 +4615,7 @@ A reference to the `lodash` function. ### `_.VERSION` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7142 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7176 "View in source") [Ⓣ][1] *(string)*: The semantic version number. @@ -4592,7 +4627,7 @@ A reference to the `lodash` function. ### `_.support` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L667 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L697 "View in source") [Ⓣ][1] *(Object)*: An object used to flag environments features. @@ -4604,7 +4639,7 @@ A reference to the `lodash` function. ### `_.support.argsClass` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L684 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L714 "View in source") [Ⓣ][1] *(boolean)*: Detect if an `arguments` object's [[Class]] is resolvable *(all but Firefox < `4`, IE < `9`)*. @@ -4616,7 +4651,7 @@ A reference to the `lodash` function. ### `_.support.argsObject` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L692 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L722 "View in source") [Ⓣ][1] *(boolean)*: Detect if `arguments` objects are `Object` objects *(all but Narwhal and Opera < `10.5`)*. @@ -4628,7 +4663,7 @@ A reference to the `lodash` function. ### `_.support.enumErrorProps` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L701 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L731 "View in source") [Ⓣ][1] *(boolean)*: Detect if `name` or `message` properties of `Error.prototype` are enumerable by default. *(IE < `9`, Safari < `5.1`)* @@ -4640,7 +4675,7 @@ A reference to the `lodash` function. ### `_.support.enumPrototypes` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L714 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L744 "View in source") [Ⓣ][1] *(boolean)*: Detect if `prototype` properties are enumerable by default. @@ -4654,7 +4689,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.funcDecomp` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L723 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L753 "View in source") [Ⓣ][1] *(boolean)*: Detect if functions can be decompiled by `Function#toString` *(all but PS3 and older Opera mobile browsers & avoided in Windows `8` apps)*. @@ -4666,7 +4701,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.funcNames` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L731 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L761 "View in source") [Ⓣ][1] *(boolean)*: Detect if `Function#name` is supported *(all but IE)*. @@ -4678,7 +4713,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.nonEnumArgs` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L740 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L770 "View in source") [Ⓣ][1] *(boolean)*: Detect if `arguments` object indexes are non-enumerable *(Firefox < `4`, IE < `9`, PhantomJS, Safari < `5.1`)*. @@ -4690,7 +4725,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.nonEnumShadows` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L751 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L781 "View in source") [Ⓣ][1] *(boolean)*: Detect if properties shadowing those on `Object.prototype` are non-enumerable. @@ -4704,7 +4739,7 @@ In IE < `9` an objects own properties, shadowing non-enumerable ones, are made n ### `_.support.ownLast` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L759 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L789 "View in source") [Ⓣ][1] *(boolean)*: Detect if own properties are iterated after inherited properties *(all but IE < `9`)*. @@ -4716,7 +4751,7 @@ In IE < `9` an objects own properties, shadowing non-enumerable ones, are made n ### `_.support.spliceObjects` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L773 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L803 "View in source") [Ⓣ][1] *(boolean)*: Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. @@ -4730,7 +4765,7 @@ Firefox < `10`, IE compatibility mode, and IE < `9` have buggy Array `shift()` a ### `_.support.unindexedChars` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L784 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L814 "View in source") [Ⓣ][1] *(boolean)*: Detect lack of support for accessing string characters by index. @@ -4744,7 +4779,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L822 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L852 "View in source") [Ⓣ][1] *(Object)*: By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby *(ERB)*. Change the following template settings to use alternative delimiters. @@ -4756,7 +4791,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.escape` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L830 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L860 "View in source") [Ⓣ][1] *(RegExp)*: Used to detect `data` property values to be HTML-escaped. @@ -4768,7 +4803,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.evaluate` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L838 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L868 "View in source") [Ⓣ][1] *(RegExp)*: Used to detect code to be evaluated. @@ -4780,7 +4815,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.interpolate` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L846 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L876 "View in source") [Ⓣ][1] *(RegExp)*: Used to detect `data` property values to inject. @@ -4792,7 +4827,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.variable` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L854 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L884 "View in source") [Ⓣ][1] *(string)*: Used to reference the data object in the template text. @@ -4804,7 +4839,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.imports` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L862 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L892 "View in source") [Ⓣ][1] *(Object)*: Used to import variables into the compiled template. diff --git a/lodash.js b/lodash.js index 07d8352394..16dc526516 100644 --- a/lodash.js +++ b/lodash.js @@ -616,12 +616,13 @@ * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `map`, `mapValues`, `max`, `memoize`, `merge`, - * `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `pick`, `pluck`, `property`, `pull`, `push`, `range`, `reject`, `remove`, - * `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, - * `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `where`, `without`, `wrap`, `xor`, and `zip` + * `invert`, `invoke`, `keys`, `map`, `mapValues`, `match`, `max`, `memoize`, + * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, + * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, + * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, + * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, + * and `zip` * * The non-chainable wrapper functions are: * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, @@ -4469,8 +4470,8 @@ } /** - * Performs a deep comparison of each element in a `collection` to the given - * `properties` object, returning an array of all elements that have equivalent + * Performs a deep comparison between each element in `collection` and the + * `props` object, returning an array of all elements that have equivalent * property values. * * @static @@ -6222,34 +6223,8 @@ if (func == null || type == 'function') { return baseCreateCallback(func, thisArg, argCount); } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; - - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; - } - } - return result; - }; + // handle "_.pluck" and "_.where" style callback shorthands + return type != 'object' ? property(func) : match(func); } /** @@ -6291,6 +6266,58 @@ return value; } + /** + * Creates a "_.where" style function, which returns `true` for a given object + * if it has the equivalent property values of the `props` object, else `false`. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} props The object of property values to match. + * @returns {Function} Returns the new function. + * @example + * + * var characters = [ + * { 'name': 'fred', 'age': 40 }, + * { 'name': 'barney', 'age': 36 } + * ]; + * + * var matchAge = _.match({ 'age': 36 }); + * + * _.filter(characters, matchAge); + * // => [{ 'name': 'barney', 'age': 36 }] + * + * _.find(characters, matchAge); + * // => { 'name': 'barney', 'age': 36 } + */ + function match(source) { + source || (source = {}); + + var props = keys(source), + key = props[0], + a = source[key]; + + // fast path the common case of providing an object with a single + // property containing a primitive value + if (props.length == 1 && a === a && !isObject(a)) { + return function(object) { + var b = object[key]; + return a === b && (a !== 0 || (1 / a == 1 / b)); + }; + } + return function(object) { + var length = props.length, + result = false; + + while (length--) { + if (!(result = baseIsEqual(object[props[length]], source[props[length]], null, true))) { + break; + } + } + return result; + }; + } + /** * Adds function properties of a source object to the destination object. * If `object` is a function methods will be added to its prototype as well. @@ -6989,6 +7016,7 @@ lodash.keys = keys; lodash.map = map; lodash.mapValues = mapValues; + lodash.match = match; lodash.max = max; lodash.memoize = memoize; lodash.merge = merge; diff --git a/test/test.js b/test/test.js index c88ff0da97..a1719c0ae6 100644 --- a/test/test.js +++ b/test/test.js @@ -5084,6 +5084,23 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.match'); + + (function() { + test('should create a function that performs a deep comparison between a given object and the `props` object', 3, function() { + var object = { 'a': 1, 'b': 2 }, + actual = _.match({ 'a': 1 }); + + equal(actual.length, 1); + strictEqual(actual(object), true); + + actual = _.match({ 'b': 1 }); + strictEqual(actual(object), false); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.max'); (function() { @@ -8082,6 +8099,8 @@ }); }()); + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.where'); (function() { @@ -8732,7 +8751,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 157, function() { + test('should accept falsey arguments', 158, function() { var emptyArrays = _.map(falsey, function() { return []; }), isExposed = '_' in root, oldDash = root._; From c737ab764ee296f5ef05e2ce1c2dbe2a40ce0c1c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 23 Dec 2013 11:06:54 -0600 Subject: [PATCH 0081/1608] Minor doc tweaks to `_.pluck` and `_.match`. [ci skip] --- lodash.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index 16dc526516..f51586308a 100644 --- a/lodash.js +++ b/lodash.js @@ -4074,7 +4074,7 @@ * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {string} property The name of the property to pluck. + * @param {string} prop The name of the property to pluck. * @returns {Array} Returns a new array of property values. * @example * @@ -6267,8 +6267,9 @@ } /** - * Creates a "_.where" style function, which returns `true` for a given object - * if it has the equivalent property values of the `props` object, else `false`. + * Creates a "_.where" style function, which performs a deep comparison + * between a given object and the `props` object, returning `true` if the + * given object has equivalent property values, else `false`. * * @static * @memberOf _ From b338e76649492be4c5cb399d81b1d266d8f6de08 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 23 Dec 2013 17:29:51 -0600 Subject: [PATCH 0082/1608] Cleanup lodash and lodash.underscore builds. --- dist/lodash.compat.js | 7 ++-- dist/lodash.js | 10 +++--- dist/lodash.min.js | 4 +-- dist/lodash.underscore.js | 10 +++--- dist/lodash.underscore.min.js | 68 +++++++++++++++++------------------ 5 files changed, 50 insertions(+), 49 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index afefae7f87..dc6982256f 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -4057,7 +4057,7 @@ * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {string} property The name of the property to pluck. + * @param {string} prop The name of the property to pluck. * @returns {Array} Returns a new array of property values. * @example * @@ -6250,8 +6250,9 @@ } /** - * Creates a "_.where" style function, which returns `true` for a given object - * if it has the equivalent property values of the `props` object, else `false`. + * Creates a "_.where" style function, which performs a deep comparison + * between a given object and the `props` object, returning `true` if the + * given object has equivalent property values, else `false`. * * @static * @memberOf _ diff --git a/dist/lodash.js b/dist/lodash.js index b480dae339..def25a2006 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -3742,7 +3742,7 @@ * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {string} property The name of the property to pluck. + * @param {string} prop The name of the property to pluck. * @returns {Array} Returns a new array of property values. * @example * @@ -3787,12 +3787,11 @@ * // => { 'a': 3, 'b': 6, 'c': 9 } */ function reduce(collection, callback, accumulator, thisArg) { - if (!collection) return accumulator; var noaccum = arguments.length < 3; callback = lodash.createCallback(callback, thisArg, 4); var index = -1, - length = collection.length; + length = collection ? collection.length : 0; if (typeof length == 'number') { if (noaccum) { @@ -5932,8 +5931,9 @@ } /** - * Creates a "_.where" style function, which returns `true` for a given object - * if it has the equivalent property values of the `props` object, else `false`. + * Creates a "_.where" style function, which performs a deep comparison + * between a given object and the `props` object, returning `true` if the + * given object has equivalent property values, else `false`. * * @static * @memberOf _ diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 5219a53b39..6833b00210 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -21,8 +21,8 @@ for(t=ut(t,e,3);u--&&(e=r[u],false!==t(n[e],e,n)););return n}function xt(n){var return u}function St(n,t,e){var r=n?n.length:0;if(e=typeof e=="number"?e:0,typeof r=="number"){if(e>=r)return false;if(typeof n=="string"||!Ue(n)&&It(n))return Te?Te.call(n,t,e):-1e?qe(0,r+e):e)||0,-1o&&(o=a)}}else t=null==t&&It(n)?r:d.createCallback(t,e,3),$t(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Wt(n,t,e,r){if(!n)return e;var u=3>arguments.length;t=d.createCallback(t,r,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(e=n[++o]);++oarguments.length;return t=d.createCallback(t,r,4),Ft(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) -}),e}function Pt(n){var t=-1,e=n?n.length:0,r=ue(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++eo&&(o=a)}}else t=null==t&&It(n)?r:d.createCallback(t,e,3),$t(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Wt(n,t,e,r){var u=3>arguments.length;t=d.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&(e=n[++o]);++oarguments.length;return t=d.createCallback(t,r,4),Ft(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e +}function Pt(n){var t=-1,e=n?n.length:0,r=ue(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?qe(0,u+r):r||0}else if(r)return r=Ut(t,e),t[r]===e?r:-1;return n(t,e,r)}function Vt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=d.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=h;m?(i&&(i=je(i)),s=f,a=n.apply(l,o)):i||(i=Ne(r,h))}return m&&c?c=je(c):c||t===v||(c=Ne(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Yt(n){return n}function Zt(n){n||(n={});var t=Ge(n),e=t[0],r=n[e]; diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 3d19d71129..f8b0af8e43 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -2496,7 +2496,7 @@ * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {string} property The name of the property to pluck. + * @param {string} prop The name of the property to pluck. * @returns {Array} Returns a new array of property values. * @example * @@ -2541,12 +2541,11 @@ * // => { 'a': 3, 'b': 6, 'c': 9 } */ function reduce(collection, callback, accumulator, thisArg) { - if (!collection) return accumulator; var noaccum = arguments.length < 3; callback = createCallback(callback, thisArg, 4); var index = -1, - length = collection.length; + length = collection ? collection.length : 0; if (typeof length == 'number') { if (noaccum) { @@ -4301,8 +4300,9 @@ } /** - * Creates a "_.where" style function, which returns `true` for a given object - * if it has the equivalent property values of the `props` object, else `false`. + * Creates a "_.where" style function, which performs a deep comparison + * between a given object and the `props` object, returning `true` if the + * given object has equivalent property values, else `false`. * * @static * @memberOf _ diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index f9dd4d27ee..526aa4c44f 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -3,37 +3,37 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js` */ -;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++tf||typeof i=="undefined")return 1;if(it?0:t);++ee(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(t&&f.push(l),i.push(a))}return i}function h(n){return function(r,t,e){var u={};t=X(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++eu&&(u=t); -else r=X(r,t,3),$(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function W(n,r,t,e){if(!n)return t;var u=3>arguments.length;r=X(r,e,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(t=n[++o]);++oarguments.length;return r=X(r,e,4),D(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return $(n,function(n){var t;t=++r,t=0+Br(Gr()*(t-0+1)),e[r]=e[t],e[t]=n -}),e}function P(n,r,t){var e;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++te?Ur(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1; -return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o>>1,t(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;return null==n||"function"==e?a(n,r,t):"object"!=e?rr(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var r=Lr(n);return function(t){for(var e=r.length,u=false;e--&&(u=t[r[e]]===n[r[e]]););return u}}function nr(n){$(T(n),function(r){var t=u[r]=n[r]; -u.prototype[r]=function(){var n=[this.__wrapped__];return Dr.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function rr(n){return function(r){return r[n]}}var tr,er=0,ur={},or=+new Date+"",ir=/&(?:amp|lt|gt|quot|#x27);/g,fr=/[&<>"']/g,ar=/($^)/,lr=/['\n\r\t\u2028\u2029\\]/g,cr="[object Arguments]",pr="[object Array]",sr="[object Boolean]",gr="[object Date]",hr="[object Number]",vr="[object Object]",yr="[object RegExp]",mr="[object String]",_r={"&":"&","<":"<",">":">",'"':""","'":"'"},dr={"&":"&","<":"<",">":">",""":'"',"'":"'"},br={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},wr={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},jr=br[typeof window]&&window||this,xr=br[typeof exports]&&exports&&!exports.nodeType&&exports,Tr=br[typeof global]&&global; -!Tr||Tr.global!==Tr&&Tr.window!==Tr||(jr=Tr);var Ar=br[typeof module]&&module&&!module.nodeType&&module,Er=Ar&&Ar.exports===xr&&xr,Or=[],Sr=Object.prototype,kr=jr._,Nr=Sr.toString,qr=RegExp("^"+(Nr+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Fr=Math.ceil,Br=Math.floor,Rr=Function.prototype.toString,$r=Sr.hasOwnProperty,Dr=Or.push,Ir=Sr.propertyIsEnumerable,Mr=_(Mr=Object.create)&&Mr,Wr=_(Wr=Array.isArray)&&Wr,zr=jr.isFinite,Cr=jr.isNaN,Pr=_(Pr=Object.keys)&&Pr,Ur=Math.max,Vr=Math.min,Gr=Math.random; -o.prototype=u.prototype;var Hr={};!function(){var n={0:1,length:1};Hr.spliceObjects=(Or.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Mr||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||jr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$r.call(n,"callee")&&!Ir.call(n,"callee")||false});var Jr=Wr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n)==pr||false -},Kr=function(n){var r=[];if(!n||!br[typeof n])return r;for(var t in n)$r.call(n,t)&&r.push(t);return r},Lr=Pr?function(n){return O(n)?Pr(n):[]}:Kr,Qr=function(n,r){if(!n||!br[typeof n])return n;for(var t in n)if(r(n[t],t,n)===ur)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nr.call(n)});var Xr=h(function(n,r,t){$r.call(n,t)?n[t]++:n[t]=1}),Yr=h(function(n,r,t){($r.call(n,t)?n[t]:n[t]=[]).push(r)}),Zr=h(function(n,r,t){n[t]=r}),nt=I,rt=_(rt=Date.now)&&rt||function(){return(new Date).getTime() -};u.after=function(n,r){if(!E(r))throw new TypeError;return function(){return 1>--n?r.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var r=1i(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},u.invert=function(n,r){for(var t=-1,e=Lr(n),u=e.length,o={};++tr?0:r);++nt?Ur(0,e+t):Vr(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=nr,u.noConflict=function(){return jr._=kr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Br(Gr()*(r-n+1)) -},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return E(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Lr(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||ar).source+"|"+(e.interpolate||ar).source+"|"+(e.evaluate||ar).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(lr,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r -}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(ir,d))},u.uniqueId=function(n){var r=++er+"";return n?n+r:r},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0; -if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:tr;return e(n,Ur(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=N(n)),null==r||t?n?n[0+Br(Gr()*(n.length-1-0+1))]:tr:(n=C(n),n.length=Vr(Ur(0,r),n.length),n)},u.take=V,u.head=V,nr(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var r=Or[n]; -u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Hr.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var r=Or[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jr._=u, define(function(){return u})):xr&&Ar?Er?(Ar.exports=u)._=u:xr._=u:jr._=u}).call(this); \ No newline at end of file +;(function(){function n(n,t,r){r=(r||0)-1;for(var e=n?n.length:0;++rf||typeof i=="undefined")return 1;if(ir?0:r);++ee(t,i)&&o.push(i)}return o}function p(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(r&&f.push(l),i.push(a))}return i}function h(n){return function(t,r,e){var u={};r=X(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++eu&&(u=r); +else t=X(t,r,3),$(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function W(n,t,r,e){var u=3>arguments.length;t=X(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&(r=n[++o]);++oarguments.length;return t=X(t,e,4),D(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function C(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r;r=++t,r=0+Bt(Gt()*(r-0+1)),e[t]=e[r],e[r]=n +}),e}function P(n,t,r){var e;t=X(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Ut(0,u+e):e||0}else if(e)return e=J(t,r),t[e]===r?e:-1; +return n(t,r,e)}function H(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,i=n?n.length:0;for(t=X(t,r,3);++o>>1,r(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||t===p||(a=setTimeout(h,t)),r&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,t,r){var e=typeof n;return null==n||"function"==e?a(n,t,r):"object"!=e?tt(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var t=Lt(n);return function(r){for(var e=t.length,u=false;e--&&(u=r[t[e]]===n[t[e]]););return u}}function nt(n){$(T(n),function(t){var r=u[t]=n[t]; +u.prototype[t]=function(){var n=[this.__wrapped__];return Dt.apply(n,arguments),n=r.apply(u,n),this.__chain__?new o(n,true):n}})}function tt(n){return function(t){return t[n]}}var rt,et=0,ut={},ot=+new Date+"",it=/&(?:amp|lt|gt|quot|#x27);/g,ft=/[&<>"']/g,at=/($^)/,lt=/['\n\r\t\u2028\u2029\\]/g,ct="[object Arguments]",pt="[object Array]",st="[object Boolean]",gt="[object Date]",ht="[object Number]",vt="[object Object]",yt="[object RegExp]",mt="[object String]",_t={"&":"&","<":"<",">":">",'"':""","'":"'"},dt={"&":"&","<":"<",">":">",""":'"',"'":"'"},bt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},wt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},jt=bt[typeof window]&&window||this,xt=bt[typeof exports]&&exports&&!exports.nodeType&&exports,Tt=bt[typeof global]&&global; +!Tt||Tt.global!==Tt&&Tt.window!==Tt||(jt=Tt);var At=bt[typeof module]&&module&&!module.nodeType&&module,Et=At&&At.exports===xt&&xt,Ot=[],St=Object.prototype,kt=jt._,Nt=St.toString,qt=RegExp("^"+(Nt+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ft=Math.ceil,Bt=Math.floor,Rt=Function.prototype.toString,$t=St.hasOwnProperty,Dt=Ot.push,It=St.propertyIsEnumerable,Mt=_(Mt=Object.create)&&Mt,Wt=_(Wt=Array.isArray)&&Wt,zt=jt.isFinite,Ct=jt.isNaN,Pt=_(Pt=Object.keys)&&Pt,Ut=Math.max,Vt=Math.min,Gt=Math.random; +o.prototype=u.prototype;var Ht={};!function(){var n={0:1,length:1};Ht.spliceObjects=(Ot.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Mt||(f=function(){function n(){}return function(t){if(O(t)){n.prototype=t;var r=new n;n.prototype=null}return r||jt.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$t.call(n,"callee")&&!It.call(n,"callee")||false});var Jt=Wt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nt.call(n)==pt||false +},Kt=function(n){var t=[];if(!n||!bt[typeof n])return t;for(var r in n)$t.call(n,r)&&t.push(r);return t},Lt=Pt?function(n){return O(n)?Pt(n):[]}:Kt,Qt=function(n,t){if(!n||!bt[typeof n])return n;for(var r in n)if(t(n[r],r,n)===ut)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nt.call(n)});var Xt=h(function(n,t,r){$t.call(n,r)?n[r]++:n[r]=1}),Yt=h(function(n,t,r){($t.call(n,r)?n[r]:n[r]=[]).push(t)}),Zt=h(function(n,t,r){n[r]=t}),nr=I,tr=_(tr=Date.now)&&tr||function(){return(new Date).getTime() +};u.after=function(n,t){if(!E(t))throw new TypeError;return function(){return 1>--n?t.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var t=1i(a,e)){for(t=r;--t;)if(0>i(n[t],e))continue n;a.push(e)}return a},u.invert=function(n,t){for(var r=-1,e=Lt(n),u=e.length,o={};++rt?0:t);++nr?Ut(0,e+r):Vt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=nt,u.noConflict=function(){return jt._=kt,this},u.random=function(n,t){return null==n&&null==t&&(t=1),n=+n||0,null==t?(t=n,n=0):t=+t||0,n+Bt(Gt()*(t-n+1)) +},u.reduce=W,u.reduceRight=z,u.result=function(n,t){if(n){var r=n[t];return E(r)?n[t]():r}},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Lt(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,t,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||at).source+"|"+(e.interpolate||at).source+"|"+(e.evaluate||at).source+"|$","g"),function(t,e,u,o,i){return a+=n.slice(f,i).replace(lt,r),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+t.length,t +}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return t?l(t):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(it,d))},u.uniqueId=function(n){var t=++et+"";return n?n+t:t},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,t){return U(n,t,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,t,r){var u=0,o=n?n.length:0; +if(typeof t!="number"&&null!=t){var i=o;for(t=X(t,r,3);i--&&t(n[i],i,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:rt;return e(n,Ut(0,o-u))},u.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=N(n)),null==t||r?n?n[0+Bt(Gt()*(n.length-1-0+1))]:rt:(n=C(n),n.length=Vt(Ut(0,t),n.length),n)},u.take=V,u.head=V,nt(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Ot[n]; +u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Ht.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var t=Ot[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jt._=u, define(function(){return u})):xt&&At?Et?(At.exports=u)._=u:xt._=u:jt._=u}).call(this); \ No newline at end of file From 2dab4ccf8575e55d6ef303cb53f9a18388774f29 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 24 Dec 2013 12:47:22 -0600 Subject: [PATCH 0083/1608] Fix `_.reduce` for modern and underscore builds. --- dist/lodash.js | 2 +- dist/lodash.min.js | 4 ++-- dist/lodash.underscore.js | 2 +- dist/lodash.underscore.min.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dist/lodash.js b/dist/lodash.js index def25a2006..e1e0b00269 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -3794,7 +3794,7 @@ length = collection ? collection.length : 0; if (typeof length == 'number') { - if (noaccum) { + if (noaccum && length) { accumulator = collection[++index]; } while (++index < length) { diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 6833b00210..24e9bbf997 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -21,8 +21,8 @@ for(t=ut(t,e,3);u--&&(e=r[u],false!==t(n[e],e,n)););return n}function xt(n){var return u}function St(n,t,e){var r=n?n.length:0;if(e=typeof e=="number"?e:0,typeof r=="number"){if(e>=r)return false;if(typeof n=="string"||!Ue(n)&&It(n))return Te?Te.call(n,t,e):-1e?qe(0,r+e):e)||0,-1o&&(o=a)}}else t=null==t&&It(n)?r:d.createCallback(t,e,3),$t(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Wt(n,t,e,r){var u=3>arguments.length;t=d.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&(e=n[++o]);++oarguments.length;return t=d.createCallback(t,r,4),Ft(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e -}function Pt(n){var t=-1,e=n?n.length:0,r=ue(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++eo&&(o=a)}}else t=null==t&&It(n)?r:d.createCallback(t,e,3),$t(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Wt(n,t,e,r){var u=3>arguments.length;t=d.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(e=n[++o]);++oarguments.length;return t=d.createCallback(t,r,4),Ft(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) +}),e}function Pt(n){var t=-1,e=n?n.length:0,r=ue(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?qe(0,u+r):r||0}else if(r)return r=Ut(t,e),t[r]===e?r:-1;return n(t,e,r)}function Vt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=d.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=h;m?(i&&(i=je(i)),s=f,a=n.apply(l,o)):i||(i=Ne(r,h))}return m&&c?c=je(c):c||t===v||(c=Ne(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Yt(n){return n}function Zt(n){n||(n={});var t=Ge(n),e=t[0],r=n[e]; diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index f8b0af8e43..84f600d609 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -2548,7 +2548,7 @@ length = collection ? collection.length : 0; if (typeof length == 'number') { - if (noaccum) { + if (noaccum && length) { accumulator = collection[++index]; } while (++index < length) { diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index 526aa4c44f..451157bcb4 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -14,7 +14,7 @@ if(!(2&t||E(n)))throw new TypeError;return f&&!r.length&&(t&=-17,r=false),a&&!e. }function S(n){return typeof n=="number"||n&&typeof n=="object"&&Nt.call(n)==ht||false}function k(n){return typeof n=="string"||n&&typeof n=="object"&&Nt.call(n)==mt||false}function N(n){for(var t=-1,r=Lt(n),e=r.length,u=Array(e);++tu&&(u=r); -else t=X(t,r,3),$(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function W(n,t,r,e){var u=3>arguments.length;t=X(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&(r=n[++o]);++oarguments.length;return t=X(t,e,4),D(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function C(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r;r=++t,r=0+Bt(Gt()*(r-0+1)),e[t]=e[r],e[r]=n +else t=X(t,r,3),$(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function W(n,t,r,e){var u=3>arguments.length;t=X(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=X(t,e,4),D(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function C(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r;r=++t,r=0+Bt(Gt()*(r-0+1)),e[t]=e[r],e[r]=n }),e}function P(n,t,r){var e;t=X(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Ut(0,u+e):e||0}else if(e)return e=J(t,r),t[e]===r?e:-1; return n(t,r,e)}function H(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,i=n?n.length:0;for(t=X(t,r,3);++o>>1,r(n[e]) Date: Wed, 25 Dec 2013 00:21:45 -0600 Subject: [PATCH 0084/1608] Ensure `_.reduce` doesn't assign `accumulator` a collection value if its `length` is `0`. --- dist/lodash.compat.js | 2 +- dist/lodash.compat.min.js | 2 +- doc/README.md | 48 +++++++++++++++++++-------------------- lodash.js | 2 +- test/test.js | 14 ++++++++++++ 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index dc6982256f..129d47f51b 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -4109,7 +4109,7 @@ var index = -1, length = collection.length; - if (noaccum) { + if (noaccum && length) { accumulator = collection[++index]; } while (++index < length) { diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index a3c11b4979..ed011aa031 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -23,7 +23,7 @@ for(t=t&&typeof r=="undefined"?t:ut(t,r,3);++e=e)return false;if(typeof n=="string"||!Xr(n)&&Rt(n))return qr?qr.call(n,t,r):-1r?Kr(0,e+r):r)||0,-1o&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Xr(n)){var o=-1,a=n.length;for(u&&(r=n[++o]);++oo&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Xr(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=v.createCallback(t,e,4),Bt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Ft(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;if(t=v.createCallback(t,r,3),Xr(n)){r=-1;for(var u=n.length;++re?Kr(0,u+e):e||0}else if(e)return e=Jt(t,r),t[e]===r?e:-1;return n(t,r,e)}function Ht(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=v.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t`_.map` * `_.max` * `_.min` -* `_.pluck` +* `_.pluck` * `_.reduce` * `_.reduceRight` * `_.reject` @@ -1140,7 +1140,7 @@ _.isArray(squares.value()); ### `_.chain(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6884 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6885 "View in source") [Ⓣ][1] Creates a `lodash` object that wraps the given value with explicit method chaining enabled. @@ -1174,7 +1174,7 @@ var youngest = _.chain(characters) ### `_.tap(value, interceptor, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6911 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6912 "View in source") [Ⓣ][1] This method invokes `interceptor` and returns `value`. The interceptor is bound to `thisArg` and invoked with one argument; *(value)*. The purpose of this method is to "tap into" a method chain in order to perform operations on intermediate results within the chain. @@ -1203,7 +1203,7 @@ _([1, 2, 3, 4]) ### `_.prototype.chain()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6941 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6942 "View in source") [Ⓣ][1] Enables explicit method chaining on the wrapper object. @@ -1237,7 +1237,7 @@ _(characters).chain() ### `_.prototype.toString()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6958 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6959 "View in source") [Ⓣ][1] Produces the `toString` result of the wrapped value. @@ -1258,7 +1258,7 @@ _([1, 2, 3]).toString(); ### `_.prototype.valueOf()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6975 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6976 "View in source") [Ⓣ][1] Extracts the wrapped value. @@ -1858,14 +1858,14 @@ _.min(characters, 'age'); -### `_.pluck(collection, property)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4089 "View in source") [Ⓣ][1] +### `_.pluck(collection, prop)` +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4089 "View in source") [Ⓣ][1] Retrieves the value of a specified property from all elements in the collection. #### Arguments 1. `collection` *(Array|Object|string)*: The collection to iterate over. -2. `property` *(string)*: The name of the property to pluck. +2. `prop` *(string)*: The name of the property to pluck. #### Returns *(Array)*: Returns a new array of property values. @@ -4019,7 +4019,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 }); ### `_.now` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6439 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6440 "View in source") [Ⓣ][1] *(unknown)*: Gets the number of milliseconds that have elapsed since the Unix epoch *(1 January `1970 00`:00:00 UTC)*. @@ -4154,9 +4154,9 @@ _.identity(object) === object; ### `_.match(props)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6293 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6294 "View in source") [Ⓣ][1] -Creates a "_.where" style function, which returns `true` for a given object if it has the equivalent property values of the `props` object, else `false`. +Creates a "_.where" style function, which performs a deep comparison between a given object and the `props` object, returning `true` if the given object has equivalent property values, else `false`. #### Arguments 1. `props` *(Object)*: The object of property values to match. @@ -4188,7 +4188,7 @@ _.find(characters, matchAge); ### `_.mixin([object=lodash], source, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6349 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6350 "View in source") [Ⓣ][1] Adds function properties of a source object to the destination object. If `object` is a function methods will be added to its prototype as well. @@ -4224,7 +4224,7 @@ _('fred').capitalize(); ### `_.noConflict()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6405 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6406 "View in source") [Ⓣ][1] Reverts the '_' variable to its previous value and returns a reference to the `lodash` function. @@ -4244,7 +4244,7 @@ var lodash = _.noConflict(); ### `_.noop()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6422 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6423 "View in source") [Ⓣ][1] A no-operation function. @@ -4263,7 +4263,7 @@ _.noop(object) === undefined; ### `_.parseInt(value, [radix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6463 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6464 "View in source") [Ⓣ][1] Converts the given value into an integer of the specified radix. If `radix` is `undefined` or `0` a `radix` of `10` is used unless the `value` is a hexadecimal, in which case a `radix` of `16` is used. @@ -4290,7 +4290,7 @@ _.parseInt('08'); ### `_.property(key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6492 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6493 "View in source") [Ⓣ][1] Creates a "_.pluck" style function, which returns the `key` value of a given object. @@ -4324,7 +4324,7 @@ _.sortBy(characters, getName); ### `_.random([min=0], [max=1], [floating=false])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6525 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6526 "View in source") [Ⓣ][1] Produces a random number between `min` and `max` *(inclusive)*. If only one argument is provided a number between `0` and the given number will be returned. If `floating` is truey or either `min` or `max` are floats a floating-point number will be returned instead of an integer. @@ -4359,7 +4359,7 @@ _.random(1.2, 5.2); ### `_.result(object, key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6583 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6584 "View in source") [Ⓣ][1] Resolves the value of property `key` on `object`. If `key` is a function it will be invoked with the `this` binding of `object` and its result returned, else the property value is returned. If `object` is falsey then `undefined` is returned. @@ -4412,7 +4412,7 @@ Create a new `lodash` function using the given context object. ### `_.template(text, data, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6676 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6677 "View in source") [Ⓣ][1] A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code. @@ -4504,7 +4504,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\ ### `_.times(n, callback, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6799 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6800 "View in source") [Ⓣ][1] Executes the callback `n` times, returning an array of the results of each callback execution. The callback is bound to `thisArg` and invoked with one argument; *(index)*. @@ -4536,7 +4536,7 @@ _.times(3, function(n) { this.cast(n); }, mage); ### `_.unescape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6829 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6830 "View in source") [Ⓣ][1] The inverse of `_.escape`; this method converts the HTML entities `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding characters. @@ -4562,7 +4562,7 @@ _.unescape('Fred, Barney & Pebbles'); ### `_.uniqueId([prefix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6853 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6854 "View in source") [Ⓣ][1] Generates a unique ID. If `prefix` is provided the ID will be appended to it. @@ -4615,7 +4615,7 @@ A reference to the `lodash` function. ### `_.VERSION` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7176 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7177 "View in source") [Ⓣ][1] *(string)*: The semantic version number. diff --git a/lodash.js b/lodash.js index f51586308a..f893ccf3f3 100644 --- a/lodash.js +++ b/lodash.js @@ -4126,7 +4126,7 @@ var index = -1, length = collection.length; - if (noaccum) { + if (noaccum && length) { accumulator = collection[++index]; } while (++index < length) { diff --git a/test/test.js b/test/test.js index a1719c0ae6..116b4afaeb 100644 --- a/test/test.js +++ b/test/test.js @@ -6367,6 +6367,20 @@ var actual = func([], noop, undefined); strictEqual(actual, undefined); }); + + test('`_.' + methodName + '` should return `undefined` for empty collections when no `accumulator` is provided (test in IE > 9 and modern browsers)', 2, function() { + var array = [], + object = { '0': 1, 'length': 0 }; + + if ('__proto__' in array) { + array.__proto__ = object; + strictEqual(_.reduce(array, noop), undefined); + } + else { + skipTest(); + } + strictEqual(_.reduce(object, noop), undefined); + }); }); /*--------------------------------------------------------------------------*/ From e4df75519c86d974995339e26b03683f9a2016a9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 26 Dec 2013 10:09:09 -0600 Subject: [PATCH 0085/1608] Ensure `_.random()` returns `1` or `0`. --- dist/lodash.compat.js | 5 +++-- dist/lodash.compat.min.js | 2 +- dist/lodash.js | 5 +++-- dist/lodash.min.js | 2 +- lodash.js | 5 +++-- test/test.js | 8 +++++--- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 129d47f51b..4e8c43029a 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -6511,17 +6511,18 @@ noMax = max == null; if (floating == null) { - if (typeof min == 'boolean' && noMax) { + if (noMax && typeof min == 'boolean') { floating = min; min = 1; } - else if (!noMax && typeof max == 'boolean') { + else if (typeof max == 'boolean') { floating = max; noMax = true; } } if (noMin && noMax) { max = 1; + noMax = false; } min = +min || 0; if (noMax) { diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index ed011aa031..23bde1d488 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -50,7 +50,7 @@ i in n&&(e[i]=n[i])}else t=v.createCallback(t,r,3),ne(n,function(n,r,u){t(n,r,u) },v.cloneDeep=function(n,t,r){return tt(n,true,typeof t=="function"&&ut(t,r,1))},v.contains=Pt,v.escape=function(n){return null==n?"":vr(n).replace(R,mt)},v.every=Dt,v.find=qt,v.findIndex=function(n,t,r){var e=-1,u=n?n.length:0;for(t=v.createCallback(t,r,3);++er?Kr(0,e+r):Mr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},v.mixin=er,v.noConflict=function(){return r._=jr,this},v.noop=ur,v.now=ae,v.parseInt=ie,v.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(typeof n=="boolean"&&u?(r=n,n=1):u||typeof t!="boolean"||(r=t,u=true)),e&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Ur(),Mr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) +},v.isString=Rt,v.isUndefined=function(n){return typeof n=="undefined"},v.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?Kr(0,e+r):Mr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},v.mixin=er,v.noConflict=function(){return r._=jr,this},v.noop=ur,v.now=ae,v.parseInt=ie,v.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Ur(),Mr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) },v.reduce=zt,v.reduceRight=Kt,v.result=function(n,t){if(n){var r=n[t];return It(r)?n[t]():r}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Zr(n).length},v.some=Vt,v.sortedIndex=Jt,v.template=function(n,t,r){var e=v.templateSettings;n=vr(n||""),r=Ct({},r,e);var u,o=Ct({},r.imports,e.imports),e=Zr(o),o=Tt(o),i=0,f=r.interpolate||P,l="__p+='",f=hr((r.escape||P).source+"|"+f.source+"|"+(f===A?k:P).source+"|"+(r.evaluate||P).source+"|$","g");n.replace(f,function(t,r,e,o,f,c){return e||(e=o),l+=n.slice(i,c).replace($,a),r&&(l+="'+__e("+r+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t }),l+="';",f=r=r.variable,f||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(j,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(f?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=cr(e,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},v.unescape=function(n){return null==n?"":(n=vr(n),0>n.indexOf(";")?n:n.replace(N,wt))},v.uniqueId=function(n){var t=++m; return vr(null==n?"":n)+t},v.all=Dt,v.any=Vt,v.detect=qt,v.findWhere=qt,v.foldl=zt,v.foldr=Kt,v.include=Pt,v.inject=zt,er(function(){var n={};return kt(v,function(t,r){v.prototype[r]||(n[r]=t)}),n}(),false),v.first=Ut,v.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:h;return s(n,Kr(0,u-e))},v.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Tt(n):Jr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[st(0,n.length-1)]:h:(n=Mt(n),n.length=Mr(Kr(0,t),n.length),n) diff --git a/dist/lodash.js b/dist/lodash.js index e1e0b00269..4dbaaab861 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -6192,17 +6192,18 @@ noMax = max == null; if (floating == null) { - if (typeof min == 'boolean' && noMax) { + if (noMax && typeof min == 'boolean') { floating = min; min = 1; } - else if (!noMax && typeof max == 'boolean') { + else if (typeof max == 'boolean') { floating = max; noMax = true; } } if (noMin && noMax) { max = 1; + noMax = false; } min = +min || 0; if (noMax) { diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 24e9bbf997..83a9d81ffa 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -46,7 +46,7 @@ if(typeof t!="number"&&null!=t){var o=u;for(t=d.createCallback(t,e,3);o--&&t(n[o },d.cloneDeep=function(n,t,e){return tt(n,true,typeof t=="function"&&ut(t,e,1))},d.contains=St,d.escape=function(n){return null==n?"":se(n).replace(S,vt)},d.every=Tt,d.find=Dt,d.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;for(t=d.createCallback(t,e,3);++re?qe(0,r+e):We(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},d.mixin=ne,d.noConflict=function(){return e._=be,this},d.noop=te,d.now=Ze,d.parseInt=nr,d.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Pe(),We(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t) +},d.isString=It,d.isUndefined=function(n){return typeof n=="undefined"},d.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?qe(0,r+e):We(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},d.mixin=ne,d.noConflict=function(){return e._=be,this},d.noop=te,d.now=Ze,d.parseInt=nr,d.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(u&&typeof n=="boolean"?(e=n,n=1):typeof t=="boolean"&&(e=t,u=true)),r&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Pe(),We(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t) },d.reduce=Wt,d.reduceRight=zt,d.result=function(n,t){if(n){var e=n[t];return Ot(e)?n[t]():e}},d.runInContext=s,d.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Ge(n).length},d.some=Kt,d.sortedIndex=Ut,d.template=function(n,t,e){var r=d.templateSettings;n=se(n||""),e=wt({},e,r);var u,o=wt({},e.imports,r.imports),r=Ge(o),o=Rt(o),a=0,f=e.interpolate||A,l="__p+='",f=pe((e.escape||A).source+"|"+f.source+"|"+(f===I?x:A).source+"|"+(e.evaluate||A).source+"|$","g");n.replace(f,function(t,e,r,o,f,c){return r||(r=o),l+=n.slice(a,c).replace($,i),e&&(l+="'+__e("+e+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t }),l+="';",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(w,""):l).replace(j,"$1").replace(k,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=ae(r,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},d.unescape=function(n){return null==n?"":(n=se(n),0>n.indexOf(";")?n:n.replace(R,bt))},d.uniqueId=function(n){var t=++y; return se(null==n?"":n)+t},d.all=Tt,d.any=Kt,d.detect=Dt,d.findWhere=Dt,d.foldl=Wt,d.foldr=zt,d.include=St,d.inject=Wt,ne(function(){var n={};return jt(d,function(t,e){d.prototype[e]||(n[e]=t)}),n}(),false),d.first=Lt,d.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=d.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:h;return p(n,qe(0,u-r))},d.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Rt(n)),null==t||e?n?n[ct(0,n.length-1)]:h:(n=Pt(n),n.length=We(qe(0,t),n.length),n) diff --git a/lodash.js b/lodash.js index f893ccf3f3..cc1782ef7b 100644 --- a/lodash.js +++ b/lodash.js @@ -6528,17 +6528,18 @@ noMax = max == null; if (floating == null) { - if (typeof min == 'boolean' && noMax) { + if (noMax && typeof min == 'boolean') { floating = min; min = 1; } - else if (!noMax && typeof max == 'boolean') { + else if (typeof max == 'boolean') { floating = max; noMax = true; } } if (noMin && noMax) { max = 1; + noMax = false; } min = +min || 0; if (noMax) { diff --git a/test/test.js b/test/test.js index 116b4afaeb..e7157da670 100644 --- a/test/test.js +++ b/test/test.js @@ -6046,12 +6046,14 @@ var array = Array(1000); test('should return `0` or `1` when arguments are not provided', 1, function() { - var actual = _.random(); - ok(actual === 0 || actual === 1); + var actual = _.map(array, function() { + return _.random(); + }); + + deepEqual(_.uniq(actual).sort(), [0, 1]); }); test('supports not passing a `max` argument', 1, function() { - var actual = _.random(5); ok(_.some(array, function() { return _.random(5) != 5; })); From 53d7c6c085aafed72484a7b01db8ed9856ebc159 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 27 Dec 2013 11:21:20 -0600 Subject: [PATCH 0086/1608] Fix node 0.6 tests with npm registry's new cert. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c243375624..84952e372f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,7 @@ branches: only: - master before_install: + - "[ $TRAVIS_NODE_VERSION != '0.6' ] || npm conf set strict-ssl false" - "([ $BUILD == 'legacy' ] || [ $BUILD == 'mobile' ] || [ $BUILD == 'modern' ]) && MAKE=true || true" - "([ $BUILD == 'compat' ] || [ $BUILD == 'legacy' ]) && COMPAT=true || true" - "[ $SAUCE_LABS == false ] || npm i ecstatic@\"~0.4.0\" request@\"~2.27.0\" sauce-tunnel@\"~1.1.0\"" From 95be8b2cf3f884d58a71db8b367b5486fa9f274c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 28 Dec 2013 19:56:52 -0600 Subject: [PATCH 0087/1608] Optimize `_.sortBy` by adding `baseCompareAscending` and `compareMultipleAscending`. --- dist/lodash.compat.js | 75 +++++++++++++++-------- dist/lodash.compat.min.js | 112 +++++++++++++++++----------------- dist/lodash.js | 75 +++++++++++++++-------- dist/lodash.min.js | 102 +++++++++++++++---------------- dist/lodash.underscore.js | 56 ++++++++--------- dist/lodash.underscore.min.js | 4 +- lodash.js | 75 +++++++++++++++-------- 7 files changed, 283 insertions(+), 216 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 4e8c43029a..4a465de2f0 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -198,6 +198,27 @@ /*--------------------------------------------------------------------------*/ + /** + * The base implementation of `compareAscending` used to compare values and + * sort them in ascending order without guaranteeing a stable sort. + * + * @private + * @param {*} a The value to compare to `b`. + * @param {*} b The value to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. + */ + function baseCompareAscending(a, b) { + if (a !== b) { + if (a > b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return 0; + } + /** * The base implementation of `_.indexOf` without support for binary searches * or `fromIndex` constraints. @@ -287,36 +308,42 @@ } /** - * Used by `sortBy` to compare transformed `collection` elements, stable sorting - * them in ascending order. + * Used by `sortBy` to compare transformed elements of a collection and stable + * sort them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator of `1` or `-1`. + * @returns {number} Returns the sort order indicator for `a`. */ function compareAscending(a, b) { + return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; + } + + /** + * Used by `sortBy` to compare multiple properties of each element in a + * collection and stable sort them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. + */ + function compareMultipleAscending(a, b) { var ac = a.criteria, bc = b.criteria, index = -1, length = ac.length; while (++index < length) { - var value = ac[index], - other = bc[index]; - - if (value !== other) { - if (value > other || typeof value == 'undefined') { - return 1; - } - if (value < other || typeof other == 'undefined') { - return -1; - } + var result = baseCompareAscending(ac[index], bc[index]); + if (result) { + return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to return the same value for - // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provided the same value + // for `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See http://code.google.com/p/v8/issues/detail?id=90 @@ -4257,6 +4284,7 @@ result[index] = result[rand]; result[rand] = value; }); + return result; } @@ -4399,32 +4427,27 @@ */ function sortBy(collection, callback, thisArg) { var index = -1, - isArr = isArray(callback), + multi = callback && isArray(callback), length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); - if (!isArr) { + if (!multi) { callback = lodash.createCallback(callback, thisArg, 3); } forEach(collection, function(value, key, collection) { var object = result[++index] = getObject(); - if (isArr) { - object.criteria = map(callback, function(key) { return value[key]; }); - } else { - (object.criteria = getArray())[0] = callback(value, key, collection); - } object.index = index; object.value = value; + object.criteria = multi + ? map(callback, function(key) { return value[key]; }) + : callback(value, key, collection); }); length = result.length; - result.sort(compareAscending); + result.sort(multi ? compareMultipleAscending : compareAscending); while (length--) { var object = result[length]; result[length] = object.value; - if (!isArr) { - releaseArray(object.criteria); - } releaseObject(object); } return result; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 23bde1d488..e3c34ea384 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -3,59 +3,59 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t,r){r=(r||0)-1;for(var e=n?n.length:0;++ri||typeof a=="undefined")return 1;if(ar?0:r);++e=b&&a===n,l=[];if(f){var c=o(e);c?(a=t,e=c):f=false}for(;++ua(e,c)&&l.push(c); -return f&&p(e),l}function ft(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ut(t,r,3),typeof o=="number")for(Jr.unindexedChars&&Rt(u)&&(u=u.split(""));++e=b&&f===n,h=u||g?i():s;for(g&&(h=o(h),f=t);++af(h,y))&&((u||g)&&h.push(y),s.push(v))}return g?(c(h.g),p(h)):u&&c(h),s}function ht(n){return function(t,r,e){var u={};if(r=v.createCallback(r,e,3),Xr(t)){e=-1;for(var o=t.length;++eu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ut,K,dr,Ar,jt,br,nt,Hr,H,_r,xr) -}function mt(n){return Y[n]}function dt(){var t=(t=v.indexOf)===Gt?n:t;return t}function bt(n){return typeof n=="function"&&Cr.test(Sr.call(n))}function _t(n){var t,r;return!n||xr.call(n)!=U||(t=n.constructor,It(t)&&!(t instanceof t))||!Jr.argsClass&&jt(n)||!Jr.nodeClass&&l(n)?false:Jr.ownLast?(ne(n,function(n,t,e){return r=Ar.call(e,t),false}),false!==r):(ne(n,function(n,t){r=t}),typeof r=="undefined"||Ar.call(n,r))}function wt(n){return Z[n]}function jt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&xr.call(n)==B||false -}function xt(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!Xr(n)&&Rt(n))return qr?qr.call(n,t,r):-1r?Kr(0,e+r):r)||0,-1o&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Xr(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=v.createCallback(t,e,4),Bt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Ft(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;if(t=v.createCallback(t,r,3),Xr(n)){r=-1;for(var u=n.length;++re?Kr(0,u+e):e||0}else if(e)return e=Jt(t,r),t[e]===r?e:-1;return n(t,r,e)}function Ht(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=v.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=h;m?(u&&(u=Or(u)),c=a,o=n.apply(i,e)):u||(u=Tr(y,h))}return m&&f?f=Or(f):f||t===p||(f=Tr(v,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function tr(n){return n}function rr(n){n||(n={});var t=Zr(n),r=t[0],e=n[r];return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=ct(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function er(n,t,r){var e=true,u=t&&Et(t);t&&(r||u.length)||(null==r&&(r=t),o=y,t=n,n=v,u=Et(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain); -var o=n,a=It(o);Ft(u,function(r){var u=n[r]=t[r];a&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,a=[r];if(Nr.apply(a,arguments),a=u.apply(n,a),e||t){if(r===a&&At(a))return this;a=new o(a),a.__chain__=t}return a})})}function ur(){}function or(n){return function(t){return t[n]}}function ar(){return this.__wrapped__}r=r?at.defaults(rt.Object(),r,at.pick(rt,q)):rt;var ir=r.Array,fr=r.Boolean,lr=r.Date,cr=r.Function,pr=r.Math,sr=r.Number,gr=r.Object,hr=r.RegExp,vr=r.String,yr=r.TypeError,mr=[],dr=r.Error.prototype,br=gr.prototype,_r=vr.prototype,wr=(wr=r.window)&&wr.document,jr=r._,xr=br.toString,Cr=hr("^"+vr(xr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),kr=pr.ceil,Or=r.clearTimeout,Er=pr.floor,Sr=cr.prototype.toString,Ir=bt(Ir=gr.getPrototypeOf)&&Ir,Ar=br.hasOwnProperty,Nr=mr.push,Rr=br.propertyIsEnumerable,Tr=r.setTimeout,Pr=mr.splice,Dr=mr.unshift,$r=function(){try{var n={},t=bt(t=gr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),qr=bt(qr=_r.contains)&&qr,Fr=bt(Fr=gr.create)&&Fr,Br=bt(Br=ir.isArray)&&Br,Lr=r.isFinite,Wr=r.isNaN,zr=bt(zr=gr.keys)&&zr,Kr=pr.max,Mr=pr.min,Vr=r.parseInt,Ur=pr.random,Gr={};Gr[L]=ir,Gr[W]=fr,Gr[z]=lr,Gr[M]=cr,Gr[U]=gr,Gr[V]=sr,Gr[G]=hr,Gr[H]=vr;var Hr={};Hr[L]=Hr[z]=Hr[V]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Hr[W]=Hr[H]={constructor:true,toString:true,valueOf:true},Hr[K]=Hr[M]=Hr[G]={constructor:true,toString:true},Hr[U]={constructor:true},function(){for(var n=F.length;n--;){var t,r=F[n]; -for(t in Hr)Ar.call(Hr,t)&&!Ar.call(Hr[t],r)&&(Hr[t][r]=false)}}(),y.prototype=v.prototype;var Jr=v.support={};!function(){var n=function(){this.x=1},t={0:1,length:1},e=[];n.prototype={valueOf:1,y:1};for(var u in new n)e.push(u);for(u in arguments);Jr.argsClass=xr.call(arguments)==B,Jr.argsObject=arguments.constructor==gr&&!(arguments instanceof ir),Jr.enumErrorProps=Rr.call(dr,"message")||Rr.call(dr,"name"),Jr.enumPrototypes=Rr.call(n,"prototype"),Jr.funcDecomp=!bt(r.WinRTError)&&D.test(g),Jr.funcNames=typeof cr.name=="string",Jr.nonEnumArgs=0!=u,Jr.nonEnumShadows=!/valueOf/.test(e),Jr.ownLast="x"!=e[0],Jr.spliceObjects=(mr.splice.call(t,0,1),!t[0]),Jr.unindexedChars="xx"!="x"[0]+gr("x")[0]; -try{Jr.dom=11===wr.createDocumentFragment().nodeType}catch(o){Jr.dom=false}try{Jr.nodeClass=!(xr.call(undefined)==U&&!({toString:0}+""))}catch(a){Jr.nodeClass=true}}(1),v.templateSettings={escape:S,evaluate:I,interpolate:A,variable:"",imports:{_:v}},Fr||(et=function(){function n(){}return function(t){if(At(t)){n.prototype=t;var e=new n;n.prototype=null}return e||r.Object()}}());var Qr=$r?function(n,t){X.value=t,$r(n,"__bindData__",X)}:ur;Jr.argsClass||(jt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ar.call(n,"callee")&&!Rr.call(n,"callee")||false -});var Xr=Br||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&xr.call(n)==L||false},Yr=yt({a:"p",b:"[]",e:"",c:"s.push(l)",f:true}),Zr=zr?function(n){return At(n)?Jr.enumPrototypes&&typeof n=="function"||Jr.nonEnumArgs&&n.length&&jt(n)?Yr(n):zr(n):[]}:Yr,ne=yt({a:"p,b,x",b:"p",e:"b=b&&typeof x=='undefined'?b:a(b,x,3)",c:"if(b(p[l],l,p)===false){return s}",f:false});Jr.dom||(St=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!te(n)||false}),It(/x/)&&(It=function(n){return typeof n=="function"&&xr.call(n)==M -});var te=Ir?function(n){if(!n||xr.call(n)!=U||!Jr.argsClass&&jt(n))return false;var t=n.valueOf,r=bt(t)&&(r=Ir(t))&&Ir(r);return r?n==r||Ir(n)==r:_t(n)}:_t,re=ht(function(n,t,r){Ar.call(n,r)?n[r]++:n[r]=1}),ee=ht(function(n,t,r){(Ar.call(n,r)?n[r]:n[r]=[]).push(t)}),ue=ht(function(n,t,r){n[r]=t}),oe=Lt,ae=bt(ae=lr.now)&&ae||function(){return(new lr).getTime()},ie=8==Vr(w+"08")?Vr:function(n,t){return Vr(Rt(n)?n.replace(T,""):n,t||0)};return v.after=function(n,t){if(!It(t))throw new yr;return function(){return 1>--n?t.apply(this,arguments):void 0 -}},v.assign=xt,v.at=function(n){var t=arguments,r=-1,e=lt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ir(t);for(Jr.unindexedChars&&Rt(n)&&(n=n.split(""));++r=b&&o(e?r[e]:s)))}var l=r[0],h=-1,v=l?l.length:0,y=[];n:for(;++h(m?t(m,g):f(s,g))){for(e=u,(m||s).push(g);--e;)if(m=a[e],0>(m?t(m,g):f(r[e],g)))continue n;y.push(g)}}for(;u--;)(m=a[u])&&p(m);return c(a),c(s),y},v.invert=function(n,t){for(var r=-1,e=Zr(n),u=e.length,o={};++rr?Kr(0,e+r):Mr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},v.mixin=er,v.noConflict=function(){return r._=jr,this},v.noop=ur,v.now=ae,v.parseInt=ie,v.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Ur(),Mr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) -},v.reduce=zt,v.reduceRight=Kt,v.result=function(n,t){if(n){var r=n[t];return It(r)?n[t]():r}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Zr(n).length},v.some=Vt,v.sortedIndex=Jt,v.template=function(n,t,r){var e=v.templateSettings;n=vr(n||""),r=Ct({},r,e);var u,o=Ct({},r.imports,e.imports),e=Zr(o),o=Tt(o),i=0,f=r.interpolate||P,l="__p+='",f=hr((r.escape||P).source+"|"+f.source+"|"+(f===A?k:P).source+"|"+(r.evaluate||P).source+"|$","g");n.replace(f,function(t,r,e,o,f,c){return e||(e=o),l+=n.slice(i,c).replace($,a),r&&(l+="'+__e("+r+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t -}),l+="';",f=r=r.variable,f||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(j,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(f?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=cr(e,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},v.unescape=function(n){return null==n?"":(n=vr(n),0>n.indexOf(";")?n:n.replace(N,wt))},v.uniqueId=function(n){var t=++m; -return vr(null==n?"":n)+t},v.all=Dt,v.any=Vt,v.detect=qt,v.findWhere=qt,v.foldl=zt,v.foldr=Kt,v.include=Pt,v.inject=zt,er(function(){var n={};return kt(v,function(t,r){v.prototype[r]||(n[r]=t)}),n}(),false),v.first=Ut,v.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:h;return s(n,Kr(0,u-e))},v.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Tt(n):Jr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[st(0,n.length-1)]:h:(n=Mt(n),n.length=Mr(Kr(0,t),n.length),n) -},v.take=Ut,v.head=Ut,kt(v,function(n,t){var r="sample"!==t;v.prototype[t]||(v.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new y(o,u):o})}),v.VERSION="2.4.1",v.prototype.chain=function(){return this.__chain__=true,this},v.prototype.toString=function(){return vr(this.__wrapped__)},v.prototype.value=ar,v.prototype.valueOf=ar,ft(["join","pop","shift"],function(n){var t=mr[n];v.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new y(r,n):r}}),ft(["push","reverse","sort","unshift"],function(n){var t=mr[n];v.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ft(["concat","slice","splice"],function(n){var t=mr[n];v.prototype[n]=function(){return new y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Jr.spliceObjects||ft(["pop","shift","splice"],function(n){var t=mr[n],r="splice"==n;v.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new y(u,n):u -}}),v}var h,v=[],y=[],m=0,d=+new Date+"",b=75,_=40,w=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",j=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,k=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,O=/\w*$/,E=/^\s*function[ \n\r\t]+\w/,S=/<%-([\s\S]+?)%>/g,I=/<%([\s\S]+?)%>/g,A=/<%=([\s\S]+?)%>/g,N=/&(?:amp|lt|gt|quot|#39);/g,R=/[&<>"']/g,T=RegExp("^["+w+"]*0+(?=.$)"),P=/($^)/,D=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),F="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),B="[object Arguments]",L="[object Array]",W="[object Boolean]",z="[object Date]",K="[object Error]",M="[object Function]",V="[object Number]",U="[object Object]",G="[object RegExp]",H="[object String]",J={}; -J[M]=false,J[B]=J[L]=J[W]=J[z]=J[V]=J[U]=J[G]=J[H]=true;var Q={leading:false,maxWait:0,trailing:false},X={configurable:false,enumerable:false,value:null,writable:false},Y={"&":"&","<":"<",">":">",'"':""","'":"'"},Z={"&":"&","<":"<",">":">",""":'"',"'":"'"},nt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},tt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},rt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof global]&&global; -!ut||ut.global!==ut&&ut.window!==ut||(rt=ut);var ot=(ut=nt[typeof module]&&module&&!module.nodeType&&module)&&ut.exports===et&&et,at=g();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(rt._=at, define(function(){return at})):et&&ut?ot?(ut.exports=at)._=at:et._=at:rt._=at}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=w&&o===t,l=[]; +if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&g(e),l}function lt(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ot(t,r,3),typeof o=="number")for(Qr.unindexedChars&&Tt(u)&&(u=u.split(""));++e=w&&a===t,h=u||p?l():c;for(p&&(h=i(h),a=r);++oa(h,y))&&((u||p)&&h.push(y),c.push(v))}return p?(s(h.g),g(h)):u&&s(h),c}function vt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),Yr(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ot,V,br,Nr,xt,_r,rt,Jr,Q,wr,Cr) +}function dt(n){return nt[n]}function bt(){var n=(n=e.indexOf)===Ht?t:n;return n}function _t(n){return typeof n=="function"&&kr.test(Ir.call(n))}function wt(n){var t,r;return!n||Cr.call(n)!=H||(t=n.constructor,At(t)&&!(t instanceof t))||!Qr.argsClass&&xt(n)||!Qr.nodeClass&&p(n)?false:Qr.ownLast?(te(n,function(n,t,e){return r=Nr.call(e,t),false}),false!==r):(te(n,function(n,t){r=t}),typeof r=="undefined"||Nr.call(n,r))}function jt(n){return tt[n]}function xt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Cr.call(n)==W||false +}function Ct(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!Yr(n)&&Tt(n))return Fr?Fr.call(n,t,r):-1r?Mr(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Tt(n)?u:e.createCallback(t,r,3),lt(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Kt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),Yr(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),Lt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Vt(n){var t=-1,r=n?n.length:0,e=fr(typeof r=="number"?r:0);return Bt(n,function(n){var r=gt(0,++t);e[t]=e[r],e[r]=n}),e}function Ut(n,t,r){var u;if(t=e.createCallback(t,r,3),Yr(n)){r=-1;for(var o=n.length;++re?Mr(0,u+e):e||0}else if(e)return e=Qt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y;m?(u&&(u=Er(u)),c=a,o=n.apply(i,e)):u||(u=Pr(v,y))}return m&&f?f=Er(f):f||t===p||(f=Pr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function rr(n){return n}function er(n){n||(n={});var t=ne(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Nt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function ur(n,t,r){var u=true,o=t&&St(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=St(t)),false===r?u=false:Nt(r)&&"chain"in r&&(u=r.chain); +var a=n,i=At(a);Bt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Rr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Nt(o))return this;o=new a(o),o.__chain__=t}return o})})}function or(){}function ar(n){return function(t){return t[n]}}function ir(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var fr=n.Array,lr=n.Boolean,cr=n.Date,pr=n.Function,sr=n.Math,gr=n.Number,hr=n.Object,vr=n.RegExp,yr=n.String,mr=n.TypeError,dr=[],br=n.Error.prototype,_r=hr.prototype,wr=yr.prototype,jr=(jr=n.window)&&jr.document,xr=n._,Cr=_r.toString,kr=vr("^"+yr(Cr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Or=sr.ceil,Er=n.clearTimeout,Sr=sr.floor,Ir=pr.prototype.toString,Ar=_t(Ar=hr.getPrototypeOf)&&Ar,Nr=_r.hasOwnProperty,Rr=dr.push,Tr=_r.propertyIsEnumerable,Pr=n.setTimeout,Dr=dr.splice,$r=dr.unshift,qr=function(){try{var n={},t=_t(t=hr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Fr=_t(Fr=wr.contains)&&Fr,Br=_t(Br=hr.create)&&Br,Lr=_t(Lr=fr.isArray)&&Lr,Wr=n.isFinite,zr=n.isNaN,Kr=_t(Kr=hr.keys)&&Kr,Mr=sr.max,Vr=sr.min,Ur=n.parseInt,Gr=sr.random,Hr={};Hr[z]=fr,Hr[K]=lr,Hr[M]=cr,Hr[U]=pr,Hr[H]=hr,Hr[G]=gr,Hr[J]=vr,Hr[Q]=yr;var Jr={};Jr[z]=Jr[M]=Jr[G]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Jr[K]=Jr[Q]={constructor:true,toString:true,valueOf:true},Jr[V]=Jr[U]=Jr[J]={constructor:true,toString:true},Jr[H]={constructor:true},function(){for(var n=L.length;n--;){var t,r=L[n]; +for(t in Jr)Nr.call(Jr,t)&&!Nr.call(Jr[t],r)&&(Jr[t][r]=false)}}(),m.prototype=e.prototype;var Qr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Qr.argsClass=Cr.call(arguments)==W,Qr.argsObject=arguments.constructor==hr&&!(arguments instanceof fr),Qr.enumErrorProps=Tr.call(br,"message")||Tr.call(br,"name"),Qr.enumPrototypes=Tr.call(t,"prototype"),Qr.funcDecomp=!_t(n.WinRTError)&&q.test(v),Qr.funcNames=typeof pr.name=="string",Qr.nonEnumArgs=0!=u,Qr.nonEnumShadows=!/valueOf/.test(e),Qr.ownLast="x"!=e[0],Qr.spliceObjects=(dr.splice.call(r,0,1),!r[0]),Qr.unindexedChars="xx"!="x"[0]+hr("x")[0]; +try{Qr.dom=11===jr.createDocumentFragment().nodeType}catch(o){Qr.dom=false}try{Qr.nodeClass=!(Cr.call(undefined)==H&&!({toString:0}+""))}catch(a){Qr.nodeClass=true}}(1),e.templateSettings={escape:A,evaluate:N,interpolate:R,variable:"",imports:{_:e}},Br||(et=function(){function t(){}return function(r){if(Nt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var Xr=qr?function(n,t){Z.value=t,qr(n,"__bindData__",Z)}:or;Qr.argsClass||(xt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n,"callee")&&!Tr.call(n,"callee")||false +});var Yr=Lr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Cr.call(n)==z||false},Zr=mt({a:"p",b:"[]",e:"",c:"s.push(l)",f:true}),ne=Kr?function(n){return Nt(n)?Qr.enumPrototypes&&typeof n=="function"||Qr.nonEnumArgs&&n.length&&xt(n)?Zr(n):Kr(n):[]}:Zr,te=mt({a:"p,b,x",b:"p",e:"b=b&&typeof x=='undefined'?b:a(b,x,3)",c:"if(b(p[l],l,p)===false){return s}",f:false});Qr.dom||(It=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!re(n)||false}),At(/x/)&&(At=function(n){return typeof n=="function"&&Cr.call(n)==U +});var re=Ar?function(n){if(!n||Cr.call(n)!=H||!Qr.argsClass&&xt(n))return false;var t=n.valueOf,r=_t(t)&&(r=Ar(t))&&Ar(r);return r?n==r||Ar(n)==r:wt(n)}:wt,ee=vt(function(n,t,r){Nr.call(n,r)?n[r]++:n[r]=1}),ue=vt(function(n,t,r){(Nr.call(n,r)?n[r]:n[r]=[]).push(t)}),oe=vt(function(n,t,r){n[r]=t}),ae=Wt,ie=_t(ie=cr.now)&&ie||function(){return(new cr).getTime()},fe=8==Ur(x+"08")?Ur:function(n,t){return Ur(Tt(n)?n.replace(D,""):n,t||0)};return e.after=function(n,t){if(!At(t))throw new mr;return function(){return 1>--n?t.apply(this,arguments):void 0 +}},e.assign=Ct,e.at=function(n){var t=arguments,r=-1,e=ct(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=fr(t);for(Qr.unindexedChars&&Tt(n)&&(n=n.split(""));++r=w&&i(e?n[e]:c)))}var f=n[0],h=-1,v=f?f.length:0,y=[];n:for(;++h(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p)}}for(;u--;)(m=o[u])&&g(m);return s(o),s(c),y},e.invert=function(n,t){for(var r=-1,e=ne(n),u=e.length,o={};++rr?Mr(0,e+r):Vr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=ur,e.noConflict=function(){return n._=xr,this},e.noop=or,e.now=ie,e.parseInt=fe,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Gr(),Vr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):gt(n,t) +},e.reduce=Kt,e.reduceRight=Mt,e.result=function(n,t){if(n){var r=n[t];return At(r)?n[t]():r}},e.runInContext=v,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ne(n).length},e.some=Ut,e.sortedIndex=Qt,e.template=function(n,t,r){var u=e.templateSettings;n=yr(n||""),r=kt({},r,u);var o,a=kt({},r.imports,u.imports),u=ne(a),a=Pt(a),i=0,l=r.interpolate||$,c="__p+='",l=vr((r.escape||$).source+"|"+l.source+"|"+(l===R?E:$).source+"|"+(r.evaluate||$).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace(F,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t +}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(C,""):c).replace(k,"$1").replace(O,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=pr(u,"return "+c).apply(y,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=yr(n),0>n.indexOf(";")?n:n.replace(T,jt))},e.uniqueId=function(n){var t=++b; +return yr(null==n?"":n)+t},e.all=$t,e.any=Ut,e.detect=Ft,e.findWhere=Ft,e.foldl=Kt,e.foldr=Mt,e.include=Dt,e.inject=Kt,ur(function(){var n={};return Ot(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Gt,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:y;return h(n,Mr(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Pt(n):Qr.unindexedChars&&Tt(n)&&(n=n.split("")),null==t||r?n?n[gt(0,n.length-1)]:y:(n=Vt(n),n.length=Vr(Mr(0,t),n.length),n) +},e.take=Gt,e.head=Gt,Ot(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new m(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return yr(this.__wrapped__)},e.prototype.value=ir,e.prototype.valueOf=ir,lt(["join","pop","shift"],function(n){var t=dr[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new m(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=dr[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),lt(["concat","slice","splice"],function(n){var t=dr[n];e.prototype[n]=function(){return new m(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Qr.spliceObjects||lt(["pop","shift","splice"],function(n){var t=dr[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new m(u,n):u +}}),e}var y,m=[],d=[],b=0,_=+new Date+"",w=75,j=40,x=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",C=/\b__p\+='';/g,k=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,S=/\w*$/,I=/^\s*function[ \n\r\t]+\w/,A=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,R=/<%=([\s\S]+?)%>/g,T=/&(?:amp|lt|gt|quot|#39);/g,P=/[&<>"']/g,D=RegExp("^["+x+"]*0+(?=.$)"),$=/($^)/,q=/\bthis\b/,F=/['\n\r\t\u2028\u2029\\]/g,B="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),L="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),W="[object Arguments]",z="[object Array]",K="[object Boolean]",M="[object Date]",V="[object Error]",U="[object Function]",G="[object Number]",H="[object Object]",J="[object RegExp]",Q="[object String]",X={}; +X[U]=false,X[W]=X[z]=X[K]=X[M]=X[G]=X[H]=X[J]=X[Q]=true;var Y={leading:false,maxWait:0,trailing:false},Z={configurable:false,enumerable:false,value:null,writable:false},nt={"&":"&","<":"<",">":">",'"':""","'":"'"},tt={"&":"&","<":"<",">":">",""":'"',"'":"'"},rt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},et={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ut=rt[typeof window]&&window||this,ot=rt[typeof exports]&&exports&&!exports.nodeType&&exports,at=rt[typeof global]&&global; +!at||at.global!==at&&at.window!==at||(ut=at);var it=(at=rt[typeof module]&&module&&!module.nodeType&&module)&&at.exports===ot&&ot,ft=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ut._=ft, define(function(){return ft})):ot&&at?it?(at.exports=ft)._=ft:ot._=ft:ut._=ft}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 4dbaaab861..b74a8b3551 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -188,6 +188,27 @@ /*--------------------------------------------------------------------------*/ + /** + * The base implementation of `compareAscending` used to compare values and + * sort them in ascending order without guaranteeing a stable sort. + * + * @private + * @param {*} a The value to compare to `b`. + * @param {*} b The value to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. + */ + function baseCompareAscending(a, b) { + if (a !== b) { + if (a > b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return 0; + } + /** * The base implementation of `_.indexOf` without support for binary searches * or `fromIndex` constraints. @@ -277,36 +298,42 @@ } /** - * Used by `sortBy` to compare transformed `collection` elements, stable sorting - * them in ascending order. + * Used by `sortBy` to compare transformed elements of a collection and stable + * sort them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator of `1` or `-1`. + * @returns {number} Returns the sort order indicator for `a`. */ function compareAscending(a, b) { + return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; + } + + /** + * Used by `sortBy` to compare multiple properties of each element in a + * collection and stable sort them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. + */ + function compareMultipleAscending(a, b) { var ac = a.criteria, bc = b.criteria, index = -1, length = ac.length; while (++index < length) { - var value = ac[index], - other = bc[index]; - - if (value !== other) { - if (value > other || typeof value == 'undefined') { - return 1; - } - if (value < other || typeof other == 'undefined') { - return -1; - } + var result = baseCompareAscending(ac[index], bc[index]); + if (result) { + return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to return the same value for - // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provided the same value + // for `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See http://code.google.com/p/v8/issues/detail?id=90 @@ -3940,6 +3967,7 @@ result[index] = result[rand]; result[rand] = value; }); + return result; } @@ -4082,32 +4110,27 @@ */ function sortBy(collection, callback, thisArg) { var index = -1, - isArr = isArray(callback), + multi = callback && isArray(callback), length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); - if (!isArr) { + if (!multi) { callback = lodash.createCallback(callback, thisArg, 3); } forEach(collection, function(value, key, collection) { var object = result[++index] = getObject(); - if (isArr) { - object.criteria = map(callback, function(key) { return value[key]; }); - } else { - (object.criteria = getArray())[0] = callback(value, key, collection); - } object.index = index; object.value = value; + object.criteria = multi + ? map(callback, function(key) { return value[key]; }) + : callback(value, key, collection); }); length = result.length; - result.sort(compareAscending); + result.sort(multi ? compareMultipleAscending : compareAscending); while (length--) { var object = result[length]; result[length] = object.value; - if (!isArr) { - releaseArray(object.criteria); - } releaseObject(object); } return result; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 83a9d81ffa..4b30bf3226 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,54 +3,54 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t,e){e=(e||0)-1;for(var r=n?n.length:0;++ea||typeof i=="undefined")return 1;if(ie?0:e);++r=b&&i===n,l=[]; -if(f){var p=o(r);p?(i=t,r=p):f=false}for(;++ui(r,p)&&l.push(p);return f&&c(r),l}function at(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r=b&&f===n,v=u||h?a():s;for(h&&(v=o(v),f=t);++if(v,y))&&((u||h)&&v.push(y),s.push(g)) -}return h?(l(v.g),c(v)):u&&l(v),s}function st(n){return function(t,e,r){var u={};e=d.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r=r)return false;if(typeof n=="string"||!Ue(n)&&It(n))return Te?Te.call(n,t,e):-1e?qe(0,r+e):e)||0,-1o&&(o=a)}}else t=null==t&&It(n)?r:d.createCallback(t,e,3),$t(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Wt(n,t,e,r){var u=3>arguments.length;t=d.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(e=n[++o]);++oarguments.length;return t=d.createCallback(t,r,4),Ft(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) -}),e}function Pt(n){var t=-1,e=n?n.length:0,r=ue(typeof e=="number"?e:0);return $t(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Kt(n,t,e){var r;t=d.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?qe(0,u+r):r||0}else if(r)return r=Ut(t,e),t[r]===e?r:-1;return n(t,e,r)}function Vt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=d.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=h;m?(i&&(i=je(i)),s=f,a=n.apply(l,o)):i||(i=Ne(r,h))}return m&&c?c=je(c):c||t===v||(c=Ne(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Yt(n){return n}function Zt(n){n||(n={});var t=Ge(n),e=t[0],r=n[e]; -return 1!=t.length||r!==r||Et(r)?function(e){for(var r=t.length,u=false;r--&&(u=ft(e[t[r]],n[t[r]],null,true)););return u}:function(n){return n=n[e],r===n&&(0!==r||1/r==1/n)}}function ne(n,t,e){var r=true,u=t&&xt(t);t&&(e||u.length)||(null==e&&(e=t),o=Y,t=n,n=d,u=xt(t)),false===e?r=false:Et(e)&&"chain"in e&&(r=e.chain);var o=n,i=Ot(o);$t(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(Ee.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&Et(i))return this; -i=new o(i),i.__chain__=t}return i})})}function te(){}function ee(n){return function(t){return t[n]}}function re(){return this.__wrapped__}e=e?rt.defaults(Z.Object(),e,rt.pick(Z,F)):Z;var ue=e.Array,oe=e.Boolean,ie=e.Date,ae=e.Function,fe=e.Math,le=e.Number,ce=e.Object,pe=e.RegExp,se=e.String,he=e.TypeError,ve=[],ge=ce.prototype,ye=se.prototype,me=(me=e.window)&&me.document,be=e._,de=ge.toString,_e=pe("^"+se(de).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),we=fe.ceil,je=e.clearTimeout,ke=fe.floor,xe=ae.prototype.toString,Ce=yt(Ce=ce.getPrototypeOf)&&Ce,Oe=ge.hasOwnProperty,Ee=ve.push,Ne=e.setTimeout,Ie=ve.splice,Re=ve.unshift,Se=function(){try{var n={},t=yt(t=ce.defineProperty)&&t,e=t(n,n,n)&&t -}catch(r){}return e}(),Te=yt(Te=ye.contains)&&Te,Ae=yt(Ae=ce.create)&&Ae,De=yt(De=ue.isArray)&&De,$e=e.isFinite,Fe=e.isNaN,Be=yt(Be=ce.keys)&&Be,qe=fe.max,We=fe.min,ze=e.parseInt,Pe=fe.random,Ke={};Ke[q]=ue,Ke[W]=oe,Ke[z]=ie,Ke[P]=ae,Ke[L]=ce,Ke[K]=le,Ke[M]=pe,Ke[V]=se,Y.prototype=d.prototype;var Le=d.support={};Le.funcDecomp=!yt(e.WinRTError)&&D.test(s),Le.funcNames=typeof ae.name=="string";try{Le.dom=11===me.createDocumentFragment().nodeType}catch(Me){Le.dom=false}d.templateSettings={escape:E,evaluate:N,interpolate:I,variable:"",imports:{_:d}},Ae||(et=function(){function n(){}return function(t){if(Et(t)){n.prototype=t; -var r=new n;n.prototype=null}return r||e.Object()}}());var Ve=Se?function(n,t){H.value=t,Se(n,"__bindData__",H)}:te,Ue=De||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&de.call(n)==q||false},Ge=Be?function(n){return Et(n)?Be(n):[]}:g;Le.dom||(Ct=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!He(n)||false});var He=Ce?function(n){if(!n||de.call(n)!=L)return false;var t=n.valueOf,e=yt(t)&&(e=Ce(t))&&Ce(e);return e?n==e||Ce(n)==e:mt(n)}:mt,Je=st(function(n,t,e){Oe.call(n,e)?n[e]++:n[e]=1 -}),Qe=st(function(n,t,e){(Oe.call(n,e)?n[e]:n[e]=[]).push(t)}),Xe=st(function(n,t,e){n[e]=t}),Ye=Bt,Ze=yt(Ze=ie.now)&&Ze||function(){return(new ie).getTime()},nr=8==ze(_+"08")?ze:function(n,t){return ze(It(n)?n.replace(T,""):n,t||0)};return d.after=function(n,t){if(!Ot(t))throw new he;return function(){return 1>--n?t.apply(this,arguments):void 0}},d.assign=_t,d.at=function(n){for(var t=arguments,e=-1,r=at(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=ue(t);++e=b&&o(r?e[r]:s)))}var p=e[0],v=-1,g=p?p.length:0,y=[];n:for(;++v(m?t(m,h):f(s,h))){for(r=u,(m||s).push(h);--r;)if(m=i[r],0>(m?t(m,h):f(e[r],h)))continue n;y.push(h) -}}for(;u--;)(m=i[u])&&c(m);return l(i),l(s),y},d.invert=function(n,t){for(var e=-1,r=Ge(n),u=r.length,o={};++ee?qe(0,r+e):We(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},d.mixin=ne,d.noConflict=function(){return e._=be,this},d.noop=te,d.now=Ze,d.parseInt=nr,d.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(u&&typeof n=="boolean"?(e=n,n=1):typeof t=="boolean"&&(e=t,u=true)),r&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Pe(),We(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t) -},d.reduce=Wt,d.reduceRight=zt,d.result=function(n,t){if(n){var e=n[t];return Ot(e)?n[t]():e}},d.runInContext=s,d.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Ge(n).length},d.some=Kt,d.sortedIndex=Ut,d.template=function(n,t,e){var r=d.templateSettings;n=se(n||""),e=wt({},e,r);var u,o=wt({},e.imports,r.imports),r=Ge(o),o=Rt(o),a=0,f=e.interpolate||A,l="__p+='",f=pe((e.escape||A).source+"|"+f.source+"|"+(f===I?x:A).source+"|"+(e.evaluate||A).source+"|$","g");n.replace(f,function(t,e,r,o,f,c){return r||(r=o),l+=n.slice(a,c).replace($,i),e&&(l+="'+__e("+e+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t -}),l+="';",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(w,""):l).replace(j,"$1").replace(k,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=ae(r,"return "+l).apply(h,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},d.unescape=function(n){return null==n?"":(n=se(n),0>n.indexOf(";")?n:n.replace(R,bt))},d.uniqueId=function(n){var t=++y; -return se(null==n?"":n)+t},d.all=Tt,d.any=Kt,d.detect=Dt,d.findWhere=Dt,d.foldl=Wt,d.foldr=zt,d.include=St,d.inject=Wt,ne(function(){var n={};return jt(d,function(t,e){d.prototype[e]||(n[e]=t)}),n}(),false),d.first=Lt,d.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=d.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:h;return p(n,qe(0,u-r))},d.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Rt(n)),null==t||e?n?n[ct(0,n.length-1)]:h:(n=Pt(n),n.length=We(qe(0,t),n.length),n) -},d.take=Lt,d.head=Lt,jt(d,function(n,t){var e="sample"!==t;d.prototype[t]||(d.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new Y(o,u):o})}),d.VERSION="2.4.1",d.prototype.chain=function(){return this.__chain__=true,this},d.prototype.toString=function(){return se(this.__wrapped__)},d.prototype.value=re,d.prototype.valueOf=re,$t(["join","pop","shift"],function(n){var t=ve[n];d.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments); -return n?new Y(e,n):e}}),$t(["push","reverse","sort","unshift"],function(n){var t=ve[n];d.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),$t(["concat","slice","splice"],function(n){var t=ve[n];d.prototype[n]=function(){return new Y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),d}var h,v=[],g=[],y=0,m=+new Date+"",b=75,d=40,_=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",w=/\b__p\+='';/g,j=/\b(__p\+=)''\+/g,k=/(__e\(.*?\)|\b__t\))\+'';/g,x=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,C=/\w*$/,O=/^\s*function[ \n\r\t]+\w/,E=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,R=/&(?:amp|lt|gt|quot|#39);/g,S=/[&<>"']/g,T=RegExp("^["+_+"]*0+(?=.$)"),A=/($^)/,D=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,F="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),B="[object Arguments]",q="[object Array]",W="[object Boolean]",z="[object Date]",P="[object Function]",K="[object Number]",L="[object Object]",M="[object RegExp]",V="[object String]",U={}; -U[P]=false,U[B]=U[q]=U[W]=U[z]=U[K]=U[L]=U[M]=U[V]=true;var G={leading:false,maxWait:0,trailing:false},H={configurable:false,enumerable:false,value:null,writable:false},J={"&":"&","<":"<",">":">",'"':""","'":"'"},Q={"&":"&","<":"<",">":">",""":'"',"'":"'"},X={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},Y={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},Z=X[typeof window]&&window||this,nt=X[typeof exports]&&exports&&!exports.nodeType&&exports,tt=X[typeof global]&&global; -!tt||tt.global!==tt&&tt.window!==tt||(Z=tt);var et=(tt=X[typeof module]&&module&&!module.nodeType&&module)&&tt.exports===nt&&nt,rt=s();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Z._=rt, define(function(){return rt})):nt&&tt?et?(tt.exports=rt)._=rt:nt._=rt:Z._=rt}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne?0:e);++r=_&&o===t,l=[]; +if(f){var c=a(r);c?(o=e,r=c):f=false}for(;++uo(r,c)&&l.push(c);return f&&s(r),l}function ft(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r=_&&i===t,v=u||h?l():c;for(h&&(v=a(v),i=e);++oi(v,y))&&((u||h)&&v.push(y),c.push(g)) +}return h?(p(v.g),s(v)):u&&p(v),c}function ht(n){return function(t,e,r){var u={};e=m.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r=r)return false;if(typeof n=="string"||!Ge(n)&&Rt(n))return Ae?Ae.call(n,t,e):-1e?We(0,r+e):e)||0,-1o&&(o=a)}}else t=null==t&&Rt(n)?u:m.createCallback(t,e,3),Ft(n,function(n,e,u){e=t(n,e,u),e>r&&(r=e,o=n)});return o}function zt(n,t,e,r){var u=3>arguments.length;t=m.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(e=n[++o]);++oarguments.length;return t=m.createCallback(t,r,4),Bt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) +}),e}function Kt(n){var t=-1,e=n?n.length:0,r=oe(typeof e=="number"?e:0);return Ft(n,function(n){var e=pt(0,++t);r[t]=r[e],r[e]=n}),r}function Lt(n,t,e){var r;t=m.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?We(0,u+r):r||0}else if(r)return r=Gt(n,e),n[r]===e?r:-1;return t(n,e,r)}function Ut(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=g;m?(i&&(i=ke(i)),s=f,a=n.apply(l,o)):i||(i=Ie(r,g))}return m&&c?c=ke(c):c||t===h||(c=Ie(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Zt(n){return n}function ne(n){n||(n={});var t=He(n),e=t[0],r=n[e]; +return 1!=t.length||r!==r||Nt(r)?function(e){for(var r=t.length,u=false;r--&&(u=lt(e[t[r]],n[t[r]],null,true)););return u}:function(n){return n=n[e],r===n&&(0!==r||1/r==1/n)}}function te(n,t,e){var r=true,u=t&&Ct(t);t&&(e||u.length)||(null==e&&(e=t),o=w,t=n,n=m,u=Ct(t)),false===e?r=false:Nt(e)&&"chain"in e&&(r=e.chain);var o=n,i=Et(o);Ft(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(Ne.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&Nt(i))return this; +i=new o(i),i.__chain__=t}return i})})}function ee(){}function re(n){return function(t){return t[n]}}function ue(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var oe=n.Array,ie=n.Boolean,ae=n.Date,fe=n.Function,le=n.Math,ce=n.Number,pe=n.Object,se=n.RegExp,he=n.String,ve=n.TypeError,ge=[],ye=pe.prototype,me=he.prototype,be=(be=n.window)&&be.document,de=n._,_e=ye.toString,we=se("^"+he(_e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),je=le.ceil,ke=n.clearTimeout,xe=le.floor,Ce=fe.prototype.toString,Oe=mt(Oe=pe.getPrototypeOf)&&Oe,Ee=ye.hasOwnProperty,Ne=ge.push,Ie=n.setTimeout,Re=ge.splice,Se=ge.unshift,Te=function(){try{var n={},t=mt(t=pe.defineProperty)&&t,e=t(n,n,n)&&t +}catch(r){}return e}(),Ae=mt(Ae=me.contains)&&Ae,De=mt(De=pe.create)&&De,$e=mt($e=oe.isArray)&&$e,Fe=n.isFinite,Be=n.isNaN,qe=mt(qe=pe.keys)&&qe,We=le.max,ze=le.min,Pe=n.parseInt,Ke=le.random,Le={};Le[z]=oe,Le[P]=ie,Le[K]=ae,Le[L]=fe,Le[V]=pe,Le[M]=ce,Le[U]=se,Le[G]=he,w.prototype=m.prototype;var Me=m.support={};Me.funcDecomp=!mt(n.WinRTError)&&F.test(v),Me.funcNames=typeof fe.name=="string";try{Me.dom=11===be.createDocumentFragment().nodeType}catch(Ve){Me.dom=false}m.templateSettings={escape:I,evaluate:R,interpolate:S,variable:"",imports:{_:m}},De||(rt=function(){function t(){}return function(e){if(Nt(e)){t.prototype=e; +var r=new t;t.prototype=null}return r||n.Object()}}());var Ue=Te?function(n,t){Q.value=t,Te(n,"__bindData__",Q)}:ee,Ge=$e||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&_e.call(n)==z||false},He=qe?function(n){return Nt(n)?qe(n):[]}:y;Me.dom||(Ot=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!Je(n)||false});var Je=Oe?function(n){if(!n||_e.call(n)!=V)return false;var t=n.valueOf,e=mt(t)&&(e=Oe(t))&&Oe(e);return e?n==e||Oe(n)==e:bt(n)}:bt,Qe=ht(function(n,t,e){Ee.call(n,e)?n[e]++:n[e]=1 +}),Xe=ht(function(n,t,e){(Ee.call(n,e)?n[e]:n[e]=[]).push(t)}),Ye=ht(function(n,t,e){n[e]=t}),Ze=qt,nr=mt(nr=ae.now)&&nr||function(){return(new ae).getTime()},tr=8==Pe(j+"08")?Pe:function(n,t){return Pe(Rt(n)?n.replace(D,""):n,t||0)};return m.after=function(n,t){if(!Et(t))throw new ve;return function(){return 1>--n?t.apply(this,arguments):void 0}},m.assign=wt,m.at=function(n){for(var t=arguments,e=-1,r=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=oe(t);++e=_&&a(r?n[r]:c)))}var f=n[0],v=-1,g=f?f.length:0,y=[];n:for(;++v(m?e(m,h):i(c,h))){for(r=u,(m||c).push(h);--r;)if(m=o[r],0>(m?e(m,h):i(n[r],h)))continue n;y.push(h) +}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var e=-1,r=He(n),u=r.length,o={};++ee?We(0,r+e):ze(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},m.mixin=te,m.noConflict=function(){return n._=de,this},m.noop=ee,m.now=nr,m.parseInt=tr,m.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(u&&typeof n=="boolean"?(e=n,n=1):typeof t=="boolean"&&(e=t,u=true)),r&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Ke(),ze(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):pt(n,t) +},m.reduce=zt,m.reduceRight=Pt,m.result=function(n,t){if(n){var e=n[t];return Et(e)?n[t]():e}},m.runInContext=v,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:He(n).length},m.some=Lt,m.sortedIndex=Gt,m.template=function(n,t,e){var r=m.templateSettings;n=he(n||""),e=jt({},e,r);var u,o=jt({},e.imports,r.imports),r=He(o),o=St(o),i=0,a=e.interpolate||$,l="__p+='",a=se((e.escape||$).source+"|"+a.source+"|"+(a===S?O:$).source+"|"+(e.evaluate||$).source+"|$","g");n.replace(a,function(t,e,r,o,a,c){return r||(r=o),l+=n.slice(i,c).replace(B,f),e&&(l+="'+__e("+e+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t +}),l+="';",a=e=e.variable,a||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+e+"){"+(a?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=fe(r,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=he(n),0>n.indexOf(";")?n:n.replace(T,dt))},m.uniqueId=function(n){var t=++b; +return he(null==n?"":n)+t},m.all=At,m.any=Lt,m.detect=$t,m.findWhere=$t,m.foldl=zt,m.foldr=Pt,m.include=Tt,m.inject=zt,te(function(){var n={};return kt(m,function(t,e){m.prototype[e]||(n[e]=t)}),n}(),false),m.first=Mt,m.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:g;return h(n,We(0,u-r))},m.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=St(n)),null==t||e?n?n[pt(0,n.length-1)]:g:(n=Kt(n),n.length=ze(We(0,t),n.length),n) +},m.take=Mt,m.head=Mt,kt(m,function(n,t){var e="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return he(this.__wrapped__)},m.prototype.value=ue,m.prototype.valueOf=ue,Ft(["join","pop","shift"],function(n){var t=ge[n];m.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments); +return n?new w(e,n):e}}),Ft(["push","reverse","sort","unshift"],function(n){var t=ge[n];m.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Ft(["concat","slice","splice"],function(n){var t=ge[n];m.prototype[n]=function(){return new w(t.apply(this.__wrapped__,arguments),this.__chain__)}}),m}var g,y=[],m=[],b=0,d=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,O=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,E=/\w*$/,N=/^\s*function[ \n\r\t]+\w/,I=/<%-([\s\S]+?)%>/g,R=/<%([\s\S]+?)%>/g,S=/<%=([\s\S]+?)%>/g,T=/&(?:amp|lt|gt|quot|#39);/g,A=/[&<>"']/g,D=RegExp("^["+j+"]*0+(?=.$)"),$=/($^)/,F=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="[object Arguments]",z="[object Array]",P="[object Boolean]",K="[object Date]",L="[object Function]",M="[object Number]",V="[object Object]",U="[object RegExp]",G="[object String]",H={}; +H[L]=false,H[W]=H[z]=H[P]=H[K]=H[M]=H[V]=H[U]=H[G]=true;var J={leading:false,maxWait:0,trailing:false},Q={configurable:false,enumerable:false,value:null,writable:false},X={"&":"&","<":"<",">":">",'"':""","'":"'"},Y={"&":"&","<":"<",">":">",""":'"',"'":"'"},Z={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},nt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},tt=Z[typeof window]&&window||this,et=Z[typeof exports]&&exports&&!exports.nodeType&&exports,rt=Z[typeof global]&&global; +!rt||rt.global!==rt&&rt.window!==rt||(tt=rt);var ut=(rt=Z[typeof module]&&module&&!module.nodeType&&module)&&rt.exports===et&&et,ot=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):et&&rt?ut?(rt.exports=ot)._=ot:et._=ot:tt._=ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 84f600d609..7c3fd3d24a 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -113,6 +113,27 @@ /*--------------------------------------------------------------------------*/ + /** + * The base implementation of `compareAscending` used to compare values and + * sort them in ascending order without guaranteeing a stable sort. + * + * @private + * @param {*} a The value to compare to `b`. + * @param {*} b The value to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. + */ + function baseCompareAscending(a, b) { + if (a !== b) { + if (a > b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return 0; + } + /** * The base implementation of `_.indexOf` without support for binary searches * or `fromIndex` constraints. @@ -136,40 +157,16 @@ } /** - * Used by `sortBy` to compare transformed `collection` elements, stable sorting - * them in ascending order. + * Used by `sortBy` to compare transformed elements of a collection and stable + * sort them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator of `1` or `-1`. + * @returns {number} Returns the sort order indicator for `a`. */ function compareAscending(a, b) { - var ac = a.criteria, - bc = b.criteria, - index = -1, - length = ac.length; - - while (++index < length) { - var value = ac[index], - other = bc[index]; - - if (value !== other) { - if (value > other || typeof value == 'undefined') { - return 1; - } - if (value < other || typeof other == 'undefined') { - return -1; - } - } - } - // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to return the same value for - // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 - // - // This also ensures a stable sort in V8 and other engines. - // See http://code.google.com/p/v8/issues/detail?id=90 - return a.index - b.index; + return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; } /** @@ -2694,6 +2691,7 @@ result[index] = result[rand]; result[rand] = value; }); + return result; } @@ -2842,7 +2840,7 @@ callback = createCallback(callback, thisArg, 3); forEach(collection, function(value, key, collection) { result[++index] = { - 'criteria': [callback(value, key, collection)], + 'criteria': callback(value, key, collection), 'index': index, 'value': value }; diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index 451157bcb4..271fd0471c 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -3,7 +3,7 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js` */ -;(function(){function n(n,t,r){r=(r||0)-1;for(var e=n?n.length:0;++rf||typeof i=="undefined")return 1;if(ir?0:r);++ee||typeof r=="undefined"){r=1;break n}if(rr?0:r);++ee(t,i)&&o.push(i)}return o}function p(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++ei(a,e)){for(t=r;--t;)if(0>i(n[t],e))continue n;a.push(e)}return a},u.invert=function(n,t){for(var r=-1,e=Lt(n),u=e.length,o={};++rt?0:t);++n b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return 0; + } + /** * The base implementation of `_.indexOf` without support for binary searches * or `fromIndex` constraints. @@ -286,36 +307,42 @@ } /** - * Used by `sortBy` to compare transformed `collection` elements, stable sorting - * them in ascending order. + * Used by `sortBy` to compare transformed elements of a collection and stable + * sort them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator of `1` or `-1`. + * @returns {number} Returns the sort order indicator for `a`. */ function compareAscending(a, b) { + return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; + } + + /** + * Used by `sortBy` to compare multiple properties of each element in a + * collection and stable sort them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. + */ + function compareMultipleAscending(a, b) { var ac = a.criteria, bc = b.criteria, index = -1, length = ac.length; while (++index < length) { - var value = ac[index], - other = bc[index]; - - if (value !== other) { - if (value > other || typeof value == 'undefined') { - return 1; - } - if (value < other || typeof other == 'undefined') { - return -1; - } + var result = baseCompareAscending(ac[index], bc[index]); + if (result) { + return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to return the same value for - // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provided the same value + // for `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See http://code.google.com/p/v8/issues/detail?id=90 @@ -4274,6 +4301,7 @@ result[index] = result[rand]; result[rand] = value; }); + return result; } @@ -4416,32 +4444,27 @@ */ function sortBy(collection, callback, thisArg) { var index = -1, - isArr = isArray(callback), + multi = callback && isArray(callback), length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); - if (!isArr) { + if (!multi) { callback = lodash.createCallback(callback, thisArg, 3); } forEach(collection, function(value, key, collection) { var object = result[++index] = getObject(); - if (isArr) { - object.criteria = map(callback, function(key) { return value[key]; }); - } else { - (object.criteria = getArray())[0] = callback(value, key, collection); - } object.index = index; object.value = value; + object.criteria = multi + ? map(callback, function(key) { return value[key]; }) + : callback(value, key, collection); }); length = result.length; - result.sort(compareAscending); + result.sort(multi ? compareMultipleAscending : compareAscending); while (length--) { var object = result[length]; result[length] = object.value; - if (!isArr) { - releaseArray(object.criteria); - } releaseObject(object); } return result; From 106fa64060a21b265c07e5b9bc2907703765ef30 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 29 Dec 2013 15:49:26 -0600 Subject: [PATCH 0088/1608] Cleanup `arrayReg` and `splice` references. --- dist/lodash.compat.js | 13 ++------- dist/lodash.compat.min.js | 4 +-- dist/lodash.js | 11 ++----- dist/lodash.min.js | 2 +- dist/lodash.underscore.js | 16 ++++------- dist/lodash.underscore.min.js | 54 +++++++++++++++++------------------ lodash.js | 13 ++------- 7 files changed, 43 insertions(+), 70 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 4a465de2f0..1a913ba219 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -530,16 +530,9 @@ String = context.String, TypeError = context.TypeError; - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - /** Used for native method references */ - var errorProto = Error.prototype, + var arrayRef = Array.prototype, + errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype; @@ -828,7 +821,7 @@ * @memberOf _.support * @type boolean */ - support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]); + support.spliceObjects = (splice.call(object, 0, 1), !object[0]); /** * Detect lack of support for accessing string characters by index. diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index e3c34ea384..5d4cbb3e63 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -29,9 +29,9 @@ for(t=e.createCallback(t,r,3);++ar?0:r);++t=y;m?(u&&(u=Er(u)),c=a,o=n.apply(i,e)):u||(u=Pr(v,y))}return m&&f?f=Er(f):f||t===p||(f=Pr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function rr(n){return n}function er(n){n||(n={});var t=ne(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Nt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function ur(n,t,r){var u=true,o=t&&St(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=St(t)),false===r?u=false:Nt(r)&&"chain"in r&&(u=r.chain); -var a=n,i=At(a);Bt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Rr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Nt(o))return this;o=new a(o),o.__chain__=t}return o})})}function or(){}function ar(n){return function(t){return t[n]}}function ir(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var fr=n.Array,lr=n.Boolean,cr=n.Date,pr=n.Function,sr=n.Math,gr=n.Number,hr=n.Object,vr=n.RegExp,yr=n.String,mr=n.TypeError,dr=[],br=n.Error.prototype,_r=hr.prototype,wr=yr.prototype,jr=(jr=n.window)&&jr.document,xr=n._,Cr=_r.toString,kr=vr("^"+yr(Cr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Or=sr.ceil,Er=n.clearTimeout,Sr=sr.floor,Ir=pr.prototype.toString,Ar=_t(Ar=hr.getPrototypeOf)&&Ar,Nr=_r.hasOwnProperty,Rr=dr.push,Tr=_r.propertyIsEnumerable,Pr=n.setTimeout,Dr=dr.splice,$r=dr.unshift,qr=function(){try{var n={},t=_t(t=hr.defineProperty)&&t,r=t(n,n,n)&&t +var a=n,i=At(a);Bt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Rr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Nt(o))return this;o=new a(o),o.__chain__=t}return o})})}function or(){}function ar(n){return function(t){return t[n]}}function ir(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var fr=n.Array,lr=n.Boolean,cr=n.Date,pr=n.Function,sr=n.Math,gr=n.Number,hr=n.Object,vr=n.RegExp,yr=n.String,mr=n.TypeError,dr=fr.prototype,br=n.Error.prototype,_r=hr.prototype,wr=yr.prototype,jr=(jr=n.window)&&jr.document,xr=n._,Cr=_r.toString,kr=vr("^"+yr(Cr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Or=sr.ceil,Er=n.clearTimeout,Sr=sr.floor,Ir=pr.prototype.toString,Ar=_t(Ar=hr.getPrototypeOf)&&Ar,Nr=_r.hasOwnProperty,Rr=dr.push,Tr=_r.propertyIsEnumerable,Pr=n.setTimeout,Dr=dr.splice,$r=dr.unshift,qr=function(){try{var n={},t=_t(t=hr.defineProperty)&&t,r=t(n,n,n)&&t }catch(e){}return r}(),Fr=_t(Fr=wr.contains)&&Fr,Br=_t(Br=hr.create)&&Br,Lr=_t(Lr=fr.isArray)&&Lr,Wr=n.isFinite,zr=n.isNaN,Kr=_t(Kr=hr.keys)&&Kr,Mr=sr.max,Vr=sr.min,Ur=n.parseInt,Gr=sr.random,Hr={};Hr[z]=fr,Hr[K]=lr,Hr[M]=cr,Hr[U]=pr,Hr[H]=hr,Hr[G]=gr,Hr[J]=vr,Hr[Q]=yr;var Jr={};Jr[z]=Jr[M]=Jr[G]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Jr[K]=Jr[Q]={constructor:true,toString:true,valueOf:true},Jr[V]=Jr[U]=Jr[J]={constructor:true,toString:true},Jr[H]={constructor:true},function(){for(var n=L.length;n--;){var t,r=L[n]; -for(t in Jr)Nr.call(Jr,t)&&!Nr.call(Jr[t],r)&&(Jr[t][r]=false)}}(),m.prototype=e.prototype;var Qr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Qr.argsClass=Cr.call(arguments)==W,Qr.argsObject=arguments.constructor==hr&&!(arguments instanceof fr),Qr.enumErrorProps=Tr.call(br,"message")||Tr.call(br,"name"),Qr.enumPrototypes=Tr.call(t,"prototype"),Qr.funcDecomp=!_t(n.WinRTError)&&q.test(v),Qr.funcNames=typeof pr.name=="string",Qr.nonEnumArgs=0!=u,Qr.nonEnumShadows=!/valueOf/.test(e),Qr.ownLast="x"!=e[0],Qr.spliceObjects=(dr.splice.call(r,0,1),!r[0]),Qr.unindexedChars="xx"!="x"[0]+hr("x")[0]; +for(t in Jr)Nr.call(Jr,t)&&!Nr.call(Jr[t],r)&&(Jr[t][r]=false)}}(),m.prototype=e.prototype;var Qr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Qr.argsClass=Cr.call(arguments)==W,Qr.argsObject=arguments.constructor==hr&&!(arguments instanceof fr),Qr.enumErrorProps=Tr.call(br,"message")||Tr.call(br,"name"),Qr.enumPrototypes=Tr.call(t,"prototype"),Qr.funcDecomp=!_t(n.WinRTError)&&q.test(v),Qr.funcNames=typeof pr.name=="string",Qr.nonEnumArgs=0!=u,Qr.nonEnumShadows=!/valueOf/.test(e),Qr.ownLast="x"!=e[0],Qr.spliceObjects=(Dr.call(r,0,1),!r[0]),Qr.unindexedChars="xx"!="x"[0]+hr("x")[0]; try{Qr.dom=11===jr.createDocumentFragment().nodeType}catch(o){Qr.dom=false}try{Qr.nodeClass=!(Cr.call(undefined)==H&&!({toString:0}+""))}catch(a){Qr.nodeClass=true}}(1),e.templateSettings={escape:A,evaluate:N,interpolate:R,variable:"",imports:{_:e}},Br||(et=function(){function t(){}return function(r){if(Nt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var Xr=qr?function(n,t){Z.value=t,qr(n,"__bindData__",Z)}:or;Qr.argsClass||(xt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n,"callee")&&!Tr.call(n,"callee")||false });var Yr=Lr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Cr.call(n)==z||false},Zr=mt({a:"p",b:"[]",e:"",c:"s.push(l)",f:true}),ne=Kr?function(n){return Nt(n)?Qr.enumPrototypes&&typeof n=="function"||Qr.nonEnumArgs&&n.length&&xt(n)?Zr(n):Kr(n):[]}:Zr,te=mt({a:"p,b,x",b:"p",e:"b=b&&typeof x=='undefined'?b:a(b,x,3)",c:"if(b(p[l],l,p)===false){return s}",f:false});Qr.dom||(It=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!re(n)||false}),At(/x/)&&(At=function(n){return typeof n=="function"&&Cr.call(n)==U });var re=Ar?function(n){if(!n||Cr.call(n)!=H||!Qr.argsClass&&xt(n))return false;var t=n.valueOf,r=_t(t)&&(r=Ar(t))&&Ar(r);return r?n==r||Ar(n)==r:wt(n)}:wt,ee=vt(function(n,t,r){Nr.call(n,r)?n[r]++:n[r]=1}),ue=vt(function(n,t,r){(Nr.call(n,r)?n[r]:n[r]=[]).push(t)}),oe=vt(function(n,t,r){n[r]=t}),ae=Wt,ie=_t(ie=cr.now)&&ie||function(){return(new cr).getTime()},fe=8==Ur(x+"08")?Ur:function(n,t){return Ur(Tt(n)?n.replace(D,""):n,t||0)};return e.after=function(n,t){if(!At(t))throw new mr;return function(){return 1>--n?t.apply(this,arguments):void 0 diff --git a/dist/lodash.js b/dist/lodash.js index b74a8b3551..d4a8c879ef 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -506,16 +506,9 @@ String = context.String, TypeError = context.TypeError; - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - /** Used for native method references */ - var objectProto = Object.prototype, + var arrayRef = Array.prototype, + objectProto = Object.prototype, stringProto = String.prototype; /** Used to detect DOM support */ diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 4b30bf3226..7ff353f633 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -27,7 +27,7 @@ for(var i=n.length;++eo&&(o=a)}}else t=null==t&&Rt(n)?u:m.crea }function Jt(){for(var n=1e?0:e);++t=g;m?(i&&(i=ke(i)),s=f,a=n.apply(l,o)):i||(i=Ie(r,g))}return m&&c?c=ke(c):c||t===h||(c=Ie(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Zt(n){return n}function ne(n){n||(n={});var t=He(n),e=t[0],r=n[e]; return 1!=t.length||r!==r||Nt(r)?function(e){for(var r=t.length,u=false;r--&&(u=lt(e[t[r]],n[t[r]],null,true)););return u}:function(n){return n=n[e],r===n&&(0!==r||1/r==1/n)}}function te(n,t,e){var r=true,u=t&&Ct(t);t&&(e||u.length)||(null==e&&(e=t),o=w,t=n,n=m,u=Ct(t)),false===e?r=false:Nt(e)&&"chain"in e&&(r=e.chain);var o=n,i=Et(o);Ft(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(Ne.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&Nt(i))return this; -i=new o(i),i.__chain__=t}return i})})}function ee(){}function re(n){return function(t){return t[n]}}function ue(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var oe=n.Array,ie=n.Boolean,ae=n.Date,fe=n.Function,le=n.Math,ce=n.Number,pe=n.Object,se=n.RegExp,he=n.String,ve=n.TypeError,ge=[],ye=pe.prototype,me=he.prototype,be=(be=n.window)&&be.document,de=n._,_e=ye.toString,we=se("^"+he(_e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),je=le.ceil,ke=n.clearTimeout,xe=le.floor,Ce=fe.prototype.toString,Oe=mt(Oe=pe.getPrototypeOf)&&Oe,Ee=ye.hasOwnProperty,Ne=ge.push,Ie=n.setTimeout,Re=ge.splice,Se=ge.unshift,Te=function(){try{var n={},t=mt(t=pe.defineProperty)&&t,e=t(n,n,n)&&t +i=new o(i),i.__chain__=t}return i})})}function ee(){}function re(n){return function(t){return t[n]}}function ue(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var oe=n.Array,ie=n.Boolean,ae=n.Date,fe=n.Function,le=n.Math,ce=n.Number,pe=n.Object,se=n.RegExp,he=n.String,ve=n.TypeError,ge=oe.prototype,ye=pe.prototype,me=he.prototype,be=(be=n.window)&&be.document,de=n._,_e=ye.toString,we=se("^"+he(_e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),je=le.ceil,ke=n.clearTimeout,xe=le.floor,Ce=fe.prototype.toString,Oe=mt(Oe=pe.getPrototypeOf)&&Oe,Ee=ye.hasOwnProperty,Ne=ge.push,Ie=n.setTimeout,Re=ge.splice,Se=ge.unshift,Te=function(){try{var n={},t=mt(t=pe.defineProperty)&&t,e=t(n,n,n)&&t }catch(r){}return e}(),Ae=mt(Ae=me.contains)&&Ae,De=mt(De=pe.create)&&De,$e=mt($e=oe.isArray)&&$e,Fe=n.isFinite,Be=n.isNaN,qe=mt(qe=pe.keys)&&qe,We=le.max,ze=le.min,Pe=n.parseInt,Ke=le.random,Le={};Le[z]=oe,Le[P]=ie,Le[K]=ae,Le[L]=fe,Le[V]=pe,Le[M]=ce,Le[U]=se,Le[G]=he,w.prototype=m.prototype;var Me=m.support={};Me.funcDecomp=!mt(n.WinRTError)&&F.test(v),Me.funcNames=typeof fe.name=="string";try{Me.dom=11===be.createDocumentFragment().nodeType}catch(Ve){Me.dom=false}m.templateSettings={escape:I,evaluate:R,interpolate:S,variable:"",imports:{_:m}},De||(rt=function(){function t(){}return function(e){if(Nt(e)){t.prototype=e; var r=new t;t.prototype=null}return r||n.Object()}}());var Ue=Te?function(n,t){Q.value=t,Te(n,"__bindData__",Q)}:ee,Ge=$e||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&_e.call(n)==z||false},He=qe?function(n){return Nt(n)?qe(n):[]}:y;Me.dom||(Ot=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!Je(n)||false});var Je=Oe?function(n){if(!n||_e.call(n)!=V)return false;var t=n.valueOf,e=mt(t)&&(e=Oe(t))&&Oe(e);return e?n==e||Oe(n)==e:bt(n)}:bt,Qe=ht(function(n,t,e){Ee.call(n,e)?n[e]++:n[e]=1 }),Xe=ht(function(n,t,e){(Ee.call(n,e)?n[e]:n[e]=[]).push(t)}),Ye=ht(function(n,t,e){n[e]=t}),Ze=qt,nr=mt(nr=ae.now)&&nr||function(){return(new ae).getTime()},tr=8==Pe(j+"08")?Pe:function(n,t){return Pe(Rt(n)?n.replace(D,""):n,t||0)};return m.after=function(n,t){if(!Et(t))throw new ve;return function(){return 1>--n?t.apply(this,arguments):void 0}},m.assign=wt,m.at=function(n){for(var t=arguments,e=-1,r=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=oe(t);++ee||typeof r=="undefined"){r=1;break n}if(rr?0:r);++ee(t,i)&&o.push(i)}return o}function p(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(r&&f.push(l),i.push(a))}return i}function h(n){return function(t,r,e){var u={};r=X(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++ee(t,i)&&o.push(i)}return o}function p(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(r&&f.push(l),i.push(a))}return i}function h(n){return function(t,r,e){var u={};r=X(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++eu&&(u=r); -else t=X(t,r,3),$(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function W(n,t,r,e){var u=3>arguments.length;t=X(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=X(t,e,4),D(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function C(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r;r=++t,r=0+Bt(Gt()*(r-0+1)),e[t]=e[r],e[r]=n -}),e}function P(n,t,r){var e;t=X(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Ut(0,u+e):e||0}else if(e)return e=J(t,r),t[e]===r?e:-1; -return n(t,r,e)}function H(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,i=n?n.length:0;for(t=X(t,r,3);++o>>1,r(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||t===p||(a=setTimeout(h,t)),r&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,t,r){var e=typeof n;return null==n||"function"==e?a(n,t,r):"object"!=e?tt(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var t=Lt(n);return function(r){for(var e=t.length,u=false;e--&&(u=r[t[e]]===n[t[e]]););return u}}function nt(n){$(T(n),function(t){var r=u[t]=n[t]; +}function D(n,t){var r=n?n.length:0;if(typeof r=="number")for(;r--&&false!==t(n[r],r,n););else{var e=Qt(n),r=e.length;x(n,function(n,u,o){return u=e?e[--r]:--r,false===t(o[u],u,o)&&ut})}}function I(n,t,r){var e=-1,u=n?n.length:0;if(t=X(t,r,3),typeof u=="number")for(var o=Array(u);++eu&&(u=r); +else t=X(t,r,3),$(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function W(n,t,r,e){var u=3>arguments.length;t=X(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=X(t,e,4),D(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function C(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r;r=++t,r=0+Bt(Ht()*(r-0+1)),e[t]=e[r],e[r]=n +}),e}function P(n,t,r){var e;t=X(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Vt(0,u+e):e||0}else if(e)return e=J(t,r),t[e]===r?e:-1; +return n(t,r,e)}function H(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,i=n?n.length:0;for(t=X(t,r,3);++o>>1,r(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||t===p||(a=setTimeout(h,t)),r&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,t,r){var e=typeof n;return null==n||"function"==e?a(n,t,r):"object"!=e?tt(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var t=Qt(n);return function(r){for(var e=t.length,u=false;e--&&(u=r[t[e]]===n[t[e]]););return u}}function nt(n){$(T(n),function(t){var r=u[t]=n[t]; u.prototype[t]=function(){var n=[this.__wrapped__];return Dt.apply(n,arguments),n=r.apply(u,n),this.__chain__?new o(n,true):n}})}function tt(n){return function(t){return t[n]}}var rt,et=0,ut={},ot=+new Date+"",it=/&(?:amp|lt|gt|quot|#x27);/g,ft=/[&<>"']/g,at=/($^)/,lt=/['\n\r\t\u2028\u2029\\]/g,ct="[object Arguments]",pt="[object Array]",st="[object Boolean]",gt="[object Date]",ht="[object Number]",vt="[object Object]",yt="[object RegExp]",mt="[object String]",_t={"&":"&","<":"<",">":">",'"':""","'":"'"},dt={"&":"&","<":"<",">":">",""":'"',"'":"'"},bt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},wt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},jt=bt[typeof window]&&window||this,xt=bt[typeof exports]&&exports&&!exports.nodeType&&exports,Tt=bt[typeof global]&&global; -!Tt||Tt.global!==Tt&&Tt.window!==Tt||(jt=Tt);var At=bt[typeof module]&&module&&!module.nodeType&&module,Et=At&&At.exports===xt&&xt,Ot=[],St=Object.prototype,kt=jt._,Nt=St.toString,qt=RegExp("^"+(Nt+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ft=Math.ceil,Bt=Math.floor,Rt=Function.prototype.toString,$t=St.hasOwnProperty,Dt=Ot.push,It=St.propertyIsEnumerable,Mt=_(Mt=Object.create)&&Mt,Wt=_(Wt=Array.isArray)&&Wt,zt=jt.isFinite,Ct=jt.isNaN,Pt=_(Pt=Object.keys)&&Pt,Ut=Math.max,Vt=Math.min,Gt=Math.random; -o.prototype=u.prototype;var Ht={};!function(){var n={0:1,length:1};Ht.spliceObjects=(Ot.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Mt||(f=function(){function n(){}return function(t){if(O(t)){n.prototype=t;var r=new n;n.prototype=null}return r||jt.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$t.call(n,"callee")&&!It.call(n,"callee")||false});var Jt=Wt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nt.call(n)==pt||false -},Kt=function(n){var t=[];if(!n||!bt[typeof n])return t;for(var r in n)$t.call(n,r)&&t.push(r);return t},Lt=Pt?function(n){return O(n)?Pt(n):[]}:Kt,Qt=function(n,t){if(!n||!bt[typeof n])return n;for(var r in n)if(t(n[r],r,n)===ut)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nt.call(n)});var Xt=h(function(n,t,r){$t.call(n,r)?n[r]++:n[r]=1}),Yt=h(function(n,t,r){($t.call(n,r)?n[r]:n[r]=[]).push(t)}),Zt=h(function(n,t,r){n[r]=t}),nr=I,tr=_(tr=Date.now)&&tr||function(){return(new Date).getTime() +!Tt||Tt.global!==Tt&&Tt.window!==Tt||(jt=Tt);var At=bt[typeof module]&&module&&!module.nodeType&&module,Et=At&&At.exports===xt&&xt,Ot=Array.prototype,St=Object.prototype,kt=jt._,Nt=St.toString,qt=RegExp("^"+(Nt+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ft=Math.ceil,Bt=Math.floor,Rt=Function.prototype.toString,$t=St.hasOwnProperty,Dt=Ot.push,It=St.propertyIsEnumerable,Mt=Ot.splice,Wt=_(Wt=Object.create)&&Wt,zt=_(zt=Array.isArray)&&zt,Ct=jt.isFinite,Pt=jt.isNaN,Ut=_(Ut=Object.keys)&&Ut,Vt=Math.max,Gt=Math.min,Ht=Math.random; +o.prototype=u.prototype;var Jt={};!function(){var n={0:1,length:1};Jt.spliceObjects=(Mt.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Wt||(f=function(){function n(){}return function(t){if(O(t)){n.prototype=t;var r=new n;n.prototype=null}return r||jt.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$t.call(n,"callee")&&!It.call(n,"callee")||false});var Kt=zt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nt.call(n)==pt||false +},Lt=function(n){var t=[];if(!n||!bt[typeof n])return t;for(var r in n)$t.call(n,r)&&t.push(r);return t},Qt=Ut?function(n){return O(n)?Ut(n):[]}:Lt,Xt=function(n,t){if(!n||!bt[typeof n])return n;for(var r in n)if(t(n[r],r,n)===ut)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nt.call(n)});var Yt=h(function(n,t,r){$t.call(n,r)?n[r]++:n[r]=1}),Zt=h(function(n,t,r){($t.call(n,r)?n[r]:n[r]=[]).push(t)}),nr=h(function(n,t,r){n[r]=t}),tr=I,rr=_(rr=Date.now)&&rr||function(){return(new Date).getTime() };u.after=function(n,t){if(!E(t))throw new TypeError;return function(){return 1>--n?t.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var t=1i(a,e)){for(t=r;--t;)if(0>i(n[t],e))continue n;a.push(e)}return a},u.invert=function(n,t){for(var r=-1,e=Lt(n),u=e.length,o={};++rt?0:t);++nr?Ut(0,e+r):Vt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=nt,u.noConflict=function(){return jt._=kt,this},u.random=function(n,t){return null==n&&null==t&&(t=1),n=+n||0,null==t?(t=n,n=0):t=+t||0,n+Bt(Gt()*(t-n+1)) -},u.reduce=W,u.reduceRight=z,u.result=function(n,t){if(n){var r=n[t];return E(r)?n[t]():r}},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Lt(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,t,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||at).source+"|"+(e.interpolate||at).source+"|"+(e.evaluate||at).source+"|$","g"),function(t,e,u,o,i){return a+=n.slice(f,i).replace(lt,r),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+t.length,t +return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},u.countBy=Yt,u.debounce=Q,u.defaults=j,u.defer=function(n){if(!E(n))throw new TypeError;var t=e(arguments,1);return setTimeout(function(){n.apply(rt,t)},1)},u.delay=function(n,t){if(!E(n))throw new TypeError;var r=e(arguments,2);return setTimeout(function(){n.apply(rt,r)},t)},u.difference=function(n){return c(n,p(arguments,true,true,1))},u.filter=B,u.flatten=function(n,t){return p(n,t)},u.forEach=$,u.functions=T,u.groupBy=Zt,u.indexBy=nr,u.initial=function(n,t,r){var u=0,o=n?n.length:0; +if(typeof t!="number"&&null!=t){var i=o;for(t=X(t,r,3);i--&&t(n[i],i,n);)u++}else u=null==t||r?1:t||u;return e(n,0,Gt(Vt(0,o-u),o))},u.intersection=function(){for(var n=[],t=-1,r=arguments.length;++ti(a,e)){for(t=r;--t;)if(0>i(n[t],e))continue n;a.push(e)}return a},u.invert=function(n,t){for(var r=-1,e=Qt(n),u=e.length,o={};++rt?0:t);++nr?Vt(0,e+r):Gt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=nt,u.noConflict=function(){return jt._=kt,this},u.random=function(n,t){return null==n&&null==t&&(t=1),n=+n||0,null==t?(t=n,n=0):t=+t||0,n+Bt(Ht()*(t-n+1)) +},u.reduce=W,u.reduceRight=z,u.result=function(n,t){if(n){var r=n[t];return E(r)?n[t]():r}},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Qt(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,t,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||at).source+"|"+(e.interpolate||at).source+"|"+(e.evaluate||at).source+"|$","g"),function(t,e,u,o,i){return a+=n.slice(f,i).replace(lt,r),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+t.length,t }),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return t?l(t):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(it,d))},u.uniqueId=function(n){var t=++et+"";return n?n+t:t},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,t){return U(n,t,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,t,r){var u=0,o=n?n.length:0; -if(typeof t!="number"&&null!=t){var i=o;for(t=X(t,r,3);i--&&t(n[i],i,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:rt;return e(n,Ut(0,o-u))},u.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=N(n)),null==t||r?n?n[0+Bt(Gt()*(n.length-1-0+1))]:rt:(n=C(n),n.length=Vt(Ut(0,t),n.length),n)},u.take=V,u.head=V,nt(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Ot[n]; -u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Ht.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var t=Ot[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jt._=u, define(function(){return u})):xt&&At?Et?(At.exports=u)._=u:xt._=u:jt._=u}).call(this); \ No newline at end of file +if(typeof t!="number"&&null!=t){var i=o;for(t=X(t,r,3);i--&&t(n[i],i,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:rt;return e(n,Vt(0,o-u))},u.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=N(n)),null==t||r?n?n[0+Bt(Ht()*(n.length-1-0+1))]:rt:(n=C(n),n.length=Gt(Vt(0,t),n.length),n)},u.take=V,u.head=V,nt(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Ot[n]; +u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Jt.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var t=Ot[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jt._=u, define(function(){return u})):xt&&At?Et?(At.exports=u)._=u:xt._=u:jt._=u}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index 4d2ac0e75a..f9d7cb2a4f 100644 --- a/lodash.js +++ b/lodash.js @@ -529,16 +529,9 @@ String = context.String, TypeError = context.TypeError; - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - /** Used for native method references */ - var errorProto = Error.prototype, + var arrayRef = Array.prototype, + errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype; @@ -827,7 +820,7 @@ * @memberOf _.support * @type boolean */ - support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]); + support.spliceObjects = (splice.call(object, 0, 1), !object[0]); /** * Detect lack of support for accessing string characters by index. From 4d10584233af1e83a5aea100775c6975ec91aedd Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 30 Dec 2013 23:58:56 -0600 Subject: [PATCH 0089/1608] Beef up `_.parseInt` support and add `trim` internally. --- dist/lodash.compat.js | 65 ++++++--- dist/lodash.compat.min.js | 105 +++++++------- dist/lodash.js | 63 +++++--- dist/lodash.min.js | 102 ++++++------- dist/lodash.underscore.js | 12 +- doc/README.md | 292 +++++++++++++++++++------------------- lodash.js | 66 ++++++--- test/test.js | 66 ++++++--- 8 files changed, 448 insertions(+), 323 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 1a913ba219..401a6e154d 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -31,7 +31,7 @@ /** Used as the max size of the `arrayPool` and `objectPool` */ var maxPoolSize = 40; - /** Used to detect and test whitespace */ + /** Used to detect and test whitespace (unicode 6.3.0) */ var whitespace = ( // whitespace ' \t\x0B\f\xA0\ufeff' + @@ -40,7 +40,7 @@ '\n\r\u2028\u2029' + // unicode category "Zs" space separators - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + '\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to match empty string literals in compiled template source */ @@ -48,6 +48,15 @@ reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + /** Used to match HTML entities and HTML characters */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g; + + /** Used to match template delimiters */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + /** * Used to match ES6 template delimiters * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals @@ -60,17 +69,8 @@ /** Used to detected named functions */ var reFuncName = /^\s*function[ \n\r\t]+\w/; - /** Used to match template delimiters */ - var reEscape = /<%-([\s\S]+?)%>/g, - reEvaluate = /<%([\s\S]+?)%>/g, - reInterpolate = /<%=([\s\S]+?)%>/g; - - /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, - reUnescapedHtml = /[&<>"']/g; - - /** Used to match leading whitespace and zeros to be removed */ - var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)'); + /** Used to detect hexadecimal string values */ + var reHexPrefix = /^0[xX]/; /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; @@ -586,7 +586,8 @@ nativeMax = Math.max, nativeMin = Math.min, nativeParseInt = context.parseInt, - nativeRandom = Math.random; + nativeRandom = Math.random, + nativeTrim = isNative(nativeTrim = stringProto.trim) && nativeTrim; /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; @@ -1131,7 +1132,7 @@ function baseCreate(prototype, properties) { return isObject(prototype) ? nativeCreate(prototype) : {}; } - // fallback for browsers without `Object.create` + // fallback for environments without `Object.create` if (!nativeCreate) { baseCreate = (function() { function Object() {} @@ -1894,6 +1895,32 @@ return typeof result == 'undefined' || hasOwnProperty.call(value, result); } + /** + * Removes leading and trailing whitespace from a given string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function trim(string) { + return string == null ? '' : nativeTrim.call(string); + } + // fallback for environments without a proper `String#trim` + if (!nativeTrim || nativeTrim.call(whitespace)) { + trim = function(string) { + var start = -1, + end = string ? string.length : 0; + + if (!end || string == null) { + return ''; + } + string = String(string); + while (whitespace.indexOf(string.charAt(++start)) > -1) { } + while (whitespace.indexOf(string.charAt(--end)) > -1) { } + return string.slice(start, end + 1); + }; + } + /** * Used by `unescape` to convert HTML entities to characters. * @@ -1927,7 +1954,7 @@ return value && typeof value == 'object' && typeof value.length == 'number' && toString.call(value) == argsClass || false; } - // fallback for browsers that can't detect `arguments` objects by [[Class]] + // fallback for environments that can't detect `arguments` objects by [[Class]] if (!support.argsClass) { isArguments = function(value) { return value && typeof value == 'object' && typeof value.length == 'number' && @@ -6461,8 +6488,10 @@ * // => 8 */ var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) { - // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt` - return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0); + // Chrome fails to trim leading whitespace characters. + // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`. + value = trim(value); + return nativeParseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10)); }; /** diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 5d4cbb3e63..8e19d23319 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -6,56 +6,57 @@ ;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=w&&o===t,l=[]; -if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&g(e),l}function lt(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ot(t,r,3),typeof o=="number")for(Qr.unindexedChars&&Tt(u)&&(u=u.split(""));++e=w&&a===t,h=u||p?l():c;for(p&&(h=i(h),a=r);++oa(h,y))&&((u||p)&&h.push(y),c.push(v))}return p?(s(h.g),g(h)):u&&s(h),c}function vt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),Yr(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ot,V,br,Nr,xt,_r,rt,Jr,Q,wr,Cr) -}function dt(n){return nt[n]}function bt(){var n=(n=e.indexOf)===Ht?t:n;return n}function _t(n){return typeof n=="function"&&kr.test(Ir.call(n))}function wt(n){var t,r;return!n||Cr.call(n)!=H||(t=n.constructor,At(t)&&!(t instanceof t))||!Qr.argsClass&&xt(n)||!Qr.nodeClass&&p(n)?false:Qr.ownLast?(te(n,function(n,t,e){return r=Nr.call(e,t),false}),false!==r):(te(n,function(n,t){r=t}),typeof r=="undefined"||Nr.call(n,r))}function jt(n){return tt[n]}function xt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Cr.call(n)==W||false -}function Ct(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!Yr(n)&&Tt(n))return Fr?Fr.call(n,t,r):-1r?Mr(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Tt(n)?u:e.createCallback(t,r,3),lt(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Kt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),Yr(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),Lt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Vt(n){var t=-1,r=n?n.length:0,e=fr(typeof r=="number"?r:0);return Bt(n,function(n){var r=gt(0,++t);e[t]=e[r],e[r]=n}),e}function Ut(n,t,r){var u;if(t=e.createCallback(t,r,3),Yr(n)){r=-1;for(var o=n.length;++re?Mr(0,u+e):e||0}else if(e)return e=Qt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y;m?(u&&(u=Er(u)),c=a,o=n.apply(i,e)):u||(u=Pr(v,y))}return m&&f?f=Er(f):f||t===p||(f=Pr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function rr(n){return n}function er(n){n||(n={});var t=ne(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Nt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function ur(n,t,r){var u=true,o=t&&St(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=St(t)),false===r?u=false:Nt(r)&&"chain"in r&&(u=r.chain); -var a=n,i=At(a);Bt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Rr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Nt(o))return this;o=new a(o),o.__chain__=t}return o})})}function or(){}function ar(n){return function(t){return t[n]}}function ir(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var fr=n.Array,lr=n.Boolean,cr=n.Date,pr=n.Function,sr=n.Math,gr=n.Number,hr=n.Object,vr=n.RegExp,yr=n.String,mr=n.TypeError,dr=fr.prototype,br=n.Error.prototype,_r=hr.prototype,wr=yr.prototype,jr=(jr=n.window)&&jr.document,xr=n._,Cr=_r.toString,kr=vr("^"+yr(Cr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Or=sr.ceil,Er=n.clearTimeout,Sr=sr.floor,Ir=pr.prototype.toString,Ar=_t(Ar=hr.getPrototypeOf)&&Ar,Nr=_r.hasOwnProperty,Rr=dr.push,Tr=_r.propertyIsEnumerable,Pr=n.setTimeout,Dr=dr.splice,$r=dr.unshift,qr=function(){try{var n={},t=_t(t=hr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),Fr=_t(Fr=wr.contains)&&Fr,Br=_t(Br=hr.create)&&Br,Lr=_t(Lr=fr.isArray)&&Lr,Wr=n.isFinite,zr=n.isNaN,Kr=_t(Kr=hr.keys)&&Kr,Mr=sr.max,Vr=sr.min,Ur=n.parseInt,Gr=sr.random,Hr={};Hr[z]=fr,Hr[K]=lr,Hr[M]=cr,Hr[U]=pr,Hr[H]=hr,Hr[G]=gr,Hr[J]=vr,Hr[Q]=yr;var Jr={};Jr[z]=Jr[M]=Jr[G]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Jr[K]=Jr[Q]={constructor:true,toString:true,valueOf:true},Jr[V]=Jr[U]=Jr[J]={constructor:true,toString:true},Jr[H]={constructor:true},function(){for(var n=L.length;n--;){var t,r=L[n]; -for(t in Jr)Nr.call(Jr,t)&&!Nr.call(Jr[t],r)&&(Jr[t][r]=false)}}(),m.prototype=e.prototype;var Qr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Qr.argsClass=Cr.call(arguments)==W,Qr.argsObject=arguments.constructor==hr&&!(arguments instanceof fr),Qr.enumErrorProps=Tr.call(br,"message")||Tr.call(br,"name"),Qr.enumPrototypes=Tr.call(t,"prototype"),Qr.funcDecomp=!_t(n.WinRTError)&&q.test(v),Qr.funcNames=typeof pr.name=="string",Qr.nonEnumArgs=0!=u,Qr.nonEnumShadows=!/valueOf/.test(e),Qr.ownLast="x"!=e[0],Qr.spliceObjects=(Dr.call(r,0,1),!r[0]),Qr.unindexedChars="xx"!="x"[0]+hr("x")[0]; -try{Qr.dom=11===jr.createDocumentFragment().nodeType}catch(o){Qr.dom=false}try{Qr.nodeClass=!(Cr.call(undefined)==H&&!({toString:0}+""))}catch(a){Qr.nodeClass=true}}(1),e.templateSettings={escape:A,evaluate:N,interpolate:R,variable:"",imports:{_:e}},Br||(et=function(){function t(){}return function(r){if(Nt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var Xr=qr?function(n,t){Z.value=t,qr(n,"__bindData__",Z)}:or;Qr.argsClass||(xt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n,"callee")&&!Tr.call(n,"callee")||false -});var Yr=Lr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Cr.call(n)==z||false},Zr=mt({a:"p",b:"[]",e:"",c:"s.push(l)",f:true}),ne=Kr?function(n){return Nt(n)?Qr.enumPrototypes&&typeof n=="function"||Qr.nonEnumArgs&&n.length&&xt(n)?Zr(n):Kr(n):[]}:Zr,te=mt({a:"p,b,x",b:"p",e:"b=b&&typeof x=='undefined'?b:a(b,x,3)",c:"if(b(p[l],l,p)===false){return s}",f:false});Qr.dom||(It=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!re(n)||false}),At(/x/)&&(At=function(n){return typeof n=="function"&&Cr.call(n)==U -});var re=Ar?function(n){if(!n||Cr.call(n)!=H||!Qr.argsClass&&xt(n))return false;var t=n.valueOf,r=_t(t)&&(r=Ar(t))&&Ar(r);return r?n==r||Ar(n)==r:wt(n)}:wt,ee=vt(function(n,t,r){Nr.call(n,r)?n[r]++:n[r]=1}),ue=vt(function(n,t,r){(Nr.call(n,r)?n[r]:n[r]=[]).push(t)}),oe=vt(function(n,t,r){n[r]=t}),ae=Wt,ie=_t(ie=cr.now)&&ie||function(){return(new cr).getTime()},fe=8==Ur(x+"08")?Ur:function(n,t){return Ur(Tt(n)?n.replace(D,""):n,t||0)};return e.after=function(n,t){if(!At(t))throw new mr;return function(){return 1>--n?t.apply(this,arguments):void 0 -}},e.assign=Ct,e.at=function(n){var t=arguments,r=-1,e=ct(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=fr(t);for(Qr.unindexedChars&&Tt(n)&&(n=n.split(""));++r=w&&i(e?n[e]:c)))}var f=n[0],h=-1,v=f?f.length:0,y=[];n:for(;++h(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p)}}for(;u--;)(m=o[u])&&g(m);return s(o),s(c),y},e.invert=function(n,t){for(var r=-1,e=ne(n),u=e.length,o={};++rr?Mr(0,e+r):Vr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=ur,e.noConflict=function(){return n._=xr,this},e.noop=or,e.now=ie,e.parseInt=fe,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Gr(),Vr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):gt(n,t) -},e.reduce=Kt,e.reduceRight=Mt,e.result=function(n,t){if(n){var r=n[t];return At(r)?n[t]():r}},e.runInContext=v,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ne(n).length},e.some=Ut,e.sortedIndex=Qt,e.template=function(n,t,r){var u=e.templateSettings;n=yr(n||""),r=kt({},r,u);var o,a=kt({},r.imports,u.imports),u=ne(a),a=Pt(a),i=0,l=r.interpolate||$,c="__p+='",l=vr((r.escape||$).source+"|"+l.source+"|"+(l===R?E:$).source+"|"+(r.evaluate||$).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace(F,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t -}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(C,""):c).replace(k,"$1").replace(O,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=pr(u,"return "+c).apply(y,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=yr(n),0>n.indexOf(";")?n:n.replace(T,jt))},e.uniqueId=function(n){var t=++b; -return yr(null==n?"":n)+t},e.all=$t,e.any=Ut,e.detect=Ft,e.findWhere=Ft,e.foldl=Kt,e.foldr=Mt,e.include=Dt,e.inject=Kt,ur(function(){var n={};return Ot(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Gt,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:y;return h(n,Mr(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Pt(n):Qr.unindexedChars&&Tt(n)&&(n=n.split("")),null==t||r?n?n[gt(0,n.length-1)]:y:(n=Vt(n),n.length=Vr(Mr(0,t),n.length),n) -},e.take=Gt,e.head=Gt,Ot(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new m(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return yr(this.__wrapped__)},e.prototype.value=ir,e.prototype.valueOf=ir,lt(["join","pop","shift"],function(n){var t=dr[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new m(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=dr[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),lt(["concat","slice","splice"],function(n){var t=dr[n];e.prototype[n]=function(){return new m(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Qr.spliceObjects||lt(["pop","shift","splice"],function(n){var t=dr[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new m(u,n):u -}}),e}var y,m=[],d=[],b=0,_=+new Date+"",w=75,j=40,x=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",C=/\b__p\+='';/g,k=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,S=/\w*$/,I=/^\s*function[ \n\r\t]+\w/,A=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,R=/<%=([\s\S]+?)%>/g,T=/&(?:amp|lt|gt|quot|#39);/g,P=/[&<>"']/g,D=RegExp("^["+x+"]*0+(?=.$)"),$=/($^)/,q=/\bthis\b/,F=/['\n\r\t\u2028\u2029\\]/g,B="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),L="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),W="[object Arguments]",z="[object Array]",K="[object Boolean]",M="[object Date]",V="[object Error]",U="[object Function]",G="[object Number]",H="[object Object]",J="[object RegExp]",Q="[object String]",X={}; -X[U]=false,X[W]=X[z]=X[K]=X[M]=X[G]=X[H]=X[J]=X[Q]=true;var Y={leading:false,maxWait:0,trailing:false},Z={configurable:false,enumerable:false,value:null,writable:false},nt={"&":"&","<":"<",">":">",'"':""","'":"'"},tt={"&":"&","<":"<",">":">",""":'"',"'":"'"},rt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},et={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ut=rt[typeof window]&&window||this,ot=rt[typeof exports]&&exports&&!exports.nodeType&&exports,at=rt[typeof global]&&global; +var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e=w&&o===t,l=[]; +if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&g(e),l}function lt(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ot(t,r,3),typeof o=="number")for(Yr.unindexedChars&&Rt(u)&&(u=u.split(""));++e=w&&a===t,h=u||p?l():c;for(p&&(h=i(h),a=r);++oa(h,y))&&((u||p)&&h.push(y),c.push(v))}return p?(s(h.g),g(h)):u&&s(h),c}function vt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),ne(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ot,V,_r,Tr,Ct,wr,rt,Qr,J,jr,kr) +}function dt(n){return nt[n]}function bt(){var n=(n=e.indexOf)===Ht?t:n;return n}function _t(n){return typeof n=="function"&&Or.test(Ir.call(n))}function wt(n){var t,r;return!n||kr.call(n)!=G||(t=n.constructor,Nt(t)&&!(t instanceof t))||!Yr.argsClass&&Ct(n)||!Yr.nodeClass&&p(n)?false:Yr.ownLast?(ee(n,function(n,t,e){return r=Tr.call(e,t),false}),false!==r):(ee(n,function(n,t){r=t}),typeof r=="undefined"||Tr.call(n,r))}function jt(n){return null==n?"":Hr.call(n)}function xt(n){return tt[n]}function Ct(n){return n&&typeof n=="object"&&typeof n.length=="number"&&kr.call(n)==W||false +}function kt(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!ne(n)&&Rt(n))return Br?Br.call(n,t,r):-1r?Vr(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Rt(n)?u:e.createCallback(t,r,3),lt(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Mt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),ne(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),Wt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Ut(n){var t=-1,r=n?n.length:0,e=lr(typeof r=="number"?r:0);return Lt(n,function(n){var r=gt(0,++t);e[t]=e[r],e[r]=n}),e}function Xt(n,t,r){var u;if(t=e.createCallback(t,r,3),ne(n)){r=-1;for(var o=n.length;++re?Vr(0,u+e):e||0}else if(e)return e=Qt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y;m?(u&&(u=Sr(u)),c=a,o=n.apply(i,e)):u||(u=Dr(v,y))}return m&&f?f=Sr(f):f||t===p||(f=Dr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function er(n){return n}function ur(n){n||(n={});var t=re(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Tt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function or(n,t,r){var u=true,o=t&&At(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=At(t)),false===r?u=false:Tt(r)&&"chain"in r&&(u=r.chain); +var a=n,i=Nt(a);Lt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Pr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Tt(o))return this;o=new a(o),o.__chain__=t}return o})})}function ar(){}function ir(n){return function(t){return t[n]}}function fr(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var lr=n.Array,cr=n.Boolean,pr=n.Date,sr=n.Function,gr=n.Math,hr=n.Number,vr=n.Object,yr=n.RegExp,mr=n.String,dr=n.TypeError,br=lr.prototype,_r=n.Error.prototype,wr=vr.prototype,jr=mr.prototype,xr=(xr=n.window)&&xr.document,Cr=n._,kr=wr.toString,Or=yr("^"+mr(kr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Er=gr.ceil,Sr=n.clearTimeout,Ar=gr.floor,Ir=sr.prototype.toString,Nr=_t(Nr=vr.getPrototypeOf)&&Nr,Tr=wr.hasOwnProperty,Pr=br.push,Rr=wr.propertyIsEnumerable,Dr=n.setTimeout,qr=br.splice,Fr=br.unshift,$r=function(){try{var n={},t=_t(t=vr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Br=_t(Br=jr.contains)&&Br,Lr=_t(Lr=vr.create)&&Lr,Wr=_t(Wr=lr.isArray)&&Wr,zr=n.isFinite,Kr=n.isNaN,Mr=_t(Mr=vr.keys)&&Mr,Vr=gr.max,Ur=gr.min,Xr=n.parseInt,Gr=gr.random,Hr=_t(Hr=jr.trim)&&Hr,Jr={};Jr[z]=lr,Jr[K]=cr,Jr[M]=pr,Jr[U]=sr,Jr[G]=vr,Jr[X]=hr,Jr[H]=yr,Jr[J]=mr;var Qr={};Qr[z]=Qr[M]=Qr[X]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Qr[K]=Qr[J]={constructor:true,toString:true,valueOf:true},Qr[V]=Qr[U]=Qr[H]={constructor:true,toString:true},Qr[G]={constructor:true},function(){for(var n=L.length;n--;){var t,r=L[n]; +for(t in Qr)Tr.call(Qr,t)&&!Tr.call(Qr[t],r)&&(Qr[t][r]=false)}}(),m.prototype=e.prototype;var Yr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Yr.argsClass=kr.call(arguments)==W,Yr.argsObject=arguments.constructor==vr&&!(arguments instanceof lr),Yr.enumErrorProps=Rr.call(_r,"message")||Rr.call(_r,"name"),Yr.enumPrototypes=Rr.call(t,"prototype"),Yr.funcDecomp=!_t(n.WinRTError)&&F.test(v),Yr.funcNames=typeof sr.name=="string",Yr.nonEnumArgs=0!=u,Yr.nonEnumShadows=!/valueOf/.test(e),Yr.ownLast="x"!=e[0],Yr.spliceObjects=(qr.call(r,0,1),!r[0]),Yr.unindexedChars="xx"!="x"[0]+vr("x")[0]; +try{Yr.dom=11===xr.createDocumentFragment().nodeType}catch(o){Yr.dom=false}try{Yr.nodeClass=!(kr.call(undefined)==G&&!({toString:0}+""))}catch(a){Yr.nodeClass=true}}(1),e.templateSettings={escape:A,evaluate:I,interpolate:N,variable:"",imports:{_:e}},Lr||(et=function(){function t(){}return function(r){if(Tt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var Zr=$r?function(n,t){Z.value=t,$r(n,"__bindData__",Z)}:ar;(!Hr||Hr.call(x))&&(jt=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=mr(n);-1--n?t.apply(this,arguments):void 0}},e.assign=kt,e.at=function(n){var t=arguments,r=-1,e=ct(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=lr(t);for(Yr.unindexedChars&&Rt(n)&&(n=n.split(""));++r=w&&i(e?n[e]:c)))}var f=n[0],h=-1,v=f?f.length:0,y=[];n:for(;++h(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p) +}}for(;u--;)(m=o[u])&&g(m);return s(o),s(c),y},e.invert=function(n,t){for(var r=-1,e=re(n),u=e.length,o={};++rr?Vr(0,e+r):Ur(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=or,e.noConflict=function(){return n._=Cr,this},e.noop=ar,e.now=le,e.parseInt=ce,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Gr(),Ur(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):gt(n,t) +},e.reduce=Mt,e.reduceRight=Vt,e.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},e.runInContext=v,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:re(n).length},e.some=Xt,e.sortedIndex=Qt,e.template=function(n,t,r){var u=e.templateSettings;n=mr(n||""),r=Ot({},r,u);var o,a=Ot({},r.imports,u.imports),u=re(a),a=Dt(a),i=0,l=r.interpolate||q,c="__p+='",l=yr((r.escape||q).source+"|"+l.source+"|"+(l===N?T:q).source+"|"+(r.evaluate||q).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace($,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t +}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(C,""):c).replace(k,"$1").replace(O,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=sr(u,"return "+c).apply(y,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=mr(n),0>n.indexOf(";")?n:n.replace(E,xt))},e.uniqueId=function(n){var t=++b; +return mr(null==n?"":n)+t},e.all=Ft,e.any=Xt,e.detect=Bt,e.findWhere=Bt,e.foldl=Mt,e.foldr=Vt,e.include=qt,e.inject=Mt,or(function(){var n={};return Et(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Gt,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:y;return h(n,Vr(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Dt(n):Yr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[gt(0,n.length-1)]:y:(n=Ut(n),n.length=Ur(Vr(0,t),n.length),n) +},e.take=Gt,e.head=Gt,Et(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new m(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return mr(this.__wrapped__)},e.prototype.value=fr,e.prototype.valueOf=fr,lt(["join","pop","shift"],function(n){var t=br[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new m(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=br[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),lt(["concat","slice","splice"],function(n){var t=br[n];e.prototype[n]=function(){return new m(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Yr.spliceObjects||lt(["pop","shift","splice"],function(n){var t=br[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new m(u,n):u +}}),e}var y,m=[],d=[],b=0,_=+new Date+"",w=75,j=40,x=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",C=/\b__p\+='';/g,k=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/&(?:amp|lt|gt|quot|#39);/g,S=/[&<>"']/g,A=/<%-([\s\S]+?)%>/g,I=/<%([\s\S]+?)%>/g,N=/<%=([\s\S]+?)%>/g,T=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,q=/($^)/,F=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,B="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),L="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),W="[object Arguments]",z="[object Array]",K="[object Boolean]",M="[object Date]",V="[object Error]",U="[object Function]",X="[object Number]",G="[object Object]",H="[object RegExp]",J="[object String]",Q={}; +Q[U]=false,Q[W]=Q[z]=Q[K]=Q[M]=Q[X]=Q[G]=Q[H]=Q[J]=true;var Y={leading:false,maxWait:0,trailing:false},Z={configurable:false,enumerable:false,value:null,writable:false},nt={"&":"&","<":"<",">":">",'"':""","'":"'"},tt={"&":"&","<":"<",">":">",""":'"',"'":"'"},rt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},et={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ut=rt[typeof window]&&window||this,ot=rt[typeof exports]&&exports&&!exports.nodeType&&exports,at=rt[typeof global]&&global; !at||at.global!==at&&at.window!==at||(ut=at);var it=(at=rt[typeof module]&&module&&!module.nodeType&&module)&&at.exports===ot&&ot,ft=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ut._=ft, define(function(){return ft})):ot&&at?it?(at.exports=ft)._=ft:ot._=ft:ut._=ft}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index d4a8c879ef..3697150843 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -28,7 +28,7 @@ /** Used as the max size of the `arrayPool` and `objectPool` */ var maxPoolSize = 40; - /** Used to detect and test whitespace */ + /** Used to detect and test whitespace (unicode 6.3.0) */ var whitespace = ( // whitespace ' \t\x0B\f\xA0\ufeff' + @@ -37,7 +37,7 @@ '\n\r\u2028\u2029' + // unicode category "Zs" space separators - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + '\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to match empty string literals in compiled template source */ @@ -45,6 +45,15 @@ reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + /** Used to match HTML entities and HTML characters */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g; + + /** Used to match template delimiters */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + /** * Used to match ES6 template delimiters * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals @@ -57,17 +66,8 @@ /** Used to detected named functions */ var reFuncName = /^\s*function[ \n\r\t]+\w/; - /** Used to match template delimiters */ - var reEscape = /<%-([\s\S]+?)%>/g, - reEvaluate = /<%([\s\S]+?)%>/g, - reInterpolate = /<%=([\s\S]+?)%>/g; - - /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, - reUnescapedHtml = /[&<>"']/g; - - /** Used to match leading whitespace and zeros to be removed */ - var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)'); + /** Used to detect hexadecimal string values */ + var reHexPrefix = /^0[xX]/; /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; @@ -560,7 +560,8 @@ nativeMax = Math.max, nativeMin = Math.min, nativeParseInt = context.parseInt, - nativeRandom = Math.random; + nativeRandom = Math.random, + nativeTrim = isNative(nativeTrim = stringProto.trim) && nativeTrim; /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; @@ -904,7 +905,7 @@ function baseCreate(prototype, properties) { return isObject(prototype) ? nativeCreate(prototype) : {}; } - // fallback for browsers without `Object.create` + // fallback for environments without `Object.create` if (!nativeCreate) { baseCreate = (function() { function Object() {} @@ -1593,6 +1594,32 @@ return typeof result == 'undefined' || hasOwnProperty.call(value, result); } + /** + * Removes leading and trailing whitespace from a given string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function trim(string) { + return string == null ? '' : nativeTrim.call(string); + } + // fallback for environments without a proper `String#trim` + if (!nativeTrim || nativeTrim.call(whitespace)) { + trim = function(string) { + var start = -1, + end = string ? string.length : 0; + + if (!end || string == null) { + return ''; + } + string = String(string); + while (whitespace.indexOf(string.charAt(++start)) > -1) { } + while (whitespace.indexOf(string.charAt(--end)) > -1) { } + return string.slice(start, end + 1); + }; + } + /** * Used by `unescape` to convert HTML entities to characters. * @@ -6142,8 +6169,10 @@ * // => 8 */ var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) { - // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt` - return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0); + // Chrome fails to trim leading whitespace characters. + // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`. + value = trim(value); + return nativeParseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10)); }; /** diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 7ff353f633..d250b91e7c 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,54 +3,54 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne?0:e);++r=_&&o===t,l=[]; -if(f){var c=a(r);c?(o=e,r=c):f=false}for(;++uo(r,c)&&l.push(c);return f&&s(r),l}function ft(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r=_&&i===t,v=u||h?l():c;for(h&&(v=a(v),i=e);++oi(v,y))&&((u||h)&&v.push(y),c.push(g)) -}return h?(p(v.g),s(v)):u&&p(v),c}function ht(n){return function(t,e,r){var u={};e=m.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r=r)return false;if(typeof n=="string"||!Ge(n)&&Rt(n))return Ae?Ae.call(n,t,e):-1e?We(0,r+e):e)||0,-1o&&(o=a)}}else t=null==t&&Rt(n)?u:m.createCallback(t,e,3),Ft(n,function(n,e,u){e=t(n,e,u),e>r&&(r=e,o=n)});return o}function zt(n,t,e,r){var u=3>arguments.length;t=m.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(e=n[++o]);++oarguments.length;return t=m.createCallback(t,r,4),Bt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) -}),e}function Kt(n){var t=-1,e=n?n.length:0,r=oe(typeof e=="number"?e:0);return Ft(n,function(n){var e=pt(0,++t);r[t]=r[e],r[e]=n}),r}function Lt(n,t,e){var r;t=m.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++er?We(0,u+r):r||0}else if(r)return r=Gt(n,e),n[r]===e?r:-1;return t(n,e,r)}function Ut(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,e,3);++u>>1,e(n[r])e?0:e);++t=g;m?(i&&(i=ke(i)),s=f,a=n.apply(l,o)):i||(i=Ie(r,g))}return m&&c?c=ke(c):c||t===h||(c=Ie(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Zt(n){return n}function ne(n){n||(n={});var t=He(n),e=t[0],r=n[e]; -return 1!=t.length||r!==r||Nt(r)?function(e){for(var r=t.length,u=false;r--&&(u=lt(e[t[r]],n[t[r]],null,true)););return u}:function(n){return n=n[e],r===n&&(0!==r||1/r==1/n)}}function te(n,t,e){var r=true,u=t&&Ct(t);t&&(e||u.length)||(null==e&&(e=t),o=w,t=n,n=m,u=Ct(t)),false===e?r=false:Nt(e)&&"chain"in e&&(r=e.chain);var o=n,i=Et(o);Ft(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(Ne.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&Nt(i))return this; -i=new o(i),i.__chain__=t}return i})})}function ee(){}function re(n){return function(t){return t[n]}}function ue(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var oe=n.Array,ie=n.Boolean,ae=n.Date,fe=n.Function,le=n.Math,ce=n.Number,pe=n.Object,se=n.RegExp,he=n.String,ve=n.TypeError,ge=oe.prototype,ye=pe.prototype,me=he.prototype,be=(be=n.window)&&be.document,de=n._,_e=ye.toString,we=se("^"+he(_e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),je=le.ceil,ke=n.clearTimeout,xe=le.floor,Ce=fe.prototype.toString,Oe=mt(Oe=pe.getPrototypeOf)&&Oe,Ee=ye.hasOwnProperty,Ne=ge.push,Ie=n.setTimeout,Re=ge.splice,Se=ge.unshift,Te=function(){try{var n={},t=mt(t=pe.defineProperty)&&t,e=t(n,n,n)&&t -}catch(r){}return e}(),Ae=mt(Ae=me.contains)&&Ae,De=mt(De=pe.create)&&De,$e=mt($e=oe.isArray)&&$e,Fe=n.isFinite,Be=n.isNaN,qe=mt(qe=pe.keys)&&qe,We=le.max,ze=le.min,Pe=n.parseInt,Ke=le.random,Le={};Le[z]=oe,Le[P]=ie,Le[K]=ae,Le[L]=fe,Le[V]=pe,Le[M]=ce,Le[U]=se,Le[G]=he,w.prototype=m.prototype;var Me=m.support={};Me.funcDecomp=!mt(n.WinRTError)&&F.test(v),Me.funcNames=typeof fe.name=="string";try{Me.dom=11===be.createDocumentFragment().nodeType}catch(Ve){Me.dom=false}m.templateSettings={escape:I,evaluate:R,interpolate:S,variable:"",imports:{_:m}},De||(rt=function(){function t(){}return function(e){if(Nt(e)){t.prototype=e; -var r=new t;t.prototype=null}return r||n.Object()}}());var Ue=Te?function(n,t){Q.value=t,Te(n,"__bindData__",Q)}:ee,Ge=$e||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&_e.call(n)==z||false},He=qe?function(n){return Nt(n)?qe(n):[]}:y;Me.dom||(Ot=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!Je(n)||false});var Je=Oe?function(n){if(!n||_e.call(n)!=V)return false;var t=n.valueOf,e=mt(t)&&(e=Oe(t))&&Oe(e);return e?n==e||Oe(n)==e:bt(n)}:bt,Qe=ht(function(n,t,e){Ee.call(n,e)?n[e]++:n[e]=1 -}),Xe=ht(function(n,t,e){(Ee.call(n,e)?n[e]:n[e]=[]).push(t)}),Ye=ht(function(n,t,e){n[e]=t}),Ze=qt,nr=mt(nr=ae.now)&&nr||function(){return(new ae).getTime()},tr=8==Pe(j+"08")?Pe:function(n,t){return Pe(Rt(n)?n.replace(D,""):n,t||0)};return m.after=function(n,t){if(!Et(t))throw new ve;return function(){return 1>--n?t.apply(this,arguments):void 0}},m.assign=wt,m.at=function(n){for(var t=arguments,e=-1,r=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=oe(t);++e=_&&a(r?n[r]:c)))}var f=n[0],v=-1,g=f?f.length:0,y=[];n:for(;++v(m?e(m,h):i(c,h))){for(r=u,(m||c).push(h);--r;)if(m=o[r],0>(m?e(m,h):i(n[r],h)))continue n;y.push(h) -}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var e=-1,r=He(n),u=r.length,o={};++ee?We(0,r+e):ze(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},m.mixin=te,m.noConflict=function(){return n._=de,this},m.noop=ee,m.now=nr,m.parseInt=tr,m.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(u&&typeof n=="boolean"?(e=n,n=1):typeof t=="boolean"&&(e=t,u=true)),r&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Ke(),ze(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):pt(n,t) -},m.reduce=zt,m.reduceRight=Pt,m.result=function(n,t){if(n){var e=n[t];return Et(e)?n[t]():e}},m.runInContext=v,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:He(n).length},m.some=Lt,m.sortedIndex=Gt,m.template=function(n,t,e){var r=m.templateSettings;n=he(n||""),e=jt({},e,r);var u,o=jt({},e.imports,r.imports),r=He(o),o=St(o),i=0,a=e.interpolate||$,l="__p+='",a=se((e.escape||$).source+"|"+a.source+"|"+(a===S?O:$).source+"|"+(e.evaluate||$).source+"|$","g");n.replace(a,function(t,e,r,o,a,c){return r||(r=o),l+=n.slice(i,c).replace(B,f),e&&(l+="'+__e("+e+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t -}),l+="';",a=e=e.variable,a||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+e+"){"+(a?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=fe(r,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=he(n),0>n.indexOf(";")?n:n.replace(T,dt))},m.uniqueId=function(n){var t=++b; -return he(null==n?"":n)+t},m.all=At,m.any=Lt,m.detect=$t,m.findWhere=$t,m.foldl=zt,m.foldr=Pt,m.include=Tt,m.inject=zt,te(function(){var n={};return kt(m,function(t,e){m.prototype[e]||(n[e]=t)}),n}(),false),m.first=Mt,m.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:g;return h(n,We(0,u-r))},m.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=St(n)),null==t||e?n?n[pt(0,n.length-1)]:g:(n=Kt(n),n.length=ze(We(0,t),n.length),n) -},m.take=Mt,m.head=Mt,kt(m,function(n,t){var e="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return he(this.__wrapped__)},m.prototype.value=ue,m.prototype.valueOf=ue,Ft(["join","pop","shift"],function(n){var t=ge[n];m.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments); -return n?new w(e,n):e}}),Ft(["push","reverse","sort","unshift"],function(n){var t=ge[n];m.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Ft(["concat","slice","splice"],function(n){var t=ge[n];m.prototype[n]=function(){return new w(t.apply(this.__wrapped__,arguments),this.__chain__)}}),m}var g,y=[],m=[],b=0,d=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,O=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,E=/\w*$/,N=/^\s*function[ \n\r\t]+\w/,I=/<%-([\s\S]+?)%>/g,R=/<%([\s\S]+?)%>/g,S=/<%=([\s\S]+?)%>/g,T=/&(?:amp|lt|gt|quot|#39);/g,A=/[&<>"']/g,D=RegExp("^["+j+"]*0+(?=.$)"),$=/($^)/,F=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="[object Arguments]",z="[object Array]",P="[object Boolean]",K="[object Date]",L="[object Function]",M="[object Number]",V="[object Object]",U="[object RegExp]",G="[object String]",H={}; -H[L]=false,H[W]=H[z]=H[P]=H[K]=H[M]=H[V]=H[U]=H[G]=true;var J={leading:false,maxWait:0,trailing:false},Q={configurable:false,enumerable:false,value:null,writable:false},X={"&":"&","<":"<",">":">",'"':""","'":"'"},Y={"&":"&","<":"<",">":">",""":'"',"'":"'"},Z={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},nt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},tt=Z[typeof window]&&window||this,et=Z[typeof exports]&&exports&&!exports.nodeType&&exports,rt=Z[typeof global]&&global; -!rt||rt.global!==rt&&rt.window!==rt||(tt=rt);var ut=(rt=Z[typeof module]&&module&&!module.nodeType&&module)&&rt.exports===et&&et,ot=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):et&&rt?ut?(rt.exports=ot)._=ot:et._=ot:tt._=ot}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=_&&o===t,l=[]; +if(f){var c=a(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&s(e),l}function ft(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e=_&&i===t,v=u||h?l():c;for(h&&(v=a(v),i=r);++oi(v,y))&&((u||h)&&v.push(y),c.push(g)) +}return h?(p(v.g),s(v)):u&&p(v),c}function ht(n){return function(t,r,e){var u={};r=m.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++e=e)return false;if(typeof n=="string"||!Hr(n)&&St(n))return Dr?Dr.call(n,t,r):-1r?zr(0,e+r):r)||0,-1o&&(o=a)}}else t=null==t&&St(n)?u:m.createCallback(t,r,3),Bt(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function Pt(n,t,r,e){var u=3>arguments.length;t=m.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=m.createCallback(t,e,4),qt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) +}),r}function Lt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Bt(n,function(n){var r=pt(0,++t);e[t]=e[r],e[r]=n}),e}function Mt(n,t,r){var e;t=m.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?zr(0,u+e):e||0}else if(e)return e=Gt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=g;m?(i&&(i=xr(i)),s=f,a=n.apply(l,o)):i||(i=Ir(e,g))}return m&&c?c=xr(c):c||t===h||(c=Ir(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function nr(n){return n}function tr(n){n||(n={});var t=Jr(n),r=t[0],e=n[r]; +return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=lt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function rr(n,t,r){var e=true,u=t&&Ot(t);t&&(r||u.length)||(null==r&&(r=t),o=w,t=n,n=m,u=Ot(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain);var o=n,i=Nt(o);Bt(u,function(r){var u=n[r]=t[r];i&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,i=[r];if(Ar.apply(i,arguments),i=u.apply(n,i),e||t){if(r===i&&At(i))return this; +i=new o(i),i.__chain__=t}return i})})}function er(){}function ur(n){return function(t){return t[n]}}function or(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var ir=n.Array,ar=n.Boolean,fr=n.Date,lr=n.Function,cr=n.Math,pr=n.Number,sr=n.Object,hr=n.RegExp,vr=n.String,gr=n.TypeError,yr=ir.prototype,mr=sr.prototype,br=vr.prototype,dr=(dr=n.window)&&dr.document,_r=n._,wr=mr.toString,jr=hr("^"+vr(wr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),kr=cr.ceil,xr=n.clearTimeout,Cr=cr.floor,Or=lr.prototype.toString,Er=mt(Er=sr.getPrototypeOf)&&Er,Nr=mr.hasOwnProperty,Ar=yr.push,Ir=n.setTimeout,Sr=yr.splice,Tr=yr.unshift,Rr=function(){try{var n={},t=mt(t=sr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Dr=mt(Dr=br.contains)&&Dr,Fr=mt(Fr=sr.create)&&Fr,$r=mt($r=ir.isArray)&&$r,Br=n.isFinite,qr=n.isNaN,Wr=mt(Wr=sr.keys)&&Wr,zr=cr.max,Pr=cr.min,Kr=n.parseInt,Lr=cr.random,Mr=mt(Mr=br.trim)&&Mr,Vr={};Vr[z]=ir,Vr[P]=ar,Vr[K]=fr,Vr[L]=lr,Vr[V]=sr,Vr[M]=pr,Vr[U]=hr,Vr[X]=vr,w.prototype=m.prototype;var Ur=m.support={};Ur.funcDecomp=!mt(n.WinRTError)&&$.test(v),Ur.funcNames=typeof lr.name=="string";try{Ur.dom=11===dr.createDocumentFragment().nodeType}catch(Xr){Ur.dom=false}m.templateSettings={escape:N,evaluate:A,interpolate:I,variable:"",imports:{_:m}},Fr||(et=function(){function t(){}return function(r){if(At(r)){t.prototype=r; +var e=new t;t.prototype=null}return e||n.Object()}}());var Gr=Rr?function(n,t){J.value=t,Rr(n,"__bindData__",J)}:er;(!Mr||Mr.call(j))&&(dt=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=vr(n);-1--n?t.apply(this,arguments):void 0 +}},m.assign=jt,m.at=function(n){for(var t=arguments,r=-1,e=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ir(t);++r=_&&a(e?n[e]:c))) +}var f=n[0],v=-1,g=f?f.length:0,y=[];n:for(;++v(m?r(m,h):i(c,h))){for(e=u,(m||c).push(h);--e;)if(m=o[e],0>(m?r(m,h):i(n[e],h)))continue n;y.push(h)}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var r=-1,e=Jr(n),u=e.length,o={};++rr?zr(0,e+r):Pr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},m.mixin=rr,m.noConflict=function(){return n._=_r,this},m.noop=er,m.now=re,m.parseInt=ee,m.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Lr(),Pr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):pt(n,t) +},m.reduce=Pt,m.reduceRight=Kt,m.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},m.runInContext=v,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Jr(n).length},m.some=Mt,m.sortedIndex=Gt,m.template=function(n,t,r){var e=m.templateSettings;n=vr(n||""),r=kt({},r,e);var u,o=kt({},r.imports,e.imports),e=Jr(o),o=Tt(o),i=0,a=r.interpolate||F,l="__p+='",a=hr((r.escape||F).source+"|"+a.source+"|"+(a===I?S:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(B,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t +}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=lr(e,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=vr(n),0>n.indexOf(";")?n:n.replace(O,_t))},m.uniqueId=function(n){var t=++b; +return vr(null==n?"":n)+t},m.all=Dt,m.any=Mt,m.detect=$t,m.findWhere=$t,m.foldl=Pt,m.foldr=Kt,m.include=Rt,m.inject=Pt,rr(function(){var n={};return xt(m,function(t,r){m.prototype[r]||(n[r]=t)}),n}(),false),m.first=Vt,m.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:g;return h(n,zr(0,u-e))},m.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Tt(n)),null==t||r?n?n[pt(0,n.length-1)]:g:(n=Lt(n),n.length=Pr(zr(0,t),n.length),n) +},m.take=Vt,m.head=Vt,xt(m,function(n,t){var r="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return vr(this.__wrapped__)},m.prototype.value=or,m.prototype.valueOf=or,Bt(["join","pop","shift"],function(n){var t=yr[n];m.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new w(r,n):r}}),Bt(["push","reverse","sort","unshift"],function(n){var t=yr[n];m.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Bt(["concat","slice","splice"],function(n){var t=yr[n];m.prototype[n]=function(){return new w(t.apply(this.__wrapped__,arguments),this.__chain__)}}),m}var g,y=[],m=[],b=0,d=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,O=/&(?:amp|lt|gt|quot|#39);/g,E=/[&<>"']/g,N=/<%-([\s\S]+?)%>/g,A=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,S=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,T=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,F=/($^)/,$=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="[object Arguments]",z="[object Array]",P="[object Boolean]",K="[object Date]",L="[object Function]",M="[object Number]",V="[object Object]",U="[object RegExp]",X="[object String]",G={}; +G[L]=false,G[W]=G[z]=G[P]=G[K]=G[M]=G[V]=G[U]=G[X]=true;var H={leading:false,maxWait:0,trailing:false},J={configurable:false,enumerable:false,value:null,writable:false},Q={"&":"&","<":"<",">":">",'"':""","'":"'"},Y={"&":"&","<":"<",">":">",""":'"',"'":"'"},Z={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},nt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},tt=Z[typeof window]&&window||this,rt=Z[typeof exports]&&exports&&!exports.nodeType&&exports,et=Z[typeof global]&&global; +!et||et.global!==et&&et.window!==et||(tt=et);var ut=(et=Z[typeof module]&&module&&!module.nodeType&&module)&&et.exports===rt&&rt,ot=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):rt&&et?ut?(et.exports=ot)._=ot:rt._=ot:tt._=ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index cdf5294b68..54b07b7f4a 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -21,15 +21,15 @@ /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */ var keyPrefix = +new Date + ''; + /** Used to match HTML entities and HTML characters */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g, + reUnescapedHtml = /[&<>"']/g; + /** Used to match template delimiters */ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; - /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g, - reUnescapedHtml = /[&<>"']/g; - /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; @@ -456,7 +456,7 @@ function baseCreate(prototype, properties) { return isObject(prototype) ? nativeCreate(prototype) : {}; } - // fallback for browsers without `Object.create` + // fallback for environments without `Object.create` if (!nativeCreate) { baseCreate = (function() { function Object() {} @@ -932,7 +932,7 @@ return value && typeof value == 'object' && typeof value.length == 'number' && toString.call(value) == argsClass || false; } - // fallback for browsers that can't detect `arguments` objects by [[Class]] + // fallback for environments that can't detect `arguments` objects by [[Class]] if (!isArguments(arguments)) { isArguments = function(value) { return value && typeof value == 'object' && typeof value.length == 'number' && diff --git a/doc/README.md b/doc/README.md index 3e3ac8e5a9..7480453703 100644 --- a/doc/README.md +++ b/doc/README.md @@ -240,7 +240,7 @@ ### `_.compact(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4515 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4561 "View in source") [Ⓣ][1] Creates an array with all falsey values removed. The values `false`, `null`, `0`, `""`, `undefined`, and `NaN` are all falsey. @@ -264,7 +264,7 @@ _.compact([0, 1, false, 2, '', 3]); ### `_.difference(array, [values])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4545 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4591 "View in source") [Ⓣ][1] Creates an array excluding all values of the provided arrays using strict equality for comparisons, i.e. `===`. @@ -289,7 +289,7 @@ _.difference([1, 2, 3, 4, 5], [5, 2, 10]); ### `_.findIndex(array, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4590 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4636 "View in source") [Ⓣ][1] This method is like `_.find` except that it returns the index of the first element that passes the callback check, instead of the element itself. @@ -335,7 +335,7 @@ _.findIndex(characters, 'blocked'); ### `_.findLastIndex(array, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4644 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4690 "View in source") [Ⓣ][1] This method is like `_.findIndex` except that it iterates over elements of a `collection` from right to left. @@ -381,7 +381,7 @@ _.findLastIndex(characters, 'blocked'); ### `_.first(array, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4708 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4754 "View in source") [Ⓣ][1] Gets the first element or first `n` elements of an array. If a callback is provided elements at the beginning of the array are returned as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -438,7 +438,7 @@ _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); ### `_.flatten(array, [isShallow=false], [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4769 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4815 "View in source") [Ⓣ][1] Flattens a nested array *(the nesting can be to any depth)*. If `isShallow` is truey, the array will only be flattened a single level. If a callback is provided each element of the array is passed through the callback before flattening. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -482,7 +482,7 @@ _.flatten(characters, 'pets'); ### `_.indexOf(array, value, [fromIndex=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4808 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4854 "View in source") [Ⓣ][1] Gets the index at which the first occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If the array is already sorted providing `true` for `fromIndex` will run a faster binary search. @@ -516,7 +516,7 @@ _.indexOf([1, 1, 2, 2, 3, 3], 2, true); ### `_.initial(array, [callback=1], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4871 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4917 "View in source") [Ⓣ][1] Gets all but the last element or last `n` elements of an array. If a callback is provided elements at the end of the array are excluded from the result as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -570,7 +570,7 @@ _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); ### `_.intersection([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4901 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4947 "View in source") [Ⓣ][1] Creates an array of unique values present in all provided arrays using strict equality for comparisons, i.e. `===`. @@ -594,7 +594,7 @@ _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); ### `_.last(array, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5003 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5049 "View in source") [Ⓣ][1] Gets the last element or last `n` elements of an array. If a callback is provided elements at the end of the array are returned as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -648,7 +648,7 @@ _.last(characters, { 'employer': 'na' }); ### `_.lastIndexOf(array, value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5050 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5096 "View in source") [Ⓣ][1] Gets the index at which the last occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the offset from the end of the collection. @@ -682,7 +682,7 @@ _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); ### `_.pull(array, [value])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5080 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5126 "View in source") [Ⓣ][1] Removes all provided values from the given array using strict equality for comparisons, i.e. `===`. @@ -709,7 +709,7 @@ console.log(array); ### `_.range([start=0], end, [step=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5131 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5177 "View in source") [Ⓣ][1] Creates an array of numbers *(positive and/or negative)* progressing from `start` up to but not including `end`. If `start` is less than `stop` a zero-length range is created unless a negative `step` is specified. @@ -750,7 +750,7 @@ _.range(0); ### `_.remove(array, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5184 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5230 "View in source") [Ⓣ][1] Removes all elements from an array that the callback returns truey for and returns an array of removed elements. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -786,7 +786,7 @@ console.log(evens); ### `_.rest(array, [callback=1], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5255 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5301 "View in source") [Ⓣ][1] The opposite of `_.initial`; this method gets all but the first element or first `n` elements of an array. If a callback function is provided elements at the beginning of the array are excluded from the result as long as the callback returns truey. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -843,7 +843,7 @@ _.rest(characters, { 'employer': 'slate' }); ### `_.sortedIndex(array, value, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5321 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5367 "View in source") [Ⓣ][1] Uses a binary search to determine the smallest index at which a value should be inserted into a given sorted array in order to maintain the sort order of the array. If a callback is provided it will be executed for `value` and each element of `array` to compute their sort ranking. The callback is bound to `thisArg` and invoked with one argument; *(value)*. @@ -894,7 +894,7 @@ _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); ### `_.union([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5352 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5398 "View in source") [Ⓣ][1] Creates an array of unique values, in order, of the provided arrays using strict equality for comparisons, i.e. `===`. @@ -918,7 +918,7 @@ _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); ### `_.uniq(array, [isSorted=false], [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5403 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5449 "View in source") [Ⓣ][1] Creates a duplicate-value-free version of an array using strict equality for comparisons, i.e. `===`. If the array is sorted, providing `true` for `isSorted` will use a faster algorithm. If a callback is provided each element of `array` is passed through the callback before uniqueness is computed. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, array)*. @@ -968,7 +968,7 @@ _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); ### `_.without(array, [value])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5431 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5477 "View in source") [Ⓣ][1] Creates an array excluding all provided values using strict equality for comparisons, i.e. `===`. @@ -993,7 +993,7 @@ _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); ### `_.xor([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5452 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5498 "View in source") [Ⓣ][1] Creates an array that is the symmetric difference of the provided arrays. See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. @@ -1020,7 +1020,7 @@ _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); ### `_.zip([array])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5487 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5533 "View in source") [Ⓣ][1] Creates an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on. If a zipped value is provided its corresponding unzipped value will be returned. @@ -1050,7 +1050,7 @@ _.unzip([['fred', 30, true], ['barney', 40, false]]); ### `_.zipObject(keys, [values=[]])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5517 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5563 "View in source") [Ⓣ][1] Creates an object composed from arrays of `keys` and `values`. Provide either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` or two arrays, one of `keys` and one of corresponding `values`. @@ -1085,7 +1085,7 @@ _.zipObject(['fred', 'barney'], [30, 40]); ### `_(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L668 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L692 "View in source") [Ⓣ][1] Creates a `lodash` object which wraps the given value to enable intuitive method chaining. @@ -1140,7 +1140,7 @@ _.isArray(squares.value()); ### `_.chain(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6885 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6934 "View in source") [Ⓣ][1] Creates a `lodash` object that wraps the given value with explicit method chaining enabled. @@ -1174,7 +1174,7 @@ var youngest = _.chain(characters) ### `_.tap(value, interceptor, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6912 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6961 "View in source") [Ⓣ][1] This method invokes `interceptor` and returns `value`. The interceptor is bound to `thisArg` and invoked with one argument; *(value)*. The purpose of this method is to "tap into" a method chain in order to perform operations on intermediate results within the chain. @@ -1203,7 +1203,7 @@ _([1, 2, 3, 4]) ### `_.prototype.chain()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6942 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6991 "View in source") [Ⓣ][1] Enables explicit method chaining on the wrapper object. @@ -1237,7 +1237,7 @@ _(characters).chain() ### `_.prototype.toString()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6959 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7008 "View in source") [Ⓣ][1] Produces the `toString` result of the wrapped value. @@ -1258,7 +1258,7 @@ _([1, 2, 3]).toString(); ### `_.prototype.valueOf()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6976 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7025 "View in source") [Ⓣ][1] Extracts the wrapped value. @@ -1289,7 +1289,7 @@ _([1, 2, 3]).valueOf(); ### `_.at(collection, [index])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3324 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3374 "View in source") [Ⓣ][1] Creates an array of elements from the specified indexes, or keys, of the `collection`. Indexes may be specified as individual arguments or as arrays of indexes. @@ -1317,7 +1317,7 @@ _.at(['fred', 'barney', 'pebbles'], 0, 2); ### `_.contains(collection, target, [fromIndex=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3367 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3417 "View in source") [Ⓣ][1] Checks if a given value is present in a collection using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the offset from the end of the collection. @@ -1355,7 +1355,7 @@ _.contains('pebbles', 'eb'); ### `_.countBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3430 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3480 "View in source") [Ⓣ][1] Creates an object composed of keys generated from the results of running each element of `collection` through the callback. The corresponding value of each key is the number of times the key was returned by the callback. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1391,7 +1391,7 @@ _.countBy(['one', 'two', 'three'], 'length'); ### `_.every(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3475 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3525 "View in source") [Ⓣ][1] Checks if the given callback returns truey value for **all** elements of a collection. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1437,7 +1437,7 @@ _.every(characters, { 'age': 36 }); ### `_.filter(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3536 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3586 "View in source") [Ⓣ][1] Iterates over elements of a collection, returning an array of all elements the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1483,7 +1483,7 @@ _.filter(characters, { 'age': 36 }); ### `_.find(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3603 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3653 "View in source") [Ⓣ][1] Iterates over elements of a collection, returning the first element that the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1532,7 +1532,7 @@ _.find(characters, 'blocked'); ### `_.findLast(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3648 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3698 "View in source") [Ⓣ][1] This method is like `_.find` except that it iterates over elements of a `collection` from right to left. @@ -1560,7 +1560,7 @@ _.findLast([1, 2, 3, 4], function(num) { ### `_.forEach(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3686 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3736 "View in source") [Ⓣ][1] Iterates over elements of a collection, executing the callback for each element. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -1594,7 +1594,7 @@ _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); ### `_.forEachRight(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3719 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3769 "View in source") [Ⓣ][1] This method is like `_.forEach` except that it iterates over elements of a `collection` from right to left. @@ -1623,7 +1623,7 @@ _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); ### `_.groupBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3780 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3830 "View in source") [Ⓣ][1] Creates an object composed of keys generated from the results of running each element of a collection through the callback. The corresponding value of each key is an array of the elements responsible for generating the key. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1660,7 +1660,7 @@ _.groupBy(['one', 'two', 'three'], 'length'); ### `_.indexBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3823 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3873 "View in source") [Ⓣ][1] Creates an object composed of keys generated from the results of running each element of the collection through the given callback. The corresponding value of each key is the last element responsible for generating the key. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1701,7 +1701,7 @@ _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String); ### `_.invoke(collection, methodName, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3849 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3899 "View in source") [Ⓣ][1] Invokes the method named by `methodName` on each element in the `collection` returning an array of the results of each invoked method. Additional arguments will be provided to each invoked method. If `methodName` is a function it will be invoked for, and `this` bound to, each element in the `collection`. @@ -1730,7 +1730,7 @@ _.invoke([123, 456], String.prototype.split, ''); ### `_.map(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3901 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3951 "View in source") [Ⓣ][1] Creates an array of values by running each element in the collection through the callback. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -1775,7 +1775,7 @@ _.map(characters, 'name'); ### `_.max(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3959 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4009 "View in source") [Ⓣ][1] Retrieves the maximum value of a collection. If the collection is empty or falsey `-Infinity` is returned. If a callback is provided it will be executed for each value in the collection to generate the criterion by which the value is ranked. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, collection)*. @@ -1817,7 +1817,7 @@ _.max(characters, 'age'); ### `_.min(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4034 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4084 "View in source") [Ⓣ][1] Retrieves the minimum value of a collection. If the collection is empty or falsey `Infinity` is returned. If a callback is provided it will be executed for each value in the collection to generate the criterion by which the value is ranked. The callback is bound to `thisArg` and invoked with three arguments; *(value, index, collection)*. @@ -1859,7 +1859,7 @@ _.min(characters, 'age'); ### `_.pluck(collection, prop)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4089 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4139 "View in source") [Ⓣ][1] Retrieves the value of a specified property from all elements in the collection. @@ -1889,7 +1889,7 @@ _.pluck(characters, 'name'); ### `_.reduce(collection, [callback=identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4121 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4171 "View in source") [Ⓣ][1] Reduces a collection to a value which is the accumulated result of running each element in the collection through the callback, where each successive callback execution consumes the return value of the previous execution. If `accumulator` is not provided the first element of the collection will be used as the initial `accumulator` value. The callback is bound to `thisArg` and invoked with four arguments; *(accumulator, value, index|key, collection)*. @@ -1927,7 +1927,7 @@ var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { ### `_.reduceRight(collection, [callback=identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4164 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4214 "View in source") [Ⓣ][1] This method is like `_.reduce` except that it iterates over elements of a `collection` from right to left. @@ -1958,7 +1958,7 @@ var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); ### `_.reject(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4213 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4263 "View in source") [Ⓣ][1] The opposite of `_.filter`; this method returns the elements of a collection that the callback does **not** return truey for. @@ -2001,7 +2001,7 @@ _.reject(characters, { 'age': 36 }); ### `_.sample(collection, [n])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4239 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4289 "View in source") [Ⓣ][1] Retrieves a random element or `n` random elements from a collection. @@ -2029,7 +2029,7 @@ _.sample([1, 2, 3, 4], 2); ### `_.shuffle(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4267 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4317 "View in source") [Ⓣ][1] Creates an array of shuffled values, using a version of the Fisher-Yates shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) for more details. @@ -2053,7 +2053,7 @@ _.shuffle([1, 2, 3, 4, 5, 6]); ### `_.size(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4300 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4351 "View in source") [Ⓣ][1] Gets the size of the `collection` by returning `collection.length` for arrays and array-like objects or the number of own enumerable properties for objects. @@ -2083,7 +2083,7 @@ _.size('pebbles'); ### `_.some(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4347 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4398 "View in source") [Ⓣ][1] Checks if the callback returns a truey value for **any** element of a collection. The function returns as soon as it finds a passing value and does not iterate over the entire collection. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -2129,7 +2129,7 @@ _.some(characters, { 'age': 1 }); ### `_.sortBy(collection, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4417 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4468 "View in source") [Ⓣ][1] Creates an array of elements, sorted in ascending order by the results of running each element in a collection through the callback. This method performs a stable sort, that is, it will preserve the original sort order of equal elements. The callback is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. @@ -2179,7 +2179,7 @@ _.map(_.sortBy(characters, ['name', 'age']), _.values); ### `_.toArray(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4463 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4509 "View in source") [Ⓣ][1] Converts the `collection` to an array. @@ -2203,7 +2203,7 @@ Converts the `collection` to an array. ### `_.where(collection, props)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4497 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L4543 "View in source") [Ⓣ][1] Performs a deep comparison between each element in `collection` and the `props` object, returning an array of all elements that have equivalent property values. @@ -2243,7 +2243,7 @@ _.where(characters, { 'pets': ['dino'] }); ### `_.after(n, func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5562 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5608 "View in source") [Ⓣ][1] Creates a function that executes `func`, with the `this` binding and arguments of the created function, only after being called `n` times. @@ -2276,7 +2276,7 @@ _.forEach(saves, function(type) { ### `_.bind(func, [thisArg], [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5595 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5641 "View in source") [Ⓣ][1] Creates a function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends any additional `bind` arguments to those provided to the bound function. @@ -2307,7 +2307,7 @@ func(); ### `_.bindAll(object, [methodName])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5625 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5671 "View in source") [Ⓣ][1] Binds methods of an object to the object itself, overwriting the existing method. Method names may be specified as individual arguments or as arrays of method names. If no method names are provided all the function properties of `object` will be bound. @@ -2338,7 +2338,7 @@ jQuery('#docs').on('click', view.onClick); ### `_.bindKey(object, key, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5672 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5718 "View in source") [Ⓣ][1] Creates a function that, when called, invokes the method at `object[key]` and prepends any additional `bindKey` arguments to those provided to the bound function. This method differs from `_.bind` by allowing bound functions to reference methods that will be redefined or don't yet exist. See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) for more details. @@ -2379,7 +2379,7 @@ func(); ### `_.compose([func])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5708 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5754 "View in source") [Ⓣ][1] Creates a function that is the composition of the provided functions, where each function consumes the return value of the function that follows. For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. Each function is executed with the `this` binding of the composed function. @@ -2417,7 +2417,7 @@ welcome('pebbles'); ### `_.curry(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5756 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5802 "View in source") [Ⓣ][1] Creates a function which accepts one or more arguments of `func` that when invoked either executes `func` returning its result, if all `func` arguments have been provided, or returns a function that accepts one or more of the remaining `func` arguments, and so on. The arity of `func` can be specified if `func.length` is not sufficient. @@ -2452,7 +2452,7 @@ curried(1, 2, 3); ### `_.debounce(func, wait, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5800 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5846 "View in source") [Ⓣ][1] Creates a function that will delay the execution of `func` until after `wait` milliseconds have elapsed since the last time it was invoked. 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 will return the result of the last `func` call. @@ -2496,7 +2496,7 @@ source.addEventListener('message', _.debounce(batchLog, 250, { ### `_.defer(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5916 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5962 "View in source") [Ⓣ][1] Defers executing the `func` function until the current call stack has cleared. Additional arguments will be provided to `func` when it is invoked. @@ -2521,7 +2521,7 @@ _.defer(function(text) { console.log(text); }, 'deferred'); ### `_.delay(func, wait, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5940 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5986 "View in source") [Ⓣ][1] Executes the `func` function after `wait` milliseconds. Additional arguments will be provided to `func` when it is invoked. @@ -2547,7 +2547,7 @@ _.delay(function(text) { console.log(text); }, 1000, 'later'); ### `_.memoize(func, [resolver])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L5985 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6031 "View in source") [Ⓣ][1] Creates a function that memoizes the result of `func`. If `resolver` is provided it will be used to determine the cache key for storing the result based on the arguments provided to the memoized function. By default, the first argument provided to the memoized function is used as the cache key. The `func` is executed with the `this` binding of the memoized function. The result cache is exposed as the `cache` property on the memoized function. @@ -2590,7 +2590,7 @@ get('pebbles'); ### `_.once(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6018 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6064 "View in source") [Ⓣ][1] Creates a function that is restricted to execute `func` once. Repeat calls to the function will return the value of the first call. The `func` is executed with the `this` binding of the created function. @@ -2616,7 +2616,7 @@ initialize(); ### `_.partial(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6056 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6102 "View in source") [Ⓣ][1] Creates a function that, when called, invokes `func` with any additional `partial` arguments prepended to those provided to the new function. This method is similar to `_.bind` except it does **not** alter the `this` binding. @@ -2643,7 +2643,7 @@ hi('fred'); ### `_.partialRight(func, [arg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6087 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6133 "View in source") [Ⓣ][1] This method is like `_.partial` except that `partial` arguments are appended to those provided to the new function. @@ -2680,7 +2680,7 @@ options.imports ### `_.throttle(func, wait, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6122 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6168 "View in source") [Ⓣ][1] Creates a function that, when executed, will only call the `func` function at most once per every `wait` milliseconds. 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 will return the result of the last `func` call. @@ -2716,7 +2716,7 @@ jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { ### `_.wrap(value, wrapper)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6163 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6209 "View in source") [Ⓣ][1] Creates a function that provides `value` to the wrapper function as its first argument. Additional arguments provided to the function are appended to those provided to the wrapper function. The wrapper is executed with the `this` binding of the created function. @@ -2752,7 +2752,7 @@ p('Fred, Wilma, & Pebbles'); ### `_.assign(object, [source], [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2029 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2079 "View in source") [Ⓣ][1] Assigns own enumerable properties of source object(s) to the destination object. Subsequent sources will overwrite property assignments of previous sources. If a callback is provided it will be executed to produce the assigned values. The callback is bound to `thisArg` and invoked with two arguments; *(objectValue, sourceValue)*. @@ -2790,7 +2790,7 @@ defaults(object, { 'name': 'fred', 'employer': 'slate' }); ### `_.clone(value, [isDeep=false], [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2095 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2145 "View in source") [Ⓣ][1] Creates a clone of `value`. If `isDeep` is `true` nested objects will also be cloned, otherwise they will be assigned by reference. If a callback is provided it will be executed to produce the cloned values. If the callback returns `undefined` cloning will be handled by the method instead. The callback is bound to `thisArg` and invoked with one argument; *(value)*. @@ -2837,7 +2837,7 @@ clone.childNodes.length; ### `_.cloneDeep(value, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2148 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2198 "View in source") [Ⓣ][1] Creates a deep clone of `value`. If a callback is provided it will be executed to produce the cloned values. If the callback returns `undefined` cloning will be handled by the method instead. The callback is bound to `thisArg` and invoked with one argument; *(value)*. @@ -2883,7 +2883,7 @@ clone.node == view.node; ### `_.create(prototype, [properties])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2183 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2233 "View in source") [Ⓣ][1] Creates an object that inherits from the given `prototype` object. If a `properties` object is provided its own enumerable properties are assigned to the created object. @@ -2923,7 +2923,7 @@ circle instanceof Shape; ### `_.defaults(object, [source])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2207 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2257 "View in source") [Ⓣ][1] Assigns own enumerable properties of source object(s) to the destination object for all destination properties that resolve to `undefined`. Once a property is set, additional defaults of the same property will be ignored. @@ -2949,7 +2949,7 @@ _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); ### `_.findKey(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2271 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2321 "View in source") [Ⓣ][1] This method is like `_.findIndex` except that it returns the key of the first element that passes the callback check, instead of the element itself. @@ -2995,7 +2995,7 @@ _.findKey(characters, 'blocked'); ### `_.findLastKey(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2324 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2374 "View in source") [Ⓣ][1] This method is like `_.findKey` except that it iterates over elements of a `collection` in the opposite order. @@ -3041,7 +3041,7 @@ _.findLastKey(characters, 'blocked'); ### `_.forIn(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2367 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2417 "View in source") [Ⓣ][1] Iterates over own and inherited enumerable properties of an object, executing the callback for each property. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -3079,7 +3079,7 @@ _.forIn(new Shape, function(value, key) { ### `_.forInRight(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2403 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2453 "View in source") [Ⓣ][1] This method is like `_.forIn` except that it iterates over elements of a `collection` in the opposite order. @@ -3117,7 +3117,7 @@ _.forInRight(new Shape, function(value, key) { ### `_.forOwn(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2440 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2490 "View in source") [Ⓣ][1] Iterates over own enumerable properties of an object, executing the callback for each property. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -3145,7 +3145,7 @@ _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { ### `_.forOwnRight(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2473 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2523 "View in source") [Ⓣ][1] This method is like `_.forOwn` except that it iterates over elements of a `collection` in the opposite order. @@ -3173,7 +3173,7 @@ _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { ### `_.functions(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2502 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2552 "View in source") [Ⓣ][1] Creates a sorted array of property names of all enumerable properties, own and inherited, of `object` that have function values. @@ -3200,7 +3200,7 @@ _.functions(_); ### `_.has(object, key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2527 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2577 "View in source") [Ⓣ][1] Checks if the specified property name exists as a direct property of `object`, instead of an inherited property. @@ -3225,7 +3225,7 @@ _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); ### `_.invert(object, [multiValue=false])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2556 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2606 "View in source") [Ⓣ][1] Creates an object composed of the inverted keys and values of the given object. If the given object contains duplicate values, subsequent values will overwrite property assignments of previous values unless `multiValue` is `true`. @@ -3258,7 +3258,7 @@ _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); ### `_.isArguments(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1923 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1973 "View in source") [Ⓣ][1] Checks if `value` is an `arguments` object. @@ -3285,7 +3285,7 @@ _.isArguments([1, 2, 3]); ### `_.isArray(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1952 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2002 "View in source") [Ⓣ][1] Checks if `value` is an array. @@ -3312,7 +3312,7 @@ _.isArray([1, 2, 3]); ### `_.isBoolean(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2592 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2642 "View in source") [Ⓣ][1] Checks if `value` is a boolean value. @@ -3336,7 +3336,7 @@ _.isBoolean(null); ### `_.isDate(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2610 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2660 "View in source") [Ⓣ][1] Checks if `value` is a date. @@ -3360,7 +3360,7 @@ _.isDate(new Date); ### `_.isElement(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2627 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2677 "View in source") [Ⓣ][1] Checks if `value` is a DOM element. @@ -3384,7 +3384,7 @@ _.isElement(document.body); ### `_.isEmpty(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2660 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2710 "View in source") [Ⓣ][1] Checks if `value` is empty. Arrays, strings, or `arguments` objects with a length of `0` and objects with no own enumerable properties are considered "empty". @@ -3414,7 +3414,7 @@ _.isEmpty(''); ### `_.isEqual(a, b, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2717 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2767 "View in source") [Ⓣ][1] Performs a deep comparison between two values to determine if they are equivalent to each other. If a callback is provided it will be executed to compare values. If the callback returns `undefined` comparisons will be handled by the method instead. The callback is bound to `thisArg` and invoked with two arguments; *(a, b)*. @@ -3459,7 +3459,7 @@ _.isEqual(words, otherWords, function(a, b) { ### `_.isFinite(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2750 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2800 "View in source") [Ⓣ][1] Checks if `value` is, or can be coerced to, a finite number. @@ -3497,7 +3497,7 @@ _.isFinite(Infinity); ### `_.isFunction(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2767 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2817 "View in source") [Ⓣ][1] Checks if `value` is a function. @@ -3521,7 +3521,7 @@ _.isFunction(_); ### `_.isNaN(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2831 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2881 "View in source") [Ⓣ][1] Checks if `value` is `NaN`. @@ -3556,7 +3556,7 @@ _.isNaN(undefined); ### `_.isNull(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2853 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2903 "View in source") [Ⓣ][1] Checks if `value` is `null`. @@ -3583,7 +3583,7 @@ _.isNull(undefined); ### `_.isNumber(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2873 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2923 "View in source") [Ⓣ][1] Checks if `value` is a number. @@ -3609,7 +3609,7 @@ _.isNumber(8.4 * 5); ### `_.isObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2797 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2847 "View in source") [Ⓣ][1] Checks if `value` is the language type of Object. *(e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)* @@ -3639,7 +3639,7 @@ _.isObject(1); ### `_.isPlainObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2902 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2952 "View in source") [Ⓣ][1] Checks if `value` is an object created by the `Object` constructor. @@ -3674,7 +3674,7 @@ _.isPlainObject({ 'x': 0, 'y': 0 }); ### `_.isRegExp(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2927 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2977 "View in source") [Ⓣ][1] Checks if `value` is a regular expression. @@ -3698,7 +3698,7 @@ _.isRegExp(/fred/); ### `_.isString(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2944 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2994 "View in source") [Ⓣ][1] Checks if `value` is a string. @@ -3722,7 +3722,7 @@ _.isString('fred'); ### `_.isUndefined(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2962 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3012 "View in source") [Ⓣ][1] Checks if `value` is `undefined`. @@ -3746,7 +3746,7 @@ _.isUndefined(void 0); ### `_.keys(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L1987 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L2037 "View in source") [Ⓣ][1] Creates an array composed of the own enumerable property names of an object. @@ -3770,7 +3770,7 @@ _.keys({ 'one': 1, 'two': 2, 'three': 3 }); ### `_.mapValues(object, [callback=identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3002 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3052 "View in source") [Ⓣ][1] Creates an object with the same keys as `object` and values generated by running each own enumerable property of `object` through the callback. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. @@ -3809,7 +3809,7 @@ _.mapValues(characters, 'age'); ### `_.merge(object, [source], [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3063 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3113 "View in source") [Ⓣ][1] Recursively merges own enumerable properties of the source object(s), that don't resolve to `undefined` into the destination object. Subsequent sources will overwrite property assignments of previous sources. If a callback is provided it will be executed to produce the merged values of the destination and source properties. If the callback returns `undefined` merging will be handled by the method instead. The callback is bound to `thisArg` and invoked with two arguments; *(objectValue, sourceValue)*. @@ -3865,7 +3865,7 @@ _.merge(food, otherFood, function(a, b) { ### `_.omit(object, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3119 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3169 "View in source") [Ⓣ][1] Creates a shallow clone of `object` excluding the specified properties. Property names may be specified as individual arguments or as arrays of property names. If a callback is provided it will be executed for each property of `object` omitting the properties the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. @@ -3896,7 +3896,7 @@ _.omit({ 'name': 'fred', 'age': 40 }, function(value) { ### `_.pairs(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3160 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3210 "View in source") [Ⓣ][1] Creates a two dimensional array of an object's key-value pairs, i.e. `[[key1, value1], [key2, value2]]`. @@ -3920,7 +3920,7 @@ _.pairs({ 'barney': 36, 'fred': 40 }); ### `_.pick(object, [callback], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3200 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3250 "View in source") [Ⓣ][1] Creates a shallow clone of `object` composed of the specified properties. Property names may be specified as individual arguments or as arrays of property names. If a callback is provided it will be executed for each property of `object` picking the properties the callback returns truey for. The callback is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. @@ -3951,7 +3951,7 @@ _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { ### `_.transform(object, [callback=identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3255 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3305 "View in source") [Ⓣ][1] An alternative to `_.reduce` this method transforms `object` to a new `accumulator` object which is the result of running each of its own enumerable properties through a callback, with each callback execution potentially mutating the `accumulator` object. The callback is bound to `thisArg` and invoked with four arguments; *(accumulator, value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`. @@ -3988,7 +3988,7 @@ var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) ### `_.values(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3289 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L3339 "View in source") [Ⓣ][1] Creates an array composed of the own enumerable property values of `object`. @@ -4019,7 +4019,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 }); ### `_.now` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6440 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6486 "View in source") [Ⓣ][1] *(unknown)*: Gets the number of milliseconds that have elapsed since the Unix epoch *(1 January `1970 00`:00:00 UTC)*. @@ -4038,7 +4038,7 @@ _.defer(function() { console.log(_.now() - stamp); }); ### `_.constant(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6184 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6230 "View in source") [Ⓣ][1] Creates a function that returns `value`. @@ -4064,7 +4064,7 @@ getter() === object; ### `_.createCallback([func=identity], [thisArg], [argCount])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6221 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6267 "View in source") [Ⓣ][1] Produces a callback bound to an optional `thisArg`. If `func` is a property name the created callback will return the property value for a given element. If `func` is an object the created callback will return `true` for elements that contain the equivalent object properties, otherwise it will return `false`. @@ -4103,7 +4103,7 @@ _.filter(characters, 'age__gt38'); ### `_.escape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6247 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6293 "View in source") [Ⓣ][1] Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding HTML entities. @@ -4129,7 +4129,7 @@ _.escape('Fred, Wilma, & Pebbles'); ### `_.identity(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6265 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6311 "View in source") [Ⓣ][1] This method returns the first argument provided to it. @@ -4154,7 +4154,7 @@ _.identity(object) === object; ### `_.match(props)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6294 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6340 "View in source") [Ⓣ][1] Creates a "_.where" style function, which performs a deep comparison between a given object and the `props` object, returning `true` if the given object has equivalent property values, else `false`. @@ -4188,7 +4188,7 @@ _.find(characters, matchAge); ### `_.mixin([object=lodash], source, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6350 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6396 "View in source") [Ⓣ][1] Adds function properties of a source object to the destination object. If `object` is a function methods will be added to its prototype as well. @@ -4224,7 +4224,7 @@ _('fred').capitalize(); ### `_.noConflict()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6406 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6452 "View in source") [Ⓣ][1] Reverts the '_' variable to its previous value and returns a reference to the `lodash` function. @@ -4244,7 +4244,7 @@ var lodash = _.noConflict(); ### `_.noop()` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6423 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6469 "View in source") [Ⓣ][1] A no-operation function. @@ -4263,7 +4263,7 @@ _.noop(object) === undefined; ### `_.parseInt(value, [radix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6464 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6510 "View in source") [Ⓣ][1] Converts the given value into an integer of the specified radix. If `radix` is `undefined` or `0` a `radix` of `10` is used unless the `value` is a hexadecimal, in which case a `radix` of `16` is used. @@ -4290,7 +4290,7 @@ _.parseInt('08'); ### `_.property(key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6493 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6541 "View in source") [Ⓣ][1] Creates a "_.pluck" style function, which returns the `key` value of a given object. @@ -4324,7 +4324,7 @@ _.sortBy(characters, getName); ### `_.random([min=0], [max=1], [floating=false])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6526 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6574 "View in source") [Ⓣ][1] Produces a random number between `min` and `max` *(inclusive)*. If only one argument is provided a number between `0` and the given number will be returned. If `floating` is truey or either `min` or `max` are floats a floating-point number will be returned instead of an integer. @@ -4359,7 +4359,7 @@ _.random(1.2, 5.2); ### `_.result(object, key)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6584 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6633 "View in source") [Ⓣ][1] Resolves the value of property `key` on `object`. If `key` is a function it will be invoked with the `this` binding of `object` and its result returned, else the property value is returned. If `object` is falsey then `undefined` is returned. @@ -4394,7 +4394,7 @@ _.result(object, 'stuff'); ### `_.runInContext([context=root])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L485 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L515 "View in source") [Ⓣ][1] Create a new `lodash` function using the given context object. @@ -4412,7 +4412,7 @@ Create a new `lodash` function using the given context object. ### `_.template(text, data, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6677 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6726 "View in source") [Ⓣ][1] A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code. @@ -4504,7 +4504,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\ ### `_.times(n, callback, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6800 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6849 "View in source") [Ⓣ][1] Executes the callback `n` times, returning an array of the results of each callback execution. The callback is bound to `thisArg` and invoked with one argument; *(index)*. @@ -4536,7 +4536,7 @@ _.times(3, function(n) { this.cast(n); }, mage); ### `_.unescape(string)` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6830 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6879 "View in source") [Ⓣ][1] The inverse of `_.escape`; this method converts the HTML entities `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding characters. @@ -4562,7 +4562,7 @@ _.unescape('Fred, Barney & Pebbles'); ### `_.uniqueId([prefix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6854 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L6903 "View in source") [Ⓣ][1] Generates a unique ID. If `prefix` is provided the ID will be appended to it. @@ -4596,7 +4596,7 @@ _.uniqueId(); ### `_.templateSettings.imports._` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L900 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L924 "View in source") [Ⓣ][1] A reference to the `lodash` function. @@ -4615,7 +4615,7 @@ A reference to the `lodash` function. ### `_.VERSION` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7177 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L7226 "View in source") [Ⓣ][1] *(string)*: The semantic version number. @@ -4627,7 +4627,7 @@ A reference to the `lodash` function. ### `_.support` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L697 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L721 "View in source") [Ⓣ][1] *(Object)*: An object used to flag environments features. @@ -4639,7 +4639,7 @@ A reference to the `lodash` function. ### `_.support.argsClass` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L714 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L738 "View in source") [Ⓣ][1] *(boolean)*: Detect if an `arguments` object's [[Class]] is resolvable *(all but Firefox < `4`, IE < `9`)*. @@ -4651,7 +4651,7 @@ A reference to the `lodash` function. ### `_.support.argsObject` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L722 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L746 "View in source") [Ⓣ][1] *(boolean)*: Detect if `arguments` objects are `Object` objects *(all but Narwhal and Opera < `10.5`)*. @@ -4663,7 +4663,7 @@ A reference to the `lodash` function. ### `_.support.enumErrorProps` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L731 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L755 "View in source") [Ⓣ][1] *(boolean)*: Detect if `name` or `message` properties of `Error.prototype` are enumerable by default. *(IE < `9`, Safari < `5.1`)* @@ -4675,7 +4675,7 @@ A reference to the `lodash` function. ### `_.support.enumPrototypes` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L744 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L768 "View in source") [Ⓣ][1] *(boolean)*: Detect if `prototype` properties are enumerable by default. @@ -4689,7 +4689,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.funcDecomp` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L753 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L777 "View in source") [Ⓣ][1] *(boolean)*: Detect if functions can be decompiled by `Function#toString` *(all but PS3 and older Opera mobile browsers & avoided in Windows `8` apps)*. @@ -4701,7 +4701,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.funcNames` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L761 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L785 "View in source") [Ⓣ][1] *(boolean)*: Detect if `Function#name` is supported *(all but IE)*. @@ -4713,7 +4713,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.nonEnumArgs` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L770 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L794 "View in source") [Ⓣ][1] *(boolean)*: Detect if `arguments` object indexes are non-enumerable *(Firefox < `4`, IE < `9`, PhantomJS, Safari < `5.1`)*. @@ -4725,7 +4725,7 @@ Firefox < `3.6`, Opera > `9.50` - Opera < `11.60`, and Safari < `5.1` *(if the p ### `_.support.nonEnumShadows` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L781 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L805 "View in source") [Ⓣ][1] *(boolean)*: Detect if properties shadowing those on `Object.prototype` are non-enumerable. @@ -4739,7 +4739,7 @@ In IE < `9` an objects own properties, shadowing non-enumerable ones, are made n ### `_.support.ownLast` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L789 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L813 "View in source") [Ⓣ][1] *(boolean)*: Detect if own properties are iterated after inherited properties *(all but IE < `9`)*. @@ -4751,7 +4751,7 @@ In IE < `9` an objects own properties, shadowing non-enumerable ones, are made n ### `_.support.spliceObjects` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L803 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L827 "View in source") [Ⓣ][1] *(boolean)*: Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. @@ -4765,7 +4765,7 @@ Firefox < `10`, IE compatibility mode, and IE < `9` have buggy Array `shift()` a ### `_.support.unindexedChars` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L814 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L838 "View in source") [Ⓣ][1] *(boolean)*: Detect lack of support for accessing string characters by index. @@ -4779,7 +4779,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L852 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L876 "View in source") [Ⓣ][1] *(Object)*: By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby *(ERB)*. Change the following template settings to use alternative delimiters. @@ -4791,7 +4791,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.escape` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L860 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L884 "View in source") [Ⓣ][1] *(RegExp)*: Used to detect `data` property values to be HTML-escaped. @@ -4803,7 +4803,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.evaluate` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L868 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L892 "View in source") [Ⓣ][1] *(RegExp)*: Used to detect code to be evaluated. @@ -4815,7 +4815,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.interpolate` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L876 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L900 "View in source") [Ⓣ][1] *(RegExp)*: Used to detect `data` property values to inject. @@ -4827,7 +4827,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.variable` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L884 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L908 "View in source") [Ⓣ][1] *(string)*: Used to reference the data object in the template text. @@ -4839,7 +4839,7 @@ IE < `8` can't access characters by index and IE `8` can only access characters ### `_.templateSettings.imports` -# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L892 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/master/lodash.js#L916 "View in source") [Ⓣ][1] *(Object)*: Used to import variables into the compiled template. diff --git a/lodash.js b/lodash.js index f9d7cb2a4f..ea45e45930 100644 --- a/lodash.js +++ b/lodash.js @@ -30,7 +30,7 @@ /** Used as the max size of the `arrayPool` and `objectPool` */ var maxPoolSize = 40; - /** Used to detect and test whitespace */ + /** Used to detect and test whitespace (unicode 6.3.0) */ var whitespace = ( // whitespace ' \t\x0B\f\xA0\ufeff' + @@ -39,7 +39,7 @@ '\n\r\u2028\u2029' + // unicode category "Zs" space separators - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + '\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to match empty string literals in compiled template source */ @@ -47,6 +47,15 @@ reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + /** Used to match HTML entities and HTML characters */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g; + + /** Used to match template delimiters */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + /** * Used to match ES6 template delimiters * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals @@ -59,17 +68,11 @@ /** Used to detected named functions */ var reFuncName = /^\s*function[ \n\r\t]+\w/; - /** Used to match template delimiters */ - var reEscape = /<%-([\s\S]+?)%>/g, - reEvaluate = /<%([\s\S]+?)%>/g, - reInterpolate = /<%=([\s\S]+?)%>/g; + /** Used to detect hexadecimal string values */ + var reHexPrefix = /^0[xX]/; - /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, - reUnescapedHtml = /[&<>"']/g; - - /** Used to match leading whitespace and zeros to be removed */ - var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)'); + /** Used to match leading whitespace in strings */ + var reLeadingWhitespace = RegExp('^[' + whitespace + ']+'); /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; @@ -585,7 +588,8 @@ nativeMax = Math.max, nativeMin = Math.min, nativeParseInt = context.parseInt, - nativeRandom = Math.random; + nativeRandom = Math.random, + nativeTrim = isNative(nativeTrim = stringProto.trim) && nativeTrim; /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; @@ -1146,7 +1150,7 @@ function baseCreate(prototype, properties) { return isObject(prototype) ? nativeCreate(prototype) : {}; } - // fallback for browsers without `Object.create` + // fallback for environments without `Object.create` if (!nativeCreate) { baseCreate = (function() { function Object() {} @@ -1911,6 +1915,32 @@ return typeof result == 'undefined' || hasOwnProperty.call(value, result); } + /** + * Removes leading and trailing whitespace from a given string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function trim(string) { + return string == null ? '' : nativeTrim.call(string); + } + // fallback for environments without a proper `String#trim` + if (!nativeTrim || nativeTrim.call(whitespace)) { + trim = function(string) { + var start = -1, + end = string ? string.length : 0; + + if (!end || string == null) { + return ''; + } + string = String(string); + while (whitespace.indexOf(string.charAt(++start)) > -1) { } + while (whitespace.indexOf(string.charAt(--end)) > -1) { } + return string.slice(start, end + 1); + }; + } + /** * Used by `unescape` to convert HTML entities to characters. * @@ -1944,7 +1974,7 @@ return value && typeof value == 'object' && typeof value.length == 'number' && toString.call(value) == argsClass || false; } - // fallback for browsers that can't detect `arguments` objects by [[Class]] + // fallback for environments that can't detect `arguments` objects by [[Class]] if (!support.argsClass) { isArguments = function(value) { return value && typeof value == 'object' && typeof value.length == 'number' && @@ -6478,8 +6508,10 @@ * // => 8 */ var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) { - // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt` - return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0); + // Chrome fails to trim leading whitespace characters. + // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`. + value = trim(value); + return nativeParseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10)); }; /** diff --git a/test/test.js b/test/test.js index e7157da670..c02c933caf 100644 --- a/test/test.js +++ b/test/test.js @@ -2928,7 +2928,7 @@ (function() { test('should return the function names of an object', 1, function() { - var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.each }; + var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.forEach }; deepEqual(_.functions(object), ['b', 'd']); }); @@ -5722,22 +5722,56 @@ QUnit.module('lodash.parseInt'); (function() { - test('should parse strings with leading whitespace and zeros with a `radix` of 10 by default (test in Chrome, Firefox, and Opera)', 2, function() { - var whitespace = ' \x09\x0B\x0C\xA0\ufeff\x0A\x0D\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; - equal(_.parseInt('08'), 8); - equal(_.parseInt(whitespace + '08'), 8); + var whitespace = ' \t\x0B\f\xA0\ufeff\n\r\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; + + test('should accept a `radix` argument', function() { + var expected = _.range(2, 37); + + var actual = _.map(expected, function(radix) { + return _.parseInt('10', radix); + }); + + deepEqual(actual, expected); + }); + + test('should use a radix of `10`, for non-hexadecimals, if `radix` is `undefined` or `0`', 4, function() { + strictEqual(_.parseInt('10'), 10); + strictEqual(_.parseInt('10', 0), 10); + strictEqual(_.parseInt('10', 10), 10); + strictEqual(_.parseInt('10', undefined), 10); }); - test('should use a radix of `10`, for non-hexadecimals, if `radix` is `undefined` or `0`', 3, function() { - equal(_.parseInt('10', 0), 10); - equal(_.parseInt('10'), 10); - equal(_.parseInt('10', undefined), 10); + test('should use a radix of `16`, for hexadecimals, if `radix` is `undefined` or `0`', 8, function() { + _.forEach(['0x20', '0X20'], function(string) { + strictEqual(_.parseInt(string), 32); + strictEqual(_.parseInt(string, 0), 32); + strictEqual(_.parseInt(string, 16), 32); + strictEqual(_.parseInt(string, undefined), 32); + }); + }); + + test('should use a radix of `10` for string with leading zeros', 2, function() { + strictEqual(_.parseInt('08'), 8); + strictEqual(_.parseInt('08', 10), 8); + }); + + test('should parse strings with leading whitespace (test in Chrome, Firefox, and Opera)', 8, function() { + strictEqual(_.parseInt(whitespace + '10'), 10); + strictEqual(_.parseInt(whitespace + '10', 10), 10); + + strictEqual(_.parseInt(whitespace + '08'), 8); + strictEqual(_.parseInt(whitespace + '08', 10), 8); + + _.forEach(['0x20', '0X20'], function(string) { + strictEqual(_.parseInt(whitespace + string), 32); + strictEqual(_.parseInt(whitespace + string, 16), 32); + }); }); - test('should use a radix of `16`, for hexadecimals, if `radix` is `undefined` or `0`', 3, function() { - equal(_.parseInt('0x20', 0), 32); - equal(_.parseInt('0x20'), 32); - equal(_.parseInt('0x20', undefined), 32); + test('should coerce `radix` to a number', function() { + var object = { 'valueOf': function() { return 0; } }; + strictEqual(_.parseInt('08', object), 8); + strictEqual(_.parseInt('0x20', object), 32); }); }()); @@ -7112,7 +7146,7 @@ (function() { test('should use a `with` statement by default', 1, function() { - var compiled = _.template('<%= index %><%= collection[index] %><% _.each(collection, function(value, index) { %><%= index %><% }); %>'), + var compiled = _.template('<%= index %><%= collection[index] %><% _.forEach(collection, function(value, index) { %><%= index %><% }); %>'), actual = compiled({ 'index': 1, 'collection': ['a', 'b', 'c'] }); equal(actual, '1b012'); @@ -7204,7 +7238,7 @@ 'interpolate': /\{\{=([\s\S]+?)\}\}/g }); - var compiled = _.template('
      {{ _.each(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    '), + var compiled = _.template('
      {{ _.forEach(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    '), expected = '
    • 0: a & A
    • 1: b & B
    '; equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected); @@ -7220,7 +7254,7 @@ 'interpolate': /<\?=([\s\S]+?)\?>/g }); - var compiled = _.template('
    • :
    '), + var compiled = _.template('
    • :
    '), expected = '
    • 0: a & A
    • 1: b & B
    '; equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected); From 78f8a03da544b07449ade3829bbc47ec0a0e9b7e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 31 Dec 2013 00:23:30 -0600 Subject: [PATCH 0090/1608] Ensure the `trim` fallback is tested and counted for code coverage. --- test/index.html | 18 ++++++++++++++++++ test/test.js | 26 ++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/test/index.html b/test/index.html index 40463eeb2b..f4d575aa3b 100644 --- a/test/index.html +++ b/test/index.html @@ -44,6 +44,9 @@ String.prototype._contains = String.prototype.contains; String.prototype.contains = String.prototype._contains ? function() {} : Boolean; + String.prototype._trim = String.prototype.trim; + String.prototype.trim = function() {}; + window.WinRTError = Error; document._createDocumentFragment = document.createDocumentFragment; @@ -86,6 +89,20 @@ } else { delete String.prototype.contains; } + if (String.prototype._trim) { + if (Object.defineProperty) { + Object.defineProperty(String.prototype, 'trim', { + 'configurable': true, + 'enumerable': false, + 'writable': true, + 'value': String.prototype._trim + }); + } else { + String.prototype.trim = String.prototype._trim; + } + } else { + delete String.prototype.trim; + } window.WinRTError = undefined; document.createDocumentFragment = document._createDocumentFragment; @@ -99,6 +116,7 @@ delete Object._getPrototypeOf; delete Object._keys; delete String.prototype._contains; + delete String.prototype._trim; } addBizarroMethods(); diff --git a/test/test.js b/test/test.js index c02c933caf..76f19f13a5 100644 --- a/test/test.js +++ b/test/test.js @@ -264,6 +264,9 @@ var _contains = String.prototype.contains; String.prototype.contains = _contains ? function() {} : Boolean; + var _trim = String.prototype.trim; + String.prototype.trim = _trim ? function() {} : Boolean; + // load Lo-Dash and expose it to the bad extensions/shims lodashBizarro = (lodashBizarro = require(filePath))._ || lodashBizarro; @@ -280,6 +283,18 @@ } else { delete String.prototype.contains; } + if (_trim) { + // avoid a bug where overwriting non-enumerable built-ins makes them enumerable + // https://code.google.com/p/v8/issues/detail?id=1623 + defineProperty(String.prototype, 'trim', { + 'configurable': true, + 'enumerable': false, + 'writable': true, + 'value': _trim + }); + } else { + delete String.prototype.trim; + } delete global.window; delete global.WinRTError; delete Function.prototype._method; @@ -388,7 +403,7 @@ } }); - test('should avoid overwritten native methods', 8, function() { + test('should avoid overwritten native methods', 9, function() { function Foo() {} function message(methodName) { @@ -446,9 +461,16 @@ actual = null; } strictEqual(actual, true, message('String#contains')); + + try { + actual = lodashBizarro.parseInt(' 08 '); + } catch(e) { + actual = null; + } + strictEqual(actual, 8, message('String#trim')); } else { - skipTest(8); + skipTest(9); } }); }()); From 5965591934efbb778650f92d8f11d29dc3dbdf48 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 31 Dec 2013 20:23:25 -0600 Subject: [PATCH 0091/1608] Optimize `trim`. --- dist/lodash.compat.js | 21 ++++++- dist/lodash.compat.min.js | 114 +++++++++++++++++++------------------- dist/lodash.js | 21 ++++++- dist/lodash.min.js | 102 +++++++++++++++++----------------- lodash.js | 24 ++++++-- 5 files changed, 165 insertions(+), 117 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 401a6e154d..89c1aac197 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -441,6 +441,23 @@ return typeof value.toString != 'function' && typeof (value + '') == 'string'; } + /** + * Checks the given string to determine if the character at the specified + * index is whitespace. + * + * @private + * @param {string} string The string to inspect. + * @param {number} index The character index. + * @returns {boolean} Returns `true` if specifed character is whitespace, else `false`. + */ + function isWhitespaceAt(string, index) { + var c = string.charCodeAt(index); + return ( + (c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)) + ); + } + /** * Releases the given array back to the array pool. * @@ -1915,8 +1932,8 @@ return ''; } string = String(string); - while (whitespace.indexOf(string.charAt(++start)) > -1) { } - while (whitespace.indexOf(string.charAt(--end)) > -1) { } + while (++start < end && isWhitespaceAt(string, start)) { } + while (end-- && isWhitespaceAt(string, end)) { } return string.slice(start, end + 1); }; } diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 8e19d23319..93f1479d19 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -3,60 +3,60 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=w&&o===t,l=[]; -if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&g(e),l}function lt(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ot(t,r,3),typeof o=="number")for(Yr.unindexedChars&&Rt(u)&&(u=u.split(""));++e=w&&a===t,h=u||p?l():c;for(p&&(h=i(h),a=r);++oa(h,y))&&((u||p)&&h.push(y),c.push(v))}return p?(s(h.g),g(h)):u&&s(h),c}function vt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),ne(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ot,V,_r,Tr,Ct,wr,rt,Qr,J,jr,kr) -}function dt(n){return nt[n]}function bt(){var n=(n=e.indexOf)===Ht?t:n;return n}function _t(n){return typeof n=="function"&&Or.test(Ir.call(n))}function wt(n){var t,r;return!n||kr.call(n)!=G||(t=n.constructor,Nt(t)&&!(t instanceof t))||!Yr.argsClass&&Ct(n)||!Yr.nodeClass&&p(n)?false:Yr.ownLast?(ee(n,function(n,t,e){return r=Tr.call(e,t),false}),false!==r):(ee(n,function(n,t){r=t}),typeof r=="undefined"||Tr.call(n,r))}function jt(n){return null==n?"":Hr.call(n)}function xt(n){return tt[n]}function Ct(n){return n&&typeof n=="object"&&typeof n.length=="number"&&kr.call(n)==W||false -}function kt(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!ne(n)&&Rt(n))return Br?Br.call(n,t,r):-1r?Vr(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Rt(n)?u:e.createCallback(t,r,3),lt(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Mt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),ne(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),Wt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Ut(n){var t=-1,r=n?n.length:0,e=lr(typeof r=="number"?r:0);return Lt(n,function(n){var r=gt(0,++t);e[t]=e[r],e[r]=n}),e}function Xt(n,t,r){var u;if(t=e.createCallback(t,r,3),ne(n)){r=-1;for(var o=n.length;++re?Vr(0,u+e):e||0}else if(e)return e=Qt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y;m?(u&&(u=Sr(u)),c=a,o=n.apply(i,e)):u||(u=Dr(v,y))}return m&&f?f=Sr(f):f||t===p||(f=Dr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function er(n){return n}function ur(n){n||(n={});var t=re(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Tt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function or(n,t,r){var u=true,o=t&&At(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=At(t)),false===r?u=false:Tt(r)&&"chain"in r&&(u=r.chain); -var a=n,i=Nt(a);Lt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Pr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Tt(o))return this;o=new a(o),o.__chain__=t}return o})})}function ar(){}function ir(n){return function(t){return t[n]}}function fr(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var lr=n.Array,cr=n.Boolean,pr=n.Date,sr=n.Function,gr=n.Math,hr=n.Number,vr=n.Object,yr=n.RegExp,mr=n.String,dr=n.TypeError,br=lr.prototype,_r=n.Error.prototype,wr=vr.prototype,jr=mr.prototype,xr=(xr=n.window)&&xr.document,Cr=n._,kr=wr.toString,Or=yr("^"+mr(kr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Er=gr.ceil,Sr=n.clearTimeout,Ar=gr.floor,Ir=sr.prototype.toString,Nr=_t(Nr=vr.getPrototypeOf)&&Nr,Tr=wr.hasOwnProperty,Pr=br.push,Rr=wr.propertyIsEnumerable,Dr=n.setTimeout,qr=br.splice,Fr=br.unshift,$r=function(){try{var n={},t=_t(t=vr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),Br=_t(Br=jr.contains)&&Br,Lr=_t(Lr=vr.create)&&Lr,Wr=_t(Wr=lr.isArray)&&Wr,zr=n.isFinite,Kr=n.isNaN,Mr=_t(Mr=vr.keys)&&Mr,Vr=gr.max,Ur=gr.min,Xr=n.parseInt,Gr=gr.random,Hr=_t(Hr=jr.trim)&&Hr,Jr={};Jr[z]=lr,Jr[K]=cr,Jr[M]=pr,Jr[U]=sr,Jr[G]=vr,Jr[X]=hr,Jr[H]=yr,Jr[J]=mr;var Qr={};Qr[z]=Qr[M]=Qr[X]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Qr[K]=Qr[J]={constructor:true,toString:true,valueOf:true},Qr[V]=Qr[U]=Qr[H]={constructor:true,toString:true},Qr[G]={constructor:true},function(){for(var n=L.length;n--;){var t,r=L[n]; -for(t in Qr)Tr.call(Qr,t)&&!Tr.call(Qr[t],r)&&(Qr[t][r]=false)}}(),m.prototype=e.prototype;var Yr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Yr.argsClass=kr.call(arguments)==W,Yr.argsObject=arguments.constructor==vr&&!(arguments instanceof lr),Yr.enumErrorProps=Rr.call(_r,"message")||Rr.call(_r,"name"),Yr.enumPrototypes=Rr.call(t,"prototype"),Yr.funcDecomp=!_t(n.WinRTError)&&F.test(v),Yr.funcNames=typeof sr.name=="string",Yr.nonEnumArgs=0!=u,Yr.nonEnumShadows=!/valueOf/.test(e),Yr.ownLast="x"!=e[0],Yr.spliceObjects=(qr.call(r,0,1),!r[0]),Yr.unindexedChars="xx"!="x"[0]+vr("x")[0]; -try{Yr.dom=11===xr.createDocumentFragment().nodeType}catch(o){Yr.dom=false}try{Yr.nodeClass=!(kr.call(undefined)==G&&!({toString:0}+""))}catch(a){Yr.nodeClass=true}}(1),e.templateSettings={escape:A,evaluate:I,interpolate:N,variable:"",imports:{_:e}},Lr||(et=function(){function t(){}return function(r){if(Tt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var Zr=$r?function(n,t){Z.value=t,$r(n,"__bindData__",Z)}:ar;(!Hr||Hr.call(x))&&(jt=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=mr(n);-1--n?t.apply(this,arguments):void 0}},e.assign=kt,e.at=function(n){var t=arguments,r=-1,e=ct(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=lr(t);for(Yr.unindexedChars&&Rt(n)&&(n=n.split(""));++r=w&&i(e?n[e]:c)))}var f=n[0],h=-1,v=f?f.length:0,y=[];n:for(;++h(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p) -}}for(;u--;)(m=o[u])&&g(m);return s(o),s(c),y},e.invert=function(n,t){for(var r=-1,e=re(n),u=e.length,o={};++rr?Vr(0,e+r):Ur(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=or,e.noConflict=function(){return n._=Cr,this},e.noop=ar,e.now=le,e.parseInt=ce,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Gr(),Ur(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):gt(n,t) -},e.reduce=Mt,e.reduceRight=Vt,e.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},e.runInContext=v,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:re(n).length},e.some=Xt,e.sortedIndex=Qt,e.template=function(n,t,r){var u=e.templateSettings;n=mr(n||""),r=Ot({},r,u);var o,a=Ot({},r.imports,u.imports),u=re(a),a=Dt(a),i=0,l=r.interpolate||q,c="__p+='",l=yr((r.escape||q).source+"|"+l.source+"|"+(l===N?T:q).source+"|"+(r.evaluate||q).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace($,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t -}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(C,""):c).replace(k,"$1").replace(O,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=sr(u,"return "+c).apply(y,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=mr(n),0>n.indexOf(";")?n:n.replace(E,xt))},e.uniqueId=function(n){var t=++b; -return mr(null==n?"":n)+t},e.all=Ft,e.any=Xt,e.detect=Bt,e.findWhere=Bt,e.foldl=Mt,e.foldr=Vt,e.include=qt,e.inject=Mt,or(function(){var n={};return Et(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Gt,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:y;return h(n,Vr(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Dt(n):Yr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[gt(0,n.length-1)]:y:(n=Ut(n),n.length=Ur(Vr(0,t),n.length),n) -},e.take=Gt,e.head=Gt,Et(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new m(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return mr(this.__wrapped__)},e.prototype.value=fr,e.prototype.valueOf=fr,lt(["join","pop","shift"],function(n){var t=br[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new m(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=br[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),lt(["concat","slice","splice"],function(n){var t=br[n];e.prototype[n]=function(){return new m(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Yr.spliceObjects||lt(["pop","shift","splice"],function(n){var t=br[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new m(u,n):u -}}),e}var y,m=[],d=[],b=0,_=+new Date+"",w=75,j=40,x=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",C=/\b__p\+='';/g,k=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/&(?:amp|lt|gt|quot|#39);/g,S=/[&<>"']/g,A=/<%-([\s\S]+?)%>/g,I=/<%([\s\S]+?)%>/g,N=/<%=([\s\S]+?)%>/g,T=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,q=/($^)/,F=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,B="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),L="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),W="[object Arguments]",z="[object Array]",K="[object Boolean]",M="[object Date]",V="[object Error]",U="[object Function]",X="[object Number]",G="[object Object]",H="[object RegExp]",J="[object String]",Q={}; -Q[U]=false,Q[W]=Q[z]=Q[K]=Q[M]=Q[X]=Q[G]=Q[H]=Q[J]=true;var Y={leading:false,maxWait:0,trailing:false},Z={configurable:false,enumerable:false,value:null,writable:false},nt={"&":"&","<":"<",">":">",'"':""","'":"'"},tt={"&":"&","<":"<",">":">",""":'"',"'":"'"},rt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},et={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ut=rt[typeof window]&&window||this,ot=rt[typeof exports]&&exports&&!exports.nodeType&&exports,at=rt[typeof global]&&global; -!at||at.global!==at&&at.window!==at||(ut=at);var it=(at=rt[typeof module]&&module&&!module.nodeType&&module)&&at.exports===ot&&ot,ft=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ut._=ft, define(function(){return ft})):ot&&at?it?(at.exports=ft)._=ft:ot._=ft:ut._=ft}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(n=r&&9<=r&&13>=r||32==r||160==r||5760==r||6158==r||8192<=r&&(8202>=r||8232==r||8233==r||8239==r||8287==r||12288==r||65279==r)}function g(n){n.length=0,d.lengthr?0:r);++e=j&&o===t,l=[];if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&h(e),l}function ct(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:at(t,r,3),typeof o=="number")for(Zr.unindexedChars&&Dt(u)&&(u=u.split(""));++e=j&&a===t,s=u||p?l():c;for(p&&(s=i(s),a=r);++oa(s,y))&&((u||p)&&s.push(y),c.push(v))}return p?(g(s.g),h(s)):u&&g(s),c}function yt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),te(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(at,U,wr,Pr,kt,jr,et,Yr,Q,xr,Or) +}function bt(n){return tt[n]}function _t(){var n=(n=e.indexOf)===Jt?t:n;return n}function wt(n){return typeof n=="function"&&Er.test(Nr.call(n))}function jt(n){var t,r;return!n||Or.call(n)!=H||(t=n.constructor,Tt(t)&&!(t instanceof t))||!Zr.argsClass&&kt(n)||!Zr.nodeClass&&p(n)?false:Zr.ownLast?(ue(n,function(n,t,e){return r=Pr.call(e,t),false}),false!==r):(ue(n,function(n,t){r=t}),typeof r=="undefined"||Pr.call(n,r))}function xt(n){return null==n?"":Jr.call(n)}function Ct(n){return rt[n]}function kt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Or.call(n)==z||false +}function Ot(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!te(n)&&Dt(n))return Lr?Lr.call(n,t,r):-1r?Ur(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Dt(n)?u:e.createCallback(t,r,3),ct(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Vt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),te(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),zt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Xt(n){var t=-1,r=n?n.length:0,e=cr(typeof r=="number"?r:0);return Wt(n,function(n){var r=ht(0,++t);e[t]=e[r],e[r]=n}),e}function Gt(n,t,r){var u;if(t=e.createCallback(t,r,3),te(n)){r=-1;for(var o=n.length;++re?Ur(0,u+e):e||0}else if(e)return e=Yt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Qt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y;m?(u&&(u=Ar(u)),c=a,o=n.apply(i,e)):u||(u=qr(v,y))}return m&&f?f=Ar(f):f||t===p||(f=qr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function ur(n){return n}function or(n){n||(n={});var t=ee(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Pt(e)?function(r){for(var e=t.length,u=false;e--&&(u=st(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function ar(n,t,r){var u=true,o=t&&It(t);t&&(r||o.length)||(null==r&&(r=t),a=d,t=n,n=e,o=It(t)),false===r?u=false:Pt(r)&&"chain"in r&&(u=r.chain); +var a=n,i=Tt(a);Wt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Rr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Pt(o))return this;o=new a(o),o.__chain__=t}return o})})}function ir(){}function fr(n){return function(t){return t[n]}}function lr(){return this.__wrapped__}n=n?lt.defaults(ot.Object(),n,lt.pick(ot,L)):ot;var cr=n.Array,pr=n.Boolean,sr=n.Date,gr=n.Function,hr=n.Math,vr=n.Number,yr=n.Object,mr=n.RegExp,dr=n.String,br=n.TypeError,_r=cr.prototype,wr=n.Error.prototype,jr=yr.prototype,xr=dr.prototype,Cr=(Cr=n.window)&&Cr.document,kr=n._,Or=jr.toString,Er=mr("^"+dr(Or).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Sr=hr.ceil,Ar=n.clearTimeout,Ir=hr.floor,Nr=gr.prototype.toString,Tr=wt(Tr=yr.getPrototypeOf)&&Tr,Pr=jr.hasOwnProperty,Rr=_r.push,Dr=jr.propertyIsEnumerable,qr=n.setTimeout,Fr=_r.splice,$r=_r.unshift,Br=function(){try{var n={},t=wt(t=yr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Lr=wt(Lr=xr.contains)&&Lr,Wr=wt(Wr=yr.create)&&Wr,zr=wt(zr=cr.isArray)&&zr,Kr=n.isFinite,Mr=n.isNaN,Vr=wt(Vr=yr.keys)&&Vr,Ur=hr.max,Xr=hr.min,Gr=n.parseInt,Hr=hr.random,Jr=wt(Jr=xr.trim)&&Jr,Qr={};Qr[K]=cr,Qr[M]=pr,Qr[V]=sr,Qr[X]=gr,Qr[H]=yr,Qr[G]=vr,Qr[J]=mr,Qr[Q]=dr;var Yr={};Yr[K]=Yr[V]=Yr[G]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Yr[M]=Yr[Q]={constructor:true,toString:true,valueOf:true},Yr[U]=Yr[X]=Yr[J]={constructor:true,toString:true},Yr[H]={constructor:true},function(){for(var n=W.length;n--;){var t,r=W[n]; +for(t in Yr)Pr.call(Yr,t)&&!Pr.call(Yr[t],r)&&(Yr[t][r]=false)}}(),d.prototype=e.prototype;var Zr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Zr.argsClass=Or.call(arguments)==z,Zr.argsObject=arguments.constructor==yr&&!(arguments instanceof cr),Zr.enumErrorProps=Dr.call(wr,"message")||Dr.call(wr,"name"),Zr.enumPrototypes=Dr.call(t,"prototype"),Zr.funcDecomp=!wt(n.WinRTError)&&$.test(y),Zr.funcNames=typeof gr.name=="string",Zr.nonEnumArgs=0!=u,Zr.nonEnumShadows=!/valueOf/.test(e),Zr.ownLast="x"!=e[0],Zr.spliceObjects=(Fr.call(r,0,1),!r[0]),Zr.unindexedChars="xx"!="x"[0]+yr("x")[0]; +try{Zr.dom=11===Cr.createDocumentFragment().nodeType}catch(o){Zr.dom=false}try{Zr.nodeClass=!(Or.call(undefined)==H&&!({toString:0}+""))}catch(a){Zr.nodeClass=true}}(1),e.templateSettings={escape:I,evaluate:N,interpolate:T,variable:"",imports:{_:e}},Wr||(ut=function(){function t(){}return function(r){if(Pt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var ne=Br?function(n,t){nt.value=t,Br(n,"__bindData__",nt)}:ir;(!Jr||Jr.call(C))&&(xt=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=dr(n);++t--n?t.apply(this,arguments):void 0}},e.assign=Ot,e.at=function(n){var t=arguments,r=-1,e=pt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=cr(t);for(Zr.unindexedChars&&Dt(n)&&(n=n.split(""));++r=j&&i(e?n[e]:c)))}var f=n[0],s=-1,v=f?f.length:0,y=[];n:for(;++s(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p) +}}for(;u--;)(m=o[u])&&h(m);return g(o),g(c),y},e.invert=function(n,t){for(var r=-1,e=ee(n),u=e.length,o={};++rr?Ur(0,e+r):Xr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=ar,e.noConflict=function(){return n._=kr,this},e.noop=ir,e.now=ce,e.parseInt=pe,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Hr(),Xr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):ht(n,t) +},e.reduce=Vt,e.reduceRight=Ut,e.result=function(n,t){if(n){var r=n[t];return Tt(r)?n[t]():r}},e.runInContext=y,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ee(n).length},e.some=Gt,e.sortedIndex=Yt,e.template=function(n,t,r){var u=e.templateSettings;n=dr(n||""),r=Et({},r,u);var o,a=Et({},r.imports,u.imports),u=ee(a),a=qt(a),i=0,l=r.interpolate||F,c="__p+='",l=mr((r.escape||F).source+"|"+l.source+"|"+(l===T?P:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace(B,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t +}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(k,""):c).replace(O,"$1").replace(E,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=gr(u,"return "+c).apply(m,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=dr(n),0>n.indexOf(";")?n:n.replace(S,Ct))},e.uniqueId=function(n){var t=++_; +return dr(null==n?"":n)+t},e.all=$t,e.any=Gt,e.detect=Lt,e.findWhere=Lt,e.foldl=Vt,e.foldr=Ut,e.include=Ft,e.inject=Vt,ar(function(){var n={};return St(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Ht,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:m;return v(n,Ur(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=qt(n):Zr.unindexedChars&&Dt(n)&&(n=n.split("")),null==t||r?n?n[ht(0,n.length-1)]:m:(n=Xt(n),n.length=Xr(Ur(0,t),n.length),n) +},e.take=Ht,e.head=Ht,St(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new d(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return dr(this.__wrapped__)},e.prototype.value=lr,e.prototype.valueOf=lr,ct(["join","pop","shift"],function(n){var t=_r[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new d(r,n):r}}),ct(["push","reverse","sort","unshift"],function(n){var t=_r[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ct(["concat","slice","splice"],function(n){var t=_r[n];e.prototype[n]=function(){return new d(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Zr.spliceObjects||ct(["pop","shift","splice"],function(n){var t=_r[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new d(u,n):u +}}),e}var m,d=[],b=[],_=0,w=+new Date+"",j=75,x=40,C=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,O=/\b(__p\+=)''\+/g,E=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39);/g,A=/[&<>"']/g,I=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,T=/<%=([\s\S]+?)%>/g,P=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,R=/\w*$/,D=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,F=/($^)/,$=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,L="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),z="[object Arguments]",K="[object Array]",M="[object Boolean]",V="[object Date]",U="[object Error]",X="[object Function]",G="[object Number]",H="[object Object]",J="[object RegExp]",Q="[object String]",Y={}; +Y[X]=false,Y[z]=Y[K]=Y[M]=Y[V]=Y[G]=Y[H]=Y[J]=Y[Q]=true;var Z={leading:false,maxWait:0,trailing:false},nt={configurable:false,enumerable:false,value:null,writable:false},tt={"&":"&","<":"<",">":">",'"':""","'":"'"},rt={"&":"&","<":"<",">":">",""":'"',"'":"'"},et={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},ut={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ot=et[typeof window]&&window||this,at=et[typeof exports]&&exports&&!exports.nodeType&&exports,it=et[typeof global]&&global; +!it||it.global!==it&&it.window!==it||(ot=it);var ft=(it=et[typeof module]&&module&&!module.nodeType&&module)&&it.exports===at&&at,lt=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ot._=lt, define(function(){return lt})):at&&it?ft?(it.exports=lt)._=lt:at._=lt:ot._=lt}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 3697150843..d558c68448 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -418,6 +418,23 @@ }; } + /** + * Checks the given string to determine if the character at the specified + * index is whitespace. + * + * @private + * @param {string} string The string to inspect. + * @param {number} index The character index. + * @returns {boolean} Returns `true` if specifed character is whitespace, else `false`. + */ + function isWhitespaceAt(string, index) { + var c = string.charCodeAt(index); + return ( + (c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)) + ); + } + /** * Releases the given array back to the array pool. * @@ -1614,8 +1631,8 @@ return ''; } string = String(string); - while (whitespace.indexOf(string.charAt(++start)) > -1) { } - while (whitespace.indexOf(string.charAt(--end)) > -1) { } + while (++start < end && isWhitespaceAt(string, start)) { } + while (end-- && isWhitespaceAt(string, end)) { } return string.slice(start, end + 1); }; } diff --git a/dist/lodash.min.js b/dist/lodash.min.js index d250b91e7c..fea0e8ad48 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,54 +3,54 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=_&&o===t,l=[]; -if(f){var c=a(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&s(e),l}function ft(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e=_&&i===t,v=u||h?l():c;for(h&&(v=a(v),i=r);++oi(v,y))&&((u||h)&&v.push(y),c.push(g)) -}return h?(p(v.g),s(v)):u&&p(v),c}function ht(n){return function(t,r,e){var u={};r=m.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++e=e)return false;if(typeof n=="string"||!Hr(n)&&St(n))return Dr?Dr.call(n,t,r):-1r?zr(0,e+r):r)||0,-1o&&(o=a)}}else t=null==t&&St(n)?u:m.createCallback(t,r,3),Bt(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function Pt(n,t,r,e){var u=3>arguments.length;t=m.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=m.createCallback(t,e,4),qt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) -}),r}function Lt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Bt(n,function(n){var r=pt(0,++t);e[t]=e[r],e[r]=n}),e}function Mt(n,t,r){var e;t=m.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?zr(0,u+e):e||0}else if(e)return e=Gt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=g;m?(i&&(i=xr(i)),s=f,a=n.apply(l,o)):i||(i=Ir(e,g))}return m&&c?c=xr(c):c||t===h||(c=Ir(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function nr(n){return n}function tr(n){n||(n={});var t=Jr(n),r=t[0],e=n[r]; -return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=lt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function rr(n,t,r){var e=true,u=t&&Ot(t);t&&(r||u.length)||(null==r&&(r=t),o=w,t=n,n=m,u=Ot(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain);var o=n,i=Nt(o);Bt(u,function(r){var u=n[r]=t[r];i&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,i=[r];if(Ar.apply(i,arguments),i=u.apply(n,i),e||t){if(r===i&&At(i))return this; -i=new o(i),i.__chain__=t}return i})})}function er(){}function ur(n){return function(t){return t[n]}}function or(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var ir=n.Array,ar=n.Boolean,fr=n.Date,lr=n.Function,cr=n.Math,pr=n.Number,sr=n.Object,hr=n.RegExp,vr=n.String,gr=n.TypeError,yr=ir.prototype,mr=sr.prototype,br=vr.prototype,dr=(dr=n.window)&&dr.document,_r=n._,wr=mr.toString,jr=hr("^"+vr(wr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),kr=cr.ceil,xr=n.clearTimeout,Cr=cr.floor,Or=lr.prototype.toString,Er=mt(Er=sr.getPrototypeOf)&&Er,Nr=mr.hasOwnProperty,Ar=yr.push,Ir=n.setTimeout,Sr=yr.splice,Tr=yr.unshift,Rr=function(){try{var n={},t=mt(t=sr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),Dr=mt(Dr=br.contains)&&Dr,Fr=mt(Fr=sr.create)&&Fr,$r=mt($r=ir.isArray)&&$r,Br=n.isFinite,qr=n.isNaN,Wr=mt(Wr=sr.keys)&&Wr,zr=cr.max,Pr=cr.min,Kr=n.parseInt,Lr=cr.random,Mr=mt(Mr=br.trim)&&Mr,Vr={};Vr[z]=ir,Vr[P]=ar,Vr[K]=fr,Vr[L]=lr,Vr[V]=sr,Vr[M]=pr,Vr[U]=hr,Vr[X]=vr,w.prototype=m.prototype;var Ur=m.support={};Ur.funcDecomp=!mt(n.WinRTError)&&$.test(v),Ur.funcNames=typeof lr.name=="string";try{Ur.dom=11===dr.createDocumentFragment().nodeType}catch(Xr){Ur.dom=false}m.templateSettings={escape:N,evaluate:A,interpolate:I,variable:"",imports:{_:m}},Fr||(et=function(){function t(){}return function(r){if(At(r)){t.prototype=r; -var e=new t;t.prototype=null}return e||n.Object()}}());var Gr=Rr?function(n,t){J.value=t,Rr(n,"__bindData__",J)}:er;(!Mr||Mr.call(j))&&(dt=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=vr(n);-1--n?t.apply(this,arguments):void 0 -}},m.assign=jt,m.at=function(n){for(var t=arguments,r=-1,e=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ir(t);++r=_&&a(e?n[e]:c))) -}var f=n[0],v=-1,g=f?f.length:0,y=[];n:for(;++v(m?r(m,h):i(c,h))){for(e=u,(m||c).push(h);--e;)if(m=o[e],0>(m?r(m,h):i(n[e],h)))continue n;y.push(h)}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var r=-1,e=Jr(n),u=e.length,o={};++rr?zr(0,e+r):Pr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},m.mixin=rr,m.noConflict=function(){return n._=_r,this},m.noop=er,m.now=re,m.parseInt=ee,m.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Lr(),Pr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):pt(n,t) -},m.reduce=Pt,m.reduceRight=Kt,m.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},m.runInContext=v,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Jr(n).length},m.some=Mt,m.sortedIndex=Gt,m.template=function(n,t,r){var e=m.templateSettings;n=vr(n||""),r=kt({},r,e);var u,o=kt({},r.imports,e.imports),e=Jr(o),o=Tt(o),i=0,a=r.interpolate||F,l="__p+='",a=hr((r.escape||F).source+"|"+a.source+"|"+(a===I?S:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(B,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t -}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=lr(e,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=vr(n),0>n.indexOf(";")?n:n.replace(O,_t))},m.uniqueId=function(n){var t=++b; -return vr(null==n?"":n)+t},m.all=Dt,m.any=Mt,m.detect=$t,m.findWhere=$t,m.foldl=Pt,m.foldr=Kt,m.include=Rt,m.inject=Pt,rr(function(){var n={};return xt(m,function(t,r){m.prototype[r]||(n[r]=t)}),n}(),false),m.first=Vt,m.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:g;return h(n,zr(0,u-e))},m.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Tt(n)),null==t||r?n?n[pt(0,n.length-1)]:g:(n=Lt(n),n.length=Pr(zr(0,t),n.length),n) -},m.take=Vt,m.head=Vt,xt(m,function(n,t){var r="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return vr(this.__wrapped__)},m.prototype.value=or,m.prototype.valueOf=or,Bt(["join","pop","shift"],function(n){var t=yr[n];m.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new w(r,n):r}}),Bt(["push","reverse","sort","unshift"],function(n){var t=yr[n];m.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Bt(["concat","slice","splice"],function(n){var t=yr[n];m.prototype[n]=function(){return new w(t.apply(this.__wrapped__,arguments),this.__chain__)}}),m}var g,y=[],m=[],b=0,d=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,O=/&(?:amp|lt|gt|quot|#39);/g,E=/[&<>"']/g,N=/<%-([\s\S]+?)%>/g,A=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,S=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,T=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,F=/($^)/,$=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="[object Arguments]",z="[object Array]",P="[object Boolean]",K="[object Date]",L="[object Function]",M="[object Number]",V="[object Object]",U="[object RegExp]",X="[object String]",G={}; -G[L]=false,G[W]=G[z]=G[P]=G[K]=G[M]=G[V]=G[U]=G[X]=true;var H={leading:false,maxWait:0,trailing:false},J={configurable:false,enumerable:false,value:null,writable:false},Q={"&":"&","<":"<",">":">",'"':""","'":"'"},Y={"&":"&","<":"<",">":">",""":'"',"'":"'"},Z={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},nt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},tt=Z[typeof window]&&window||this,rt=Z[typeof exports]&&exports&&!exports.nodeType&&exports,et=Z[typeof global]&&global; -!et||et.global!==et&&et.window!==et||(tt=et);var ut=(et=Z[typeof module]&&module&&!module.nodeType&&module)&&et.exports===rt&&rt,ot=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):rt&&et?ut?(et.exports=ot)._=ot:rt._=ot:tt._=ot}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(n=r&&9<=r&&13>=r||32==r||160==r||5760==r||6158==r||8192<=r&&(8202>=r||8232==r||8233==r||8239==r||8287==r||12288==r||65279==r)}function s(n){n.length=0,m.lengthr?0:r);++e=w&&o===t,l=[];if(f){var c=a(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&v(e),l}function lt(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e=w&&i===t,h=u||p?l():c; +for(p&&(h=a(h),i=r);++oi(h,y))&&((u||p)&&h.push(y),c.push(g))}return p?(s(h.g),v(h)):u&&s(h),c}function ht(n){return function(t,r,e){var u={};r=b.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++e=e)return false;if(typeof n=="string"||!Jr(n)&&At(n))return Fr?Fr.call(n,t,r):-1r?Pr(0,e+r):r)||0,-1o&&(o=a)}}else t=null==t&&At(n)?u:b.createCallback(t,r,3),qt(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function Kt(n,t,r,e){var u=3>arguments.length;t=b.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=b.createCallback(t,e,4),Wt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ar(typeof r=="number"?r:0);return qt(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;t=b.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Pr(0,u+e):e||0}else if(e)return e=Ht(n,r),n[e]===r?e:-1;return t(n,r,e)}function Gt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=b.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=y; +m?(i&&(i=Cr(i)),s=f,a=n.apply(l,o)):i||(i=Tr(e,y))}return m&&c?c=Cr(c):c||t===v||(c=Tr(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function tr(n){return n}function rr(n){n||(n={});var t=Qr(n),r=t[0],e=n[r];return 1!=t.length||e!==e||St(e)?function(r){for(var e=t.length,u=false;e--&&(u=ct(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function er(n,t,r){var e=true,u=t&&Et(t);t&&(r||u.length)||(null==r&&(r=t),o=j,t=n,n=b,u=Et(t)),false===r?e=false:St(r)&&"chain"in r&&(e=r.chain); +var o=n,i=It(o);qt(u,function(r){var u=n[r]=t[r];i&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,i=[r];if(Sr.apply(i,arguments),i=u.apply(n,i),e||t){if(r===i&&St(i))return this;i=new o(i),i.__chain__=t}return i})})}function ur(){}function or(n){return function(t){return t[n]}}function ir(){return this.__wrapped__}n=n?it.defaults(rt.Object(),n,it.pick(rt,W)):rt;var ar=n.Array,fr=n.Boolean,lr=n.Date,cr=n.Function,pr=n.Math,sr=n.Number,vr=n.Object,hr=n.RegExp,gr=n.String,yr=n.TypeError,mr=ar.prototype,br=vr.prototype,dr=gr.prototype,_r=(_r=n.window)&&_r.document,wr=n._,jr=br.toString,kr=hr("^"+gr(jr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),xr=pr.ceil,Cr=n.clearTimeout,Or=pr.floor,Er=cr.prototype.toString,Nr=bt(Nr=vr.getPrototypeOf)&&Nr,Ir=br.hasOwnProperty,Sr=mr.push,Tr=n.setTimeout,Ar=mr.splice,Rr=mr.unshift,Dr=function(){try{var n={},t=bt(t=vr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Fr=bt(Fr=dr.contains)&&Fr,$r=bt($r=vr.create)&&$r,Br=bt(Br=ar.isArray)&&Br,qr=n.isFinite,Wr=n.isNaN,zr=bt(zr=vr.keys)&&zr,Pr=pr.max,Kr=pr.min,Lr=n.parseInt,Mr=pr.random,Vr=bt(Vr=dr.trim)&&Vr,Ur={};Ur[P]=ar,Ur[K]=fr,Ur[L]=lr,Ur[M]=cr,Ur[U]=vr,Ur[V]=sr,Ur[X]=hr,Ur[G]=gr,j.prototype=b.prototype;var Xr=b.support={};Xr.funcDecomp=!bt(n.WinRTError)&&B.test(g),Xr.funcNames=typeof cr.name=="string";try{Xr.dom=11===_r.createDocumentFragment().nodeType}catch(Gr){Xr.dom=false}b.templateSettings={escape:I,evaluate:S,interpolate:T,variable:"",imports:{_:b}},$r||(ut=function(){function t(){}return function(r){if(St(r)){t.prototype=r; +var e=new t;t.prototype=null}return e||n.Object()}}());var Hr=Dr?function(n,t){Q.value=t,Dr(n,"__bindData__",Q)}:ur;(!Vr||Vr.call(k))&&(_t=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=gr(n);++t--n?t.apply(this,arguments):void 0}},b.assign=kt,b.at=function(n){for(var t=arguments,r=-1,e=lt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ar(t);++r=w&&a(e?n[e]:c)))}var f=n[0],h=-1,g=f?f.length:0,y=[];n:for(;++h(m?r(m,p):i(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):i(n[e],p)))continue n;y.push(p)}}for(;u--;)(m=o[u])&&v(m);return s(o),s(c),y},b.invert=function(n,t){for(var r=-1,e=Qr(n),u=e.length,o={};++rr?Pr(0,e+r):Kr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},b.mixin=er,b.noConflict=function(){return n._=wr,this},b.noop=ur,b.now=ee,b.parseInt=ue,b.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Mr(),Kr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) +},b.reduce=Kt,b.reduceRight=Lt,b.result=function(n,t){if(n){var r=n[t];return It(r)?n[t]():r}},b.runInContext=g,b.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Qr(n).length},b.some=Vt,b.sortedIndex=Ht,b.template=function(n,t,r){var e=b.templateSettings;n=gr(n||""),r=xt({},r,e);var u,o=xt({},r.imports,e.imports),e=Qr(o),o=Rt(o),i=0,a=r.interpolate||$,l="__p+='",a=hr((r.escape||$).source+"|"+a.source+"|"+(a===T?A:$).source+"|"+(r.evaluate||$).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(q,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t +}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(x,""):l).replace(C,"$1").replace(O,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=cr(e,"return "+l).apply(y,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},b.unescape=function(n){return null==n?"":(n=gr(n),0>n.indexOf(";")?n:n.replace(E,wt))},b.uniqueId=function(n){var t=++d; +return gr(null==n?"":n)+t},b.all=Ft,b.any=Vt,b.detect=Bt,b.findWhere=Bt,b.foldl=Kt,b.foldr=Lt,b.include=Dt,b.inject=Kt,er(function(){var n={};return Ct(b,function(t,r){b.prototype[r]||(n[r]=t)}),n}(),false),b.first=Ut,b.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=b.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:y;return h(n,Pr(0,u-e))},b.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Rt(n)),null==t||r?n?n[st(0,n.length-1)]:y:(n=Mt(n),n.length=Kr(Pr(0,t),n.length),n) +},b.take=Ut,b.head=Ut,Ct(b,function(n,t){var r="sample"!==t;b.prototype[t]||(b.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new j(o,u):o})}),b.VERSION="2.4.1",b.prototype.chain=function(){return this.__chain__=true,this},b.prototype.toString=function(){return gr(this.__wrapped__)},b.prototype.value=ir,b.prototype.valueOf=ir,qt(["join","pop","shift"],function(n){var t=mr[n];b.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new j(r,n):r}}),qt(["push","reverse","sort","unshift"],function(n){var t=mr[n];b.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),qt(["concat","slice","splice"],function(n){var t=mr[n];b.prototype[n]=function(){return new j(t.apply(this.__wrapped__,arguments),this.__chain__)}}),b}var y,m=[],b=[],d=0,_=+new Date+"",w=75,j=40,k=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",x=/\b__p\+='';/g,C=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/&(?:amp|lt|gt|quot|#39);/g,N=/[&<>"']/g,I=/<%-([\s\S]+?)%>/g,S=/<%([\s\S]+?)%>/g,T=/<%=([\s\S]+?)%>/g,A=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,R=/\w*$/,D=/^\s*function[ \n\r\t]+\w/,F=/^0[xX]/,$=/($^)/,B=/\bthis\b/,q=/['\n\r\t\u2028\u2029\\]/g,W="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),z="[object Arguments]",P="[object Array]",K="[object Boolean]",L="[object Date]",M="[object Function]",V="[object Number]",U="[object Object]",X="[object RegExp]",G="[object String]",H={}; +H[M]=false,H[z]=H[P]=H[K]=H[L]=H[V]=H[U]=H[X]=H[G]=true;var J={leading:false,maxWait:0,trailing:false},Q={configurable:false,enumerable:false,value:null,writable:false},Y={"&":"&","<":"<",">":">",'"':""","'":"'"},Z={"&":"&","<":"<",">":">",""":'"',"'":"'"},nt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},tt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},rt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof global]&&global; +!ut||ut.global!==ut&&ut.window!==ut||(rt=ut);var ot=(ut=nt[typeof module]&&module&&!module.nodeType&&module)&&ut.exports===et&&et,it=g();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(rt._=it, define(function(){return it})):et&&ut?ot?(ut.exports=it)._=it:et._=it:rt._=it}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index ea45e45930..4bb99ee7de 100644 --- a/lodash.js +++ b/lodash.js @@ -71,9 +71,6 @@ /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; - /** Used to match leading whitespace in strings */ - var reLeadingWhitespace = RegExp('^[' + whitespace + ']+'); - /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; @@ -443,6 +440,23 @@ return typeof value.toString != 'function' && typeof (value + '') == 'string'; } + /** + * Checks the given string to determine if the character at the specified + * index is whitespace. + * + * @private + * @param {string} string The string to inspect. + * @param {number} index The character index. + * @returns {boolean} Returns `true` if specifed character is whitespace, else `false`. + */ + function isWhitespaceAt(string, index) { + var c = string.charCodeAt(index); + return ( + (c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)) + ); + } + /** * Releases the given array back to the array pool. * @@ -1935,8 +1949,8 @@ return ''; } string = String(string); - while (whitespace.indexOf(string.charAt(++start)) > -1) { } - while (whitespace.indexOf(string.charAt(--end)) > -1) { } + while (++start < end && isWhitespaceAt(string, start)) { } + while (end-- && isWhitespaceAt(string, end)) { } return string.slice(start, end + 1); }; } From 6e5846d20602f6324ae7d0195316050ec3bc6bb2 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 1 Jan 2014 10:52:28 -0600 Subject: [PATCH 0092/1608] Replace `isWhitespaceAt` with `trimmedLeftIndex` and `trimmedRightIndex`. --- dist/lodash.compat.js | 71 +++++++++++++++--------- dist/lodash.compat.min.js | 114 +++++++++++++++++++------------------- dist/lodash.js | 71 +++++++++++++++--------- dist/lodash.min.js | 103 +++++++++++++++++----------------- lodash.js | 73 ++++++++++++++---------- test/test.js | 2 +- 6 files changed, 243 insertions(+), 191 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 89c1aac197..48f70a68eb 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -441,23 +441,6 @@ return typeof value.toString != 'function' && typeof (value + '') == 'string'; } - /** - * Checks the given string to determine if the character at the specified - * index is whitespace. - * - * @private - * @param {string} string The string to inspect. - * @param {number} index The character index. - * @returns {boolean} Returns `true` if specifed character is whitespace, else `false`. - */ - function isWhitespaceAt(string, index) { - var c = string.charCodeAt(index); - return ( - (c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || - (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)) - ); - } - /** * Releases the given array back to the array pool. * @@ -516,6 +499,46 @@ return result; } + /** + * Gets the index of the first non-whitespace character of a given string. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the first non-whitespace character. + */ + function trimmedLeftIndex(string) { + var index = -1, + length = string.length; + + while (++index < length) { + var c = string.charCodeAt(index); + if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { + break; + } + } + return index; + } + + /** + * Gets the index of the last non-whitespace character of a given string. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedRightIndex(string) { + var index = string.length; + while (index--) { + var c = string.charCodeAt(index); + if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { + break; + } + } + return index; + } + /*--------------------------------------------------------------------------*/ /** @@ -1925,16 +1948,10 @@ // fallback for environments without a proper `String#trim` if (!nativeTrim || nativeTrim.call(whitespace)) { trim = function(string) { - var start = -1, - end = string ? string.length : 0; - - if (!end || string == null) { - return ''; - } - string = String(string); - while (++start < end && isWhitespaceAt(string, start)) { } - while (end-- && isWhitespaceAt(string, end)) { } - return string.slice(start, end + 1); + string = string == null ? '' : String(string); + return string + ? string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1) + : string; }; } diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 93f1479d19..6f8d99f926 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -3,60 +3,60 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(n=r&&9<=r&&13>=r||32==r||160==r||5760==r||6158==r||8192<=r&&(8202>=r||8232==r||8233==r||8239==r||8287==r||12288==r||65279==r)}function g(n){n.length=0,d.lengthr?0:r);++e=j&&o===t,l=[];if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&h(e),l}function ct(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:at(t,r,3),typeof o=="number")for(Zr.unindexedChars&&Dt(u)&&(u=u.split(""));++e=j&&a===t,s=u||p?l():c;for(p&&(s=i(s),a=r);++oa(s,y))&&((u||p)&&s.push(y),c.push(v))}return p?(g(s.g),h(s)):u&&g(s),c}function yt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),te(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(at,U,wr,Pr,kt,jr,et,Yr,Q,xr,Or) -}function bt(n){return tt[n]}function _t(){var n=(n=e.indexOf)===Jt?t:n;return n}function wt(n){return typeof n=="function"&&Er.test(Nr.call(n))}function jt(n){var t,r;return!n||Or.call(n)!=H||(t=n.constructor,Tt(t)&&!(t instanceof t))||!Zr.argsClass&&kt(n)||!Zr.nodeClass&&p(n)?false:Zr.ownLast?(ue(n,function(n,t,e){return r=Pr.call(e,t),false}),false!==r):(ue(n,function(n,t){r=t}),typeof r=="undefined"||Pr.call(n,r))}function xt(n){return null==n?"":Jr.call(n)}function Ct(n){return rt[n]}function kt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Or.call(n)==z||false -}function Ot(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!te(n)&&Dt(n))return Lr?Lr.call(n,t,r):-1r?Ur(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Dt(n)?u:e.createCallback(t,r,3),ct(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Vt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),te(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),zt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Xt(n){var t=-1,r=n?n.length:0,e=cr(typeof r=="number"?r:0);return Wt(n,function(n){var r=ht(0,++t);e[t]=e[r],e[r]=n}),e}function Gt(n,t,r){var u;if(t=e.createCallback(t,r,3),te(n)){r=-1;for(var o=n.length;++re?Ur(0,u+e):e||0}else if(e)return e=Yt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Qt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y;m?(u&&(u=Ar(u)),c=a,o=n.apply(i,e)):u||(u=qr(v,y))}return m&&f?f=Ar(f):f||t===p||(f=qr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function ur(n){return n}function or(n){n||(n={});var t=ee(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Pt(e)?function(r){for(var e=t.length,u=false;e--&&(u=st(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function ar(n,t,r){var u=true,o=t&&It(t);t&&(r||o.length)||(null==r&&(r=t),a=d,t=n,n=e,o=It(t)),false===r?u=false:Pt(r)&&"chain"in r&&(u=r.chain); -var a=n,i=Tt(a);Wt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Rr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Pt(o))return this;o=new a(o),o.__chain__=t}return o})})}function ir(){}function fr(n){return function(t){return t[n]}}function lr(){return this.__wrapped__}n=n?lt.defaults(ot.Object(),n,lt.pick(ot,L)):ot;var cr=n.Array,pr=n.Boolean,sr=n.Date,gr=n.Function,hr=n.Math,vr=n.Number,yr=n.Object,mr=n.RegExp,dr=n.String,br=n.TypeError,_r=cr.prototype,wr=n.Error.prototype,jr=yr.prototype,xr=dr.prototype,Cr=(Cr=n.window)&&Cr.document,kr=n._,Or=jr.toString,Er=mr("^"+dr(Or).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Sr=hr.ceil,Ar=n.clearTimeout,Ir=hr.floor,Nr=gr.prototype.toString,Tr=wt(Tr=yr.getPrototypeOf)&&Tr,Pr=jr.hasOwnProperty,Rr=_r.push,Dr=jr.propertyIsEnumerable,qr=n.setTimeout,Fr=_r.splice,$r=_r.unshift,Br=function(){try{var n={},t=wt(t=yr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),Lr=wt(Lr=xr.contains)&&Lr,Wr=wt(Wr=yr.create)&&Wr,zr=wt(zr=cr.isArray)&&zr,Kr=n.isFinite,Mr=n.isNaN,Vr=wt(Vr=yr.keys)&&Vr,Ur=hr.max,Xr=hr.min,Gr=n.parseInt,Hr=hr.random,Jr=wt(Jr=xr.trim)&&Jr,Qr={};Qr[K]=cr,Qr[M]=pr,Qr[V]=sr,Qr[X]=gr,Qr[H]=yr,Qr[G]=vr,Qr[J]=mr,Qr[Q]=dr;var Yr={};Yr[K]=Yr[V]=Yr[G]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Yr[M]=Yr[Q]={constructor:true,toString:true,valueOf:true},Yr[U]=Yr[X]=Yr[J]={constructor:true,toString:true},Yr[H]={constructor:true},function(){for(var n=W.length;n--;){var t,r=W[n]; -for(t in Yr)Pr.call(Yr,t)&&!Pr.call(Yr[t],r)&&(Yr[t][r]=false)}}(),d.prototype=e.prototype;var Zr=e.support={};!function(){var t=function(){this.x=1},r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Zr.argsClass=Or.call(arguments)==z,Zr.argsObject=arguments.constructor==yr&&!(arguments instanceof cr),Zr.enumErrorProps=Dr.call(wr,"message")||Dr.call(wr,"name"),Zr.enumPrototypes=Dr.call(t,"prototype"),Zr.funcDecomp=!wt(n.WinRTError)&&$.test(y),Zr.funcNames=typeof gr.name=="string",Zr.nonEnumArgs=0!=u,Zr.nonEnumShadows=!/valueOf/.test(e),Zr.ownLast="x"!=e[0],Zr.spliceObjects=(Fr.call(r,0,1),!r[0]),Zr.unindexedChars="xx"!="x"[0]+yr("x")[0]; -try{Zr.dom=11===Cr.createDocumentFragment().nodeType}catch(o){Zr.dom=false}try{Zr.nodeClass=!(Or.call(undefined)==H&&!({toString:0}+""))}catch(a){Zr.nodeClass=true}}(1),e.templateSettings={escape:I,evaluate:N,interpolate:T,variable:"",imports:{_:e}},Wr||(ut=function(){function t(){}return function(r){if(Pt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var ne=Br?function(n,t){nt.value=t,Br(n,"__bindData__",nt)}:ir;(!Jr||Jr.call(C))&&(xt=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=dr(n);++t--n?t.apply(this,arguments):void 0}},e.assign=Ot,e.at=function(n){var t=arguments,r=-1,e=pt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=cr(t);for(Zr.unindexedChars&&Dt(n)&&(n=n.split(""));++r=j&&i(e?n[e]:c)))}var f=n[0],s=-1,v=f?f.length:0,y=[];n:for(;++s(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p) -}}for(;u--;)(m=o[u])&&h(m);return g(o),g(c),y},e.invert=function(n,t){for(var r=-1,e=ee(n),u=e.length,o={};++rr?Ur(0,e+r):Xr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=ar,e.noConflict=function(){return n._=kr,this},e.noop=ir,e.now=ce,e.parseInt=pe,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Hr(),Xr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):ht(n,t) -},e.reduce=Vt,e.reduceRight=Ut,e.result=function(n,t){if(n){var r=n[t];return Tt(r)?n[t]():r}},e.runInContext=y,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ee(n).length},e.some=Gt,e.sortedIndex=Yt,e.template=function(n,t,r){var u=e.templateSettings;n=dr(n||""),r=Et({},r,u);var o,a=Et({},r.imports,u.imports),u=ee(a),a=qt(a),i=0,l=r.interpolate||F,c="__p+='",l=mr((r.escape||F).source+"|"+l.source+"|"+(l===T?P:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace(B,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t -}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(k,""):c).replace(O,"$1").replace(E,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=gr(u,"return "+c).apply(m,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=dr(n),0>n.indexOf(";")?n:n.replace(S,Ct))},e.uniqueId=function(n){var t=++_; -return dr(null==n?"":n)+t},e.all=$t,e.any=Gt,e.detect=Lt,e.findWhere=Lt,e.foldl=Vt,e.foldr=Ut,e.include=Ft,e.inject=Vt,ar(function(){var n={};return St(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Ht,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:m;return v(n,Ur(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=qt(n):Zr.unindexedChars&&Dt(n)&&(n=n.split("")),null==t||r?n?n[ht(0,n.length-1)]:m:(n=Xt(n),n.length=Xr(Ur(0,t),n.length),n) -},e.take=Ht,e.head=Ht,St(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new d(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return dr(this.__wrapped__)},e.prototype.value=lr,e.prototype.valueOf=lr,ct(["join","pop","shift"],function(n){var t=_r[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new d(r,n):r}}),ct(["push","reverse","sort","unshift"],function(n){var t=_r[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ct(["concat","slice","splice"],function(n){var t=_r[n];e.prototype[n]=function(){return new d(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Zr.spliceObjects||ct(["pop","shift","splice"],function(n){var t=_r[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new d(u,n):u -}}),e}var m,d=[],b=[],_=0,w=+new Date+"",j=75,x=40,C=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,O=/\b(__p\+=)''\+/g,E=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39);/g,A=/[&<>"']/g,I=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,T=/<%=([\s\S]+?)%>/g,P=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,R=/\w*$/,D=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,F=/($^)/,$=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,L="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),z="[object Arguments]",K="[object Array]",M="[object Boolean]",V="[object Date]",U="[object Error]",X="[object Function]",G="[object Number]",H="[object Object]",J="[object RegExp]",Q="[object String]",Y={}; -Y[X]=false,Y[z]=Y[K]=Y[M]=Y[V]=Y[G]=Y[H]=Y[J]=Y[Q]=true;var Z={leading:false,maxWait:0,trailing:false},nt={configurable:false,enumerable:false,value:null,writable:false},tt={"&":"&","<":"<",">":">",'"':""","'":"'"},rt={"&":"&","<":"<",">":">",""":'"',"'":"'"},et={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},ut={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ot=et[typeof window]&&window||this,at=et[typeof exports]&&exports&&!exports.nodeType&&exports,it=et[typeof global]&&global; -!it||it.global!==it&&it.window!==it||(ot=it);var ft=(it=et[typeof module]&&module&&!module.nodeType&&module)&&it.exports===at&&at,lt=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ot._=lt, define(function(){return lt})):at&&it?ft?(it.exports=lt)._=lt:at._=lt:ot._=lt}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=w&&o===t,l=[]; +if(f){var c=i(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&g(e),l}function lt(n,t,r){var e=-1,u=n,o=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ot(t,r,3),typeof o=="number")for(Yr.unindexedChars&&Rt(u)&&(u=u.split(""));++e=w&&a===t,h=u||p?l():c;for(p&&(h=i(h),a=r);++oa(h,y))&&((u||p)&&h.push(y),c.push(v))}return p?(s(h.g),g(h)):u&&s(h),c}function vt(n){return function(t,r,u){var o={};if(r=e.createCallback(r,u,3),ne(t)){u=-1;for(var a=t.length;++uu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&h.call(p,l))",n.f||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("a,f,g,h,j,q,r,o,v,w,y",r+(e+"return s;")+"}")(ot,V,_r,Tr,Ct,wr,rt,Qr,J,jr,kr) +}function dt(n){return nt[n]}function bt(){var n=(n=e.indexOf)===Ht?t:n;return n}function _t(n){return typeof n=="function"&&Or.test(Ir.call(n))}function wt(n){var t,r;return!n||kr.call(n)!=G||(t=n.constructor,Nt(t)&&!(t instanceof t))||!Yr.argsClass&&Ct(n)||!Yr.nodeClass&&p(n)?false:Yr.ownLast?(ee(n,function(n,t,e){return r=Tr.call(e,t),false}),false!==r):(ee(n,function(n,t){r=t}),typeof r=="undefined"||Tr.call(n,r))}function jt(n){return null==n?"":Hr.call(n)}function xt(n){return tt[n]}function Ct(n){return n&&typeof n=="object"&&typeof n.length=="number"&&kr.call(n)==W||false +}function kt(n,t,r){var e=arguments,u=0,o=typeof r=="number"?2:e.length;if(3=e)return false;if(typeof n=="string"||!ne(n)&&Rt(n))return Br?Br.call(n,t,r):-1r?Vr(0,e+r):r)||0,-1a&&(a=f)}}else t=null==t&&Rt(n)?u:e.createCallback(t,r,3),lt(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Mt(n,t,r,u){var o=3>arguments.length;if(t=e.createCallback(t,u,4),ne(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=e.createCallback(t,u,4),Wt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Ut(n){var t=-1,r=n?n.length:0,e=lr(typeof r=="number"?r:0);return Lt(n,function(n){var r=gt(0,++t);e[t]=e[r],e[r]=n}),e}function Xt(n,t,r){var u;if(t=e.createCallback(t,r,3),ne(n)){r=-1;for(var o=n.length;++re?Vr(0,u+e):e||0}else if(e)return e=Qt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y; +m?(a&&(a=Sr(a)),s=f,i=n.apply(l,o)):a||(a=Dr(e,y))}return m&&c?c=Sr(c):c||t===g||(c=Dr(u,t)),r&&(m=true,i=n.apply(l,o)),!m||c||a||(o=l=null),i}}function er(n){return n}function ur(n){n||(n={});var t=re(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Tt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function or(n,t,r){var u=true,o=t&&At(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=At(t)),false===r?u=false:Tt(r)&&"chain"in r&&(u=r.chain); +var a=n,i=Nt(a);Lt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Pr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Tt(o))return this;o=new a(o),o.__chain__=t}return o})})}function ar(){}function ir(n){return function(t){return t[n]}}function fr(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var lr=n.Array,cr=n.Boolean,pr=n.Date,sr=n.Function,gr=n.Math,hr=n.Number,vr=n.Object,yr=n.RegExp,mr=n.String,dr=n.TypeError,br=lr.prototype,_r=n.Error.prototype,wr=vr.prototype,jr=mr.prototype,xr=(xr=n.window)&&xr.document,Cr=n._,kr=wr.toString,Or=yr("^"+mr(kr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Er=gr.ceil,Sr=n.clearTimeout,Ar=gr.floor,Ir=sr.prototype.toString,Nr=_t(Nr=vr.getPrototypeOf)&&Nr,Tr=wr.hasOwnProperty,Pr=br.push,Rr=wr.propertyIsEnumerable,Dr=n.setTimeout,qr=br.splice,Fr=br.unshift,$r=function(){try{var n={},t=_t(t=vr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Br=_t(Br=jr.contains)&&Br,Lr=_t(Lr=vr.create)&&Lr,Wr=_t(Wr=lr.isArray)&&Wr,zr=n.isFinite,Kr=n.isNaN,Mr=_t(Mr=vr.keys)&&Mr,Vr=gr.max,Ur=gr.min,Xr=n.parseInt,Gr=gr.random,Hr=_t(Hr=jr.trim)&&Hr,Jr={};Jr[z]=lr,Jr[K]=cr,Jr[M]=pr,Jr[U]=sr,Jr[G]=vr,Jr[X]=hr,Jr[H]=yr,Jr[J]=mr;var Qr={};Qr[z]=Qr[M]=Qr[X]={constructor:true,toLocaleString:true,toString:true,valueOf:true},Qr[K]=Qr[J]={constructor:true,toString:true,valueOf:true},Qr[V]=Qr[U]=Qr[H]={constructor:true,toString:true},Qr[G]={constructor:true},function(){for(var n=L.length;n--;){var t,r=L[n]; +for(t in Qr)Tr.call(Qr,t)&&!Tr.call(Qr[t],r)&&(Qr[t][r]=false)}}(),m.prototype=e.prototype;var Yr=e.support={};!function(){function t(){this.x=1}var r={0:1,length:1},e=[];t.prototype={valueOf:1,y:1};for(var u in new t)e.push(u);for(u in arguments);Yr.argsClass=kr.call(arguments)==W,Yr.argsObject=arguments.constructor==vr&&!(arguments instanceof lr),Yr.enumErrorProps=Rr.call(_r,"message")||Rr.call(_r,"name"),Yr.enumPrototypes=Rr.call(t,"prototype"),Yr.funcDecomp=!_t(n.WinRTError)&&F.test(v),Yr.funcNames=typeof sr.name=="string",Yr.nonEnumArgs=0!=u,Yr.nonEnumShadows=!/valueOf/.test(e),Yr.ownLast="x"!=e[0],Yr.spliceObjects=(qr.call(r,0,1),!r[0]),Yr.unindexedChars="xx"!="x"[0]+vr("x")[0]; +try{Yr.dom=11===xr.createDocumentFragment().nodeType}catch(o){Yr.dom=false}try{Yr.nodeClass=!(kr.call(undefined)==G&&!({toString:0}+""))}catch(a){Yr.nodeClass=true}}(1),e.templateSettings={escape:A,evaluate:I,interpolate:N,variable:"",imports:{_:e}},Lr||(et=function(){function t(){}return function(r){if(Tt(r)){t.prototype=r;var e=new t;t.prototype=null}return e||n.Object()}}());var Zr=$r?function(n,t){Z.value=t,$r(n,"__bindData__",Z)}:ar;(!Hr||Hr.call(x))&&(jt=function(n){if(n=null==n?"":mr(n)){for(var t=n.length;t--;){var r=n.charCodeAt(t);if((160r||13r||8202u||13u||8202--n?t.apply(this,arguments):void 0}},e.assign=kt,e.at=function(n){var t=arguments,r=-1,e=ct(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=lr(t);for(Yr.unindexedChars&&Rt(n)&&(n=n.split(""));++r=w&&i(e?n[e]:c)))}var f=n[0],h=-1,v=f?f.length:0,y=[];n:for(;++h(m?r(m,p):a(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):a(n[e],p)))continue n;y.push(p) +}}for(;u--;)(m=o[u])&&g(m);return s(o),s(c),y},e.invert=function(n,t){for(var r=-1,e=re(n),u=e.length,o={};++rr?Vr(0,e+r):Ur(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=or,e.noConflict=function(){return n._=Cr,this},e.noop=ar,e.now=le,e.parseInt=ce,e.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Gr(),Ur(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):gt(n,t) +},e.reduce=Mt,e.reduceRight=Vt,e.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},e.runInContext=v,e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:re(n).length},e.some=Xt,e.sortedIndex=Qt,e.template=function(n,t,r){var u=e.templateSettings;n=mr(n||""),r=Ot({},r,u);var o,a=Ot({},r.imports,u.imports),u=re(a),a=Dt(a),i=0,l=r.interpolate||q,c="__p+='",l=yr((r.escape||q).source+"|"+l.source+"|"+(l===N?T:q).source+"|"+(r.evaluate||q).source+"|$","g");n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace($,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t +}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(C,""):c).replace(k,"$1").replace(O,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=sr(u,"return "+c).apply(y,a)}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},e.unescape=function(n){return null==n?"":(n=mr(n),0>n.indexOf(";")?n:n.replace(E,xt))},e.uniqueId=function(n){var t=++b; +return mr(null==n?"":n)+t},e.all=Ft,e.any=Xt,e.detect=Bt,e.findWhere=Bt,e.foldl=Mt,e.foldr=Vt,e.include=qt,e.inject=Mt,or(function(){var n={};return Et(e,function(t,r){e.prototype[r]||(n[r]=t)}),n}(),false),e.first=Gt,e.last=function(n,t,r){var u=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o;for(t=e.createCallback(t,r,3);a--&&t(n[a],a,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:y;return h(n,Vr(0,o-u))},e.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Dt(n):Yr.unindexedChars&&Rt(n)&&(n=n.split("")),null==t||r?n?n[gt(0,n.length-1)]:y:(n=Ut(n),n.length=Ur(Vr(0,t),n.length),n) +},e.take=Gt,e.head=Gt,Et(e,function(n,t){var r="sample"!==t;e.prototype[t]||(e.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new m(o,u):o})}),e.VERSION="2.4.1",e.prototype.chain=function(){return this.__chain__=true,this},e.prototype.toString=function(){return mr(this.__wrapped__)},e.prototype.value=fr,e.prototype.valueOf=fr,lt(["join","pop","shift"],function(n){var t=br[n];e.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new m(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=br[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),lt(["concat","slice","splice"],function(n){var t=br[n];e.prototype[n]=function(){return new m(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Yr.spliceObjects||lt(["pop","shift","splice"],function(n){var t=br[n],r="splice"==n;e.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new m(u,n):u +}}),e}var y,m=[],d=[],b=0,_=+new Date+"",w=75,j=40,x=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",C=/\b__p\+='';/g,k=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/&(?:amp|lt|gt|quot|#39);/g,S=/[&<>"']/g,A=/<%-([\s\S]+?)%>/g,I=/<%([\s\S]+?)%>/g,N=/<%=([\s\S]+?)%>/g,T=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,q=/($^)/,F=/\bthis\b/,$=/['\n\r\t\u2028\u2029\\]/g,B="Array Boolean Date Error Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),L="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),W="[object Arguments]",z="[object Array]",K="[object Boolean]",M="[object Date]",V="[object Error]",U="[object Function]",X="[object Number]",G="[object Object]",H="[object RegExp]",J="[object String]",Q={}; +Q[U]=false,Q[W]=Q[z]=Q[K]=Q[M]=Q[X]=Q[G]=Q[H]=Q[J]=true;var Y={leading:false,maxWait:0,trailing:false},Z={configurable:false,enumerable:false,value:null,writable:false},nt={"&":"&","<":"<",">":">",'"':""","'":"'"},tt={"&":"&","<":"<",">":">",""":'"',"'":"'"},rt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},et={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ut=rt[typeof window]&&window||this,ot=rt[typeof exports]&&exports&&!exports.nodeType&&exports,at=rt[typeof global]&&global; +!at||at.global!==at&&at.window!==at||(ut=at);var it=(at=rt[typeof module]&&module&&!module.nodeType&&module)&&at.exports===ot&&ot,ft=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ut._=ft, define(function(){return ft})):ot&&at?it?(at.exports=ft)._=ft:ot._=ft:ut._=ft}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index d558c68448..c569b14164 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -418,23 +418,6 @@ }; } - /** - * Checks the given string to determine if the character at the specified - * index is whitespace. - * - * @private - * @param {string} string The string to inspect. - * @param {number} index The character index. - * @returns {boolean} Returns `true` if specifed character is whitespace, else `false`. - */ - function isWhitespaceAt(string, index) { - var c = string.charCodeAt(index); - return ( - (c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || - (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)) - ); - } - /** * Releases the given array back to the array pool. * @@ -493,6 +476,46 @@ return result; } + /** + * Gets the index of the first non-whitespace character of a given string. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the first non-whitespace character. + */ + function trimmedLeftIndex(string) { + var index = -1, + length = string.length; + + while (++index < length) { + var c = string.charCodeAt(index); + if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { + break; + } + } + return index; + } + + /** + * Gets the index of the last non-whitespace character of a given string. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedRightIndex(string) { + var index = string.length; + while (index--) { + var c = string.charCodeAt(index); + if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { + break; + } + } + return index; + } + /*--------------------------------------------------------------------------*/ /** @@ -1624,16 +1647,10 @@ // fallback for environments without a proper `String#trim` if (!nativeTrim || nativeTrim.call(whitespace)) { trim = function(string) { - var start = -1, - end = string ? string.length : 0; - - if (!end || string == null) { - return ''; - } - string = String(string); - while (++start < end && isWhitespaceAt(string, start)) { } - while (end-- && isWhitespaceAt(string, end)) { } - return string.slice(start, end + 1); + string = string == null ? '' : String(string); + return string + ? string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1) + : string; }; } diff --git a/dist/lodash.min.js b/dist/lodash.min.js index fea0e8ad48..2ee2fddd4b 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,54 +3,55 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(n=r&&9<=r&&13>=r||32==r||160==r||5760==r||6158==r||8192<=r&&(8202>=r||8232==r||8233==r||8239==r||8287==r||12288==r||65279==r)}function s(n){n.length=0,m.lengthr?0:r);++e=w&&o===t,l=[];if(f){var c=a(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&v(e),l}function lt(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e=w&&i===t,h=u||p?l():c; -for(p&&(h=a(h),i=r);++oi(h,y))&&((u||p)&&h.push(y),c.push(g))}return p?(s(h.g),v(h)):u&&s(h),c}function ht(n){return function(t,r,e){var u={};r=b.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++e=e)return false;if(typeof n=="string"||!Jr(n)&&At(n))return Fr?Fr.call(n,t,r):-1r?Pr(0,e+r):r)||0,-1o&&(o=a)}}else t=null==t&&At(n)?u:b.createCallback(t,r,3),qt(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function Kt(n,t,r,e){var u=3>arguments.length;t=b.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=b.createCallback(t,e,4),Wt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ar(typeof r=="number"?r:0);return qt(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;t=b.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Pr(0,u+e):e||0}else if(e)return e=Ht(n,r),n[e]===r?e:-1;return t(n,r,e)}function Gt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=b.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=y; -m?(i&&(i=Cr(i)),s=f,a=n.apply(l,o)):i||(i=Tr(e,y))}return m&&c?c=Cr(c):c||t===v||(c=Tr(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function tr(n){return n}function rr(n){n||(n={});var t=Qr(n),r=t[0],e=n[r];return 1!=t.length||e!==e||St(e)?function(r){for(var e=t.length,u=false;e--&&(u=ct(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function er(n,t,r){var e=true,u=t&&Et(t);t&&(r||u.length)||(null==r&&(r=t),o=j,t=n,n=b,u=Et(t)),false===r?e=false:St(r)&&"chain"in r&&(e=r.chain); -var o=n,i=It(o);qt(u,function(r){var u=n[r]=t[r];i&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,i=[r];if(Sr.apply(i,arguments),i=u.apply(n,i),e||t){if(r===i&&St(i))return this;i=new o(i),i.__chain__=t}return i})})}function ur(){}function or(n){return function(t){return t[n]}}function ir(){return this.__wrapped__}n=n?it.defaults(rt.Object(),n,it.pick(rt,W)):rt;var ar=n.Array,fr=n.Boolean,lr=n.Date,cr=n.Function,pr=n.Math,sr=n.Number,vr=n.Object,hr=n.RegExp,gr=n.String,yr=n.TypeError,mr=ar.prototype,br=vr.prototype,dr=gr.prototype,_r=(_r=n.window)&&_r.document,wr=n._,jr=br.toString,kr=hr("^"+gr(jr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),xr=pr.ceil,Cr=n.clearTimeout,Or=pr.floor,Er=cr.prototype.toString,Nr=bt(Nr=vr.getPrototypeOf)&&Nr,Ir=br.hasOwnProperty,Sr=mr.push,Tr=n.setTimeout,Ar=mr.splice,Rr=mr.unshift,Dr=function(){try{var n={},t=bt(t=vr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),Fr=bt(Fr=dr.contains)&&Fr,$r=bt($r=vr.create)&&$r,Br=bt(Br=ar.isArray)&&Br,qr=n.isFinite,Wr=n.isNaN,zr=bt(zr=vr.keys)&&zr,Pr=pr.max,Kr=pr.min,Lr=n.parseInt,Mr=pr.random,Vr=bt(Vr=dr.trim)&&Vr,Ur={};Ur[P]=ar,Ur[K]=fr,Ur[L]=lr,Ur[M]=cr,Ur[U]=vr,Ur[V]=sr,Ur[X]=hr,Ur[G]=gr,j.prototype=b.prototype;var Xr=b.support={};Xr.funcDecomp=!bt(n.WinRTError)&&B.test(g),Xr.funcNames=typeof cr.name=="string";try{Xr.dom=11===_r.createDocumentFragment().nodeType}catch(Gr){Xr.dom=false}b.templateSettings={escape:I,evaluate:S,interpolate:T,variable:"",imports:{_:b}},$r||(ut=function(){function t(){}return function(r){if(St(r)){t.prototype=r; -var e=new t;t.prototype=null}return e||n.Object()}}());var Hr=Dr?function(n,t){Q.value=t,Dr(n,"__bindData__",Q)}:ur;(!Vr||Vr.call(k))&&(_t=function(n){var t=-1,r=n?n.length:0;if(!r||null==n)return"";for(n=gr(n);++t--n?t.apply(this,arguments):void 0}},b.assign=kt,b.at=function(n){for(var t=arguments,r=-1,e=lt(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ar(t);++r=w&&a(e?n[e]:c)))}var f=n[0],h=-1,g=f?f.length:0,y=[];n:for(;++h(m?r(m,p):i(c,p))){for(e=u,(m||c).push(p);--e;)if(m=o[e],0>(m?r(m,p):i(n[e],p)))continue n;y.push(p)}}for(;u--;)(m=o[u])&&v(m);return s(o),s(c),y},b.invert=function(n,t){for(var r=-1,e=Qr(n),u=e.length,o={};++rr?Pr(0,e+r):Kr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},b.mixin=er,b.noConflict=function(){return n._=wr,this},b.noop=ur,b.now=ee,b.parseInt=ue,b.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Mr(),Kr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):st(n,t) -},b.reduce=Kt,b.reduceRight=Lt,b.result=function(n,t){if(n){var r=n[t];return It(r)?n[t]():r}},b.runInContext=g,b.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Qr(n).length},b.some=Vt,b.sortedIndex=Ht,b.template=function(n,t,r){var e=b.templateSettings;n=gr(n||""),r=xt({},r,e);var u,o=xt({},r.imports,e.imports),e=Qr(o),o=Rt(o),i=0,a=r.interpolate||$,l="__p+='",a=hr((r.escape||$).source+"|"+a.source+"|"+(a===T?A:$).source+"|"+(r.evaluate||$).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(q,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t -}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(x,""):l).replace(C,"$1").replace(O,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=cr(e,"return "+l).apply(y,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},b.unescape=function(n){return null==n?"":(n=gr(n),0>n.indexOf(";")?n:n.replace(E,wt))},b.uniqueId=function(n){var t=++d; -return gr(null==n?"":n)+t},b.all=Ft,b.any=Vt,b.detect=Bt,b.findWhere=Bt,b.foldl=Kt,b.foldr=Lt,b.include=Dt,b.inject=Kt,er(function(){var n={};return Ct(b,function(t,r){b.prototype[r]||(n[r]=t)}),n}(),false),b.first=Ut,b.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=b.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:y;return h(n,Pr(0,u-e))},b.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Rt(n)),null==t||r?n?n[st(0,n.length-1)]:y:(n=Mt(n),n.length=Kr(Pr(0,t),n.length),n) -},b.take=Ut,b.head=Ut,Ct(b,function(n,t){var r="sample"!==t;b.prototype[t]||(b.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new j(o,u):o})}),b.VERSION="2.4.1",b.prototype.chain=function(){return this.__chain__=true,this},b.prototype.toString=function(){return gr(this.__wrapped__)},b.prototype.value=ir,b.prototype.valueOf=ir,qt(["join","pop","shift"],function(n){var t=mr[n];b.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); -return n?new j(r,n):r}}),qt(["push","reverse","sort","unshift"],function(n){var t=mr[n];b.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),qt(["concat","slice","splice"],function(n){var t=mr[n];b.prototype[n]=function(){return new j(t.apply(this.__wrapped__,arguments),this.__chain__)}}),b}var y,m=[],b=[],d=0,_=+new Date+"",w=75,j=40,k=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",x=/\b__p\+='';/g,C=/\b(__p\+=)''\+/g,O=/(__e\(.*?\)|\b__t\))\+'';/g,E=/&(?:amp|lt|gt|quot|#39);/g,N=/[&<>"']/g,I=/<%-([\s\S]+?)%>/g,S=/<%([\s\S]+?)%>/g,T=/<%=([\s\S]+?)%>/g,A=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,R=/\w*$/,D=/^\s*function[ \n\r\t]+\w/,F=/^0[xX]/,$=/($^)/,B=/\bthis\b/,q=/['\n\r\t\u2028\u2029\\]/g,W="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),z="[object Arguments]",P="[object Array]",K="[object Boolean]",L="[object Date]",M="[object Function]",V="[object Number]",U="[object Object]",X="[object RegExp]",G="[object String]",H={}; -H[M]=false,H[z]=H[P]=H[K]=H[L]=H[V]=H[U]=H[X]=H[G]=true;var J={leading:false,maxWait:0,trailing:false},Q={configurable:false,enumerable:false,value:null,writable:false},Y={"&":"&","<":"<",">":">",'"':""","'":"'"},Z={"&":"&","<":"<",">":">",""":'"',"'":"'"},nt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},tt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},rt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof global]&&global; -!ut||ut.global!==ut&&ut.window!==ut||(rt=ut);var ot=(ut=nt[typeof module]&&module&&!module.nodeType&&module)&&ut.exports===et&&et,it=g();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(rt._=it, define(function(){return it})):et&&ut?ot?(ut.exports=it)._=it:et._=it:rt._=it}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr?0:r);++e=_&&o===t,l=[]; +if(f){var c=a(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&s(e),l}function ft(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e=_&&i===t,h=u||v?l():c;for(v&&(h=a(h),i=r);++oi(h,y))&&((u||v)&&h.push(y),c.push(g)) +}return v?(p(h.g),s(h)):u&&p(h),c}function vt(n){return function(t,r,e){var u={};r=m.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++e=e)return false;if(typeof n=="string"||!Hr(n)&&St(n))return Dr?Dr.call(n,t,r):-1r?zr(0,e+r):r)||0,-1o&&(o=a)}}else t=null==t&&St(n)?u:m.createCallback(t,r,3),Bt(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function Pt(n,t,r,e){var u=3>arguments.length;t=m.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=m.createCallback(t,e,4),qt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) +}),r}function Lt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Bt(n,function(n){var r=pt(0,++t);e[t]=e[r],e[r]=n}),e}function Mt(n,t,r){var e;t=m.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?zr(0,u+e):e||0}else if(e)return e=Gt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=g;m?(i&&(i=xr(i)),s=f,a=n.apply(l,o)):i||(i=Ir(e,g))}return m&&c?c=xr(c):c||t===v||(c=Ir(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function nr(n){return n}function tr(n){n||(n={});var t=Jr(n),r=t[0],e=n[r]; +return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=lt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function rr(n,t,r){var e=true,u=t&&Ot(t);t&&(r||u.length)||(null==r&&(r=t),o=w,t=n,n=m,u=Ot(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain);var o=n,i=Nt(o);Bt(u,function(r){var u=n[r]=t[r];i&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,i=[r];if(Ar.apply(i,arguments),i=u.apply(n,i),e||t){if(r===i&&At(i))return this; +i=new o(i),i.__chain__=t}return i})})}function er(){}function ur(n){return function(t){return t[n]}}function or(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var ir=n.Array,ar=n.Boolean,fr=n.Date,lr=n.Function,cr=n.Math,pr=n.Number,sr=n.Object,vr=n.RegExp,hr=n.String,gr=n.TypeError,yr=ir.prototype,mr=sr.prototype,br=hr.prototype,dr=(dr=n.window)&&dr.document,_r=n._,wr=mr.toString,jr=vr("^"+hr(wr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),kr=cr.ceil,xr=n.clearTimeout,Cr=cr.floor,Or=lr.prototype.toString,Er=mt(Er=sr.getPrototypeOf)&&Er,Nr=mr.hasOwnProperty,Ar=yr.push,Ir=n.setTimeout,Sr=yr.splice,Tr=yr.unshift,Rr=function(){try{var n={},t=mt(t=sr.defineProperty)&&t,r=t(n,n,n)&&t +}catch(e){}return r}(),Dr=mt(Dr=br.contains)&&Dr,Fr=mt(Fr=sr.create)&&Fr,$r=mt($r=ir.isArray)&&$r,Br=n.isFinite,qr=n.isNaN,Wr=mt(Wr=sr.keys)&&Wr,zr=cr.max,Pr=cr.min,Kr=n.parseInt,Lr=cr.random,Mr=mt(Mr=br.trim)&&Mr,Vr={};Vr[z]=ir,Vr[P]=ar,Vr[K]=fr,Vr[L]=lr,Vr[V]=sr,Vr[M]=pr,Vr[U]=vr,Vr[X]=hr,w.prototype=m.prototype;var Ur=m.support={};Ur.funcDecomp=!mt(n.WinRTError)&&$.test(h),Ur.funcNames=typeof lr.name=="string";try{Ur.dom=11===dr.createDocumentFragment().nodeType}catch(Xr){Ur.dom=false}m.templateSettings={escape:N,evaluate:A,interpolate:I,variable:"",imports:{_:m}},Fr||(et=function(){function t(){}return function(r){if(At(r)){t.prototype=r; +var e=new t;t.prototype=null}return e||n.Object()}}());var Gr=Rr?function(n,t){J.value=t,Rr(n,"__bindData__",J)}:er;(!Mr||Mr.call(j))&&(dt=function(n){if(n=null==n?"":hr(n)){for(var t=n.length;t--;){var r=n.charCodeAt(t);if((160r||13r||8202u||13u||8202--n?t.apply(this,arguments):void 0}},m.assign=jt,m.at=function(n){for(var t=arguments,r=-1,e=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ir(t);++r=_&&a(e?n[e]:c)))}var f=n[0],h=-1,g=f?f.length:0,y=[];n:for(;++h(m?r(m,v):i(c,v))){for(e=u,(m||c).push(v);--e;)if(m=o[e],0>(m?r(m,v):i(n[e],v)))continue n;y.push(v) +}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var r=-1,e=Jr(n),u=e.length,o={};++rr?zr(0,e+r):Pr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},m.mixin=rr,m.noConflict=function(){return n._=_r,this},m.noop=er,m.now=re,m.parseInt=ee,m.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Lr(),Pr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):pt(n,t) +},m.reduce=Pt,m.reduceRight=Kt,m.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},m.runInContext=h,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Jr(n).length},m.some=Mt,m.sortedIndex=Gt,m.template=function(n,t,r){var e=m.templateSettings;n=hr(n||""),r=kt({},r,e);var u,o=kt({},r.imports,e.imports),e=Jr(o),o=Tt(o),i=0,a=r.interpolate||F,l="__p+='",a=vr((r.escape||F).source+"|"+a.source+"|"+(a===I?S:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(B,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t +}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=lr(e,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=hr(n),0>n.indexOf(";")?n:n.replace(O,_t))},m.uniqueId=function(n){var t=++b; +return hr(null==n?"":n)+t},m.all=Dt,m.any=Mt,m.detect=$t,m.findWhere=$t,m.foldl=Pt,m.foldr=Kt,m.include=Rt,m.inject=Pt,rr(function(){var n={};return xt(m,function(t,r){m.prototype[r]||(n[r]=t)}),n}(),false),m.first=Vt,m.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:g;return v(n,zr(0,u-e))},m.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Tt(n)),null==t||r?n?n[pt(0,n.length-1)]:g:(n=Lt(n),n.length=Pr(zr(0,t),n.length),n) +},m.take=Vt,m.head=Vt,xt(m,function(n,t){var r="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return hr(this.__wrapped__)},m.prototype.value=or,m.prototype.valueOf=or,Bt(["join","pop","shift"],function(n){var t=yr[n];m.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +return n?new w(r,n):r}}),Bt(["push","reverse","sort","unshift"],function(n){var t=yr[n];m.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Bt(["concat","slice","splice"],function(n){var t=yr[n];m.prototype[n]=function(){return new w(t.apply(this.__wrapped__,arguments),this.__chain__)}}),m}var g,y=[],m=[],b=0,d=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,O=/&(?:amp|lt|gt|quot|#39);/g,E=/[&<>"']/g,N=/<%-([\s\S]+?)%>/g,A=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,S=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,T=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,F=/($^)/,$=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="[object Arguments]",z="[object Array]",P="[object Boolean]",K="[object Date]",L="[object Function]",M="[object Number]",V="[object Object]",U="[object RegExp]",X="[object String]",G={}; +G[L]=false,G[W]=G[z]=G[P]=G[K]=G[M]=G[V]=G[U]=G[X]=true;var H={leading:false,maxWait:0,trailing:false},J={configurable:false,enumerable:false,value:null,writable:false},Q={"&":"&","<":"<",">":">",'"':""","'":"'"},Y={"&":"&","<":"<",">":">",""":'"',"'":"'"},Z={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},nt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},tt=Z[typeof window]&&window||this,rt=Z[typeof exports]&&exports&&!exports.nodeType&&exports,et=Z[typeof global]&&global; +!et||et.global!==et&&et.window!==et||(tt=et);var ut=(et=Z[typeof module]&&module&&!module.nodeType&&module)&&et.exports===rt&&rt,ot=h();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):rt&&et?ut?(et.exports=ot)._=ot:rt._=ot:tt._=ot}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index 4bb99ee7de..dec066f753 100644 --- a/lodash.js +++ b/lodash.js @@ -39,7 +39,7 @@ '\n\r\u2028\u2029' + // unicode category "Zs" space separators - '\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to match empty string literals in compiled template source */ @@ -440,23 +440,6 @@ return typeof value.toString != 'function' && typeof (value + '') == 'string'; } - /** - * Checks the given string to determine if the character at the specified - * index is whitespace. - * - * @private - * @param {string} string The string to inspect. - * @param {number} index The character index. - * @returns {boolean} Returns `true` if specifed character is whitespace, else `false`. - */ - function isWhitespaceAt(string, index) { - var c = string.charCodeAt(index); - return ( - (c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || - (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)) - ); - } - /** * Releases the given array back to the array pool. * @@ -515,6 +498,46 @@ return result; } + /** + * Gets the index of the first non-whitespace character of a given string. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the first non-whitespace character. + */ + function trimmedLeftIndex(string) { + var index = -1, + length = string.length; + + while (++index < length) { + var c = string.charCodeAt(index); + if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { + break; + } + } + return index; + } + + /** + * Gets the index of the last non-whitespace character of a given string. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedRightIndex(string) { + var index = string.length; + while (index--) { + var c = string.charCodeAt(index); + if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || + (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { + break; + } + } + return index; + } + /*--------------------------------------------------------------------------*/ /** @@ -1942,16 +1965,10 @@ // fallback for environments without a proper `String#trim` if (!nativeTrim || nativeTrim.call(whitespace)) { trim = function(string) { - var start = -1, - end = string ? string.length : 0; - - if (!end || string == null) { - return ''; - } - string = String(string); - while (++start < end && isWhitespaceAt(string, start)) { } - while (end-- && isWhitespaceAt(string, end)) { } - return string.slice(start, end + 1); + string = string == null ? '' : String(string); + return string + ? string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1) + : string; }; } diff --git a/test/test.js b/test/test.js index 76f19f13a5..0736cf078d 100644 --- a/test/test.js +++ b/test/test.js @@ -5744,7 +5744,7 @@ QUnit.module('lodash.parseInt'); (function() { - var whitespace = ' \t\x0B\f\xA0\ufeff\n\r\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; + var whitespace = ' \t\x0B\f\xA0\ufeff\n\r\u2028\u2029\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; test('should accept a `radix` argument', function() { var expected = _.range(2, 37); From 3e4f9451a0da7a6106dcc10dbd2c5e74849155dd Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 1 Jan 2014 11:01:53 -0600 Subject: [PATCH 0093/1608] Update year to 2014. [ci skip] --- LICENSE.txt | 4 +- dist/lodash.compat.js | 2 +- dist/lodash.js | 2 +- dist/lodash.underscore.js | 2 +- lodash.js | 2 +- vendor/benchmark.js/LICENSE.txt | 2 +- vendor/benchmark.js/benchmark.js | 216 ++++++++++++++-------------- vendor/docdown/LICENSE.txt | 2 +- vendor/docdown/docdown.php | 2 +- vendor/platform.js/LICENSE.txt | 2 +- vendor/platform.js/platform.js | 2 +- vendor/qunit-extras/LICENSE.txt | 2 +- vendor/qunit-extras/qunit-extras.js | 2 +- 13 files changed, 125 insertions(+), 117 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 49869bbab3..e23f4fbb37 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,5 @@ -Copyright 2012-2013 The Dojo Foundation -Based on Underscore.js 1.5.2, copyright 2009-2013 Jeremy Ashkenas, +Copyright 2012-2014 The Dojo Foundation +Based on Underscore.js 1.5.2, copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Permission is hereby granted, free of charge, to any person obtaining diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 48f70a68eb..33b4dc879e 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -2,7 +2,7 @@ * @license * Lo-Dash 2.4.1 (Custom Build) * Build: `lodash -o ./dist/lodash.compat.js` - * Copyright 2012-2013 The Dojo Foundation + * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.5.2 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license diff --git a/dist/lodash.js b/dist/lodash.js index c569b14164..1469ce7842 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -2,7 +2,7 @@ * @license * Lo-Dash 2.4.1 (Custom Build) * Build: `lodash modern -o ./dist/lodash.js` - * Copyright 2012-2013 The Dojo Foundation + * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.5.2 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 54b07b7f4a..5792ceb973 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -2,7 +2,7 @@ * @license * Lo-Dash 2.4.1 (Custom Build) * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js` - * Copyright 2012-2013 The Dojo Foundation + * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.5.2 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license diff --git a/lodash.js b/lodash.js index dec066f753..4619132875 100644 --- a/lodash.js +++ b/lodash.js @@ -1,7 +1,7 @@ /** * @license * Lo-Dash 2.4.1 - * Copyright 2012-2013 The Dojo Foundation + * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.5.2 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license diff --git a/vendor/benchmark.js/LICENSE.txt b/vendor/benchmark.js/LICENSE.txt index ae29abad41..4a9583d675 100644 --- a/vendor/benchmark.js/LICENSE.txt +++ b/vendor/benchmark.js/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2010-2013 Mathias Bynens +Copyright 2010-2014 Mathias Bynens Based on JSLitmus.js, copyright Robert Kieffer Modified by John-David Dalton diff --git a/vendor/benchmark.js/benchmark.js b/vendor/benchmark.js/benchmark.js index d8023dac9d..21c9649938 100644 --- a/vendor/benchmark.js/benchmark.js +++ b/vendor/benchmark.js/benchmark.js @@ -1,6 +1,6 @@ /*! * Benchmark.js v1.0.0 - * Copyright 2010-2013 Mathias Bynens + * Copyright 2010-2014 Mathias Bynens * Based on JSLitmus.js, copyright Robert Kieffer * Modified by John-David Dalton * Available under MIT license @@ -55,7 +55,7 @@ var contextProps = [ 'Array', 'Date', 'Function', 'Math', 'Object', 'RegExp', 'String', '_', 'clearTimeout', 'chrome', 'chromium', 'document', 'java', 'navigator', - 'performance', 'platform', 'process', 'runtime', 'setTimeout' + 'performance', 'phantom', 'platform', 'process', 'runtime', 'setTimeout' ]; /** Used to avoid hz of Infinity */ @@ -162,7 +162,8 @@ shift = arrayRef.shift, slice = arrayRef.slice, sqrt = Math.sqrt, - toString = objectProto.toString; + toString = objectProto.toString, + unshift = arrayRef.unshift; /** Detect DOM document object */ var doc = isHostType(context, 'document') && context.document; @@ -202,14 +203,6 @@ (function() { - /** - * Detect Adobe AIR. - * - * @memberOf Benchmark.support - * @type boolean - */ - support.air = isClassOf(context.runtime, 'ScriptBridgingProxyObject'); - /** * Detect if in a browser environment. * @@ -234,6 +227,14 @@ */ support.timeout = isHostType(context, 'setTimeout') && isHostType(context, 'clearTimeout'); + /** + * Detect if `Array#unshift` returns the new length of the array (all but IE < 8). + * + * @memberOf _.support + * @type boolean + */ + support.unshiftResult = !![].unshift(1); + /** * Detect if functions support decompilation. * @@ -429,12 +430,12 @@ */ function Event(type) { var event = this; + if (type instanceof Event) { + return type; + } return (event == null || event.constructor != Event) ? new Event(type) - : (type instanceof Event - ? type - : _.extend(event, { 'timeStamp': +new Date }, typeof type == 'string' ? { 'type': type } : type) - ); + : _.assign(event, { 'timeStamp': +new Date }, typeof type == 'string' ? { 'type': type } : type); } /** @@ -482,7 +483,7 @@ return new Suite(name, options); } // juggle arguments - if (isClassOf(name, 'Object')) { + if (_.isPlainObject(name)) { // 1 argument (options) options = name; } else { @@ -601,7 +602,7 @@ result = (result || '').replace(/^\s+|\s+$/g, ''); // detect strings containing only the "use strict" directive - return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result) + return /^(?:\/\*+[\w\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result) ? '' : result; } @@ -644,7 +645,7 @@ * @returns {boolean} Returns `true` if the value can be coerced, else `false`. */ function isStringable(value) { - return _.has(value, 'toString') || isClassOf(value, 'String'); + return _.has(value, 'toString') || _.isString(value); } /** @@ -709,8 +710,9 @@ * @param {Object} [options={}] Options object. */ function setOptions(object, options) { - options = _.extend({}, object.constructor.options, options); - object.options = _.forOwn(options, function(value, key) { + options = object.options = _.assign({}, cloneDeep(object.constructor.options), cloneDeep(options)); + + _.forOwn(options, function(value, key) { if (value != null) { // add event listeners if (/^on[A-Z]/.test(key)) { @@ -960,7 +962,7 @@ args = slice.call(arguments, 2); } else { // 2 arguments (array, options) - options = _.extend(options, name); + options = _.assign(options, name); name = options.name; args = _.isArray(args = 'args' in options ? options.args : []) ? args : [args]; queued = options.queued; @@ -1107,7 +1109,7 @@ */ function cloneSuite(options) { var suite = this, - result = new suite.constructor(_.extend({}, suite.options, options)); + result = new suite.constructor(_.assign({}, suite.options, options)); // copy own properties _.forOwn(suite, function(value, key) { @@ -1130,7 +1132,7 @@ */ function filterSuite(callback) { var suite = this, - result = new suite.constructor; + result = new suite.constructor(suite.options); result.push.apply(result, filter(suite, callback)); return result; @@ -1386,11 +1388,10 @@ */ function clone(options) { var bench = this, - sample = bench.stats.sample, - result = new bench.constructor(_.extend({}, bench, options)); + result = new bench.constructor(_.assign({}, bench, options)); // correct the `options` object - result.options = _.extend({}, bench.options, options); + result.options = _.assign({}, cloneDeep(bench.options), cloneDeep(options)); // copy own custom properties _.forOwn(bench, function(value, key) { @@ -1463,70 +1464,72 @@ * @returns {Object} The benchmark instance. */ function reset() { - var data, - event, - bench = this, - index = 0, - changes = { 'length': 0 }, - queue = { 'length': 0 }; - + var bench = this; if (bench.running && !calledBy.abort) { // no worries, `reset()` is called within `abort()` calledBy.reset = true; bench.abort(); delete calledBy.reset; + return bench; } - else { - // a non-recursive solution to check if properties have changed - // http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4 - data = { 'destination': bench, 'source': _.extend({}, bench.constructor.prototype, bench.options) }; - do { - _.forOwn(data.source, function(value, key) { - var changed, - destination = data.destination, - currValue = destination[key]; - - // skip pseudo private properties like `_timerId` which could be a - // Java object in environments like RingoJS - if (key.charAt(0) == '_') { - return; - } - if (value && typeof value == 'object') { - if (_.isArray(value)) { - // check if an array value has changed to a non-array value - if (!_.isArray(currValue)) { - changed = currValue = []; - } - // or has changed its length - if (currValue.length != value.length) { - changed = currValue = currValue.slice(0, value.length); - currValue.length = value.length; - } - } - // check if an object has changed to a non-object value - else if (!currValue || typeof currValue != 'object') { - changed = currValue = {}; + var event, + index = 0, + changes = { 'length': 0 }, + queue = { 'length': 0 }; + + // a non-recursive solution to check if properties have changed + // http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4 + var data = { + 'destination': bench, + 'source': _.assign({}, cloneDeep(bench.constructor.prototype), cloneDeep(bench.options)) + }; + + do { + _.forOwn(data.source, function(value, key) { + var changed, + destination = data.destination, + currValue = destination[key]; + + // skip pseudo private properties like `_timerId` which could be a + // Java object in environments like RingoJS + if (key.charAt(0) == '_') { + return; + } + if (value && typeof value == 'object') { + if (_.isArray(value)) { + // check if an array value has changed to a non-array value + if (!_.isArray(currValue)) { + changed = currValue = []; } - // register a changed object - if (changed) { - changes[changes.length++] = { 'destination': destination, 'key': key, 'value': currValue }; + // or has changed its length + if (currValue.length != value.length) { + changed = currValue = currValue.slice(0, value.length); + currValue.length = value.length; } - queue[queue.length++] = { 'destination': currValue, 'source': value }; } - // register a changed primitive - else if (value !== currValue && !(value == null || _.isFunction(value))) { - changes[changes.length++] = { 'destination': destination, 'key': key, 'value': value }; + // check if an object has changed to a non-object value + else if (!currValue || typeof currValue != 'object') { + changed = currValue = {}; } - }); - } - while ((data = queue[index++])); + // register a changed object + if (changed) { + changes[changes.length++] = { 'destination': destination, 'key': key, 'value': currValue }; + } + queue[queue.length++] = { 'destination': currValue, 'source': value }; + } + // register a changed primitive + else if (value !== currValue && !(value == null || _.isFunction(value))) { + changes[changes.length++] = { 'destination': destination, 'key': key, 'value': value }; + } + }); + } + while ((data = queue[index++])); - // if changed emit the `reset` event and if it isn't cancelled reset the benchmark - if (changes.length && (bench.emit(event = Event('reset')), !event.cancelled)) { - _.each(changes, function(data) { - data.destination[data.key] = data.value; - }); - } + // if changed emit the `reset` event and if it isn't cancelled reset the benchmark + if (changes.length && (bench.emit(event = Event('reset')), !event.cancelled)) { + _.each(changes, function(data) { + data.destination[data.key] = data.value; + }); } return bench; } @@ -1633,7 +1636,7 @@ throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.'); } else if (!deferred) { - // pretest to determine if compiled code is exits early, usually by a + // pretest to determine if compiled code exits early, usually by a // rogue `return` statement, by checking for a return object with the uid bench.count = 1; compiled = (compiled.call(bench, context, timer) || {}).uid == templateData.uid && compiled; @@ -1689,7 +1692,7 @@ templateData.uid = uid + uidCounter++; - _.extend(templateData, { + _.assign(templateData, { 'setup': getSource(bench.setup, interpolate('m#.setup()')), 'fn': getSource(fn, interpolate('m#.fn(' + fnArg + ')')), 'fnArg': fnArg, @@ -1699,12 +1702,12 @@ // use API of chosen timer if (timer.unit == 'ns') { if (timer.ns.nanoTime) { - _.extend(templateData, { + _.assign(templateData, { 'begin': interpolate('s#=n#.nanoTime()'), 'end': interpolate('r#=(n#.nanoTime()-s#)/1e9') }); } else { - _.extend(templateData, { + _.assign(templateData, { 'begin': interpolate('s#=n#()'), 'end': interpolate('r#=n#(s#);r#=r#[0]+(r#[1]/1e9)') }); @@ -1712,24 +1715,24 @@ } else if (timer.unit == 'us') { if (timer.ns.stop) { - _.extend(templateData, { + _.assign(templateData, { 'begin': interpolate('s#=n#.start()'), 'end': interpolate('r#=n#.microseconds()/1e6') }); } else if (perfName) { - _.extend(templateData, { + _.assign(templateData, { 'begin': interpolate('s#=n#.' + perfName + '()'), 'end': interpolate('r#=(n#.' + perfName + '()-s#)/1e3') }); } else { - _.extend(templateData, { + _.assign(templateData, { 'begin': interpolate('s#=n#()'), 'end': interpolate('r#=(n#()-s#)/1e6') }); } } else { - _.extend(templateData, { + _.assign(templateData, { 'begin': interpolate('s#=new n#'), 'end': interpolate('r#=(new n#-s#)/1e3') }); @@ -1980,7 +1983,7 @@ // relative margin of error rme = (moe / mean) * 100 || 0; - _.extend(bench.stats, { + _.assign(bench.stats, { 'deviation': sd, 'mean': mean, 'moe': moe, @@ -2185,8 +2188,8 @@ // The bugginess continues as the `Benchmark` constructor has an argument // named `options` and Firefox 1 will not assign a value to `Benchmark.options`, // making it non-writable in the process, unless it is the first property - // assigned by for-in loop of `_.extend()`. - _.extend(Benchmark, { + // assigned by for-in loop of `_.assign()`. + _.assign(Benchmark, { /** * The default options copied by benchmark instances. @@ -2353,7 +2356,7 @@ 'version': '1.0.0' }); - _.extend(Benchmark, { + _.assign(Benchmark, { 'filter': filter, 'formatNumber': formatNumber, 'invoke': invoke, @@ -2369,7 +2372,7 @@ /*------------------------------------------------------------------------*/ - _.extend(Benchmark.prototype, { + _.assign(Benchmark.prototype, { /** * The number of times a test was executed. @@ -2613,7 +2616,7 @@ } }); - _.extend(Benchmark.prototype, { + _.assign(Benchmark.prototype, { 'abort': abort, 'clone': clone, 'compare': compare, @@ -2628,7 +2631,7 @@ /*------------------------------------------------------------------------*/ - _.extend(Deferred.prototype, { + _.assign(Deferred.prototype, { /** * The deferred benchmark instance. @@ -2663,13 +2666,13 @@ 'timeStamp': 0 }); - _.extend(Deferred.prototype, { + _.assign(Deferred.prototype, { 'resolve': resolve }); /*------------------------------------------------------------------------*/ - _.extend(Event.prototype, { + _.assign(Event.prototype, { /** * A flag to indicate if the emitters listener iteration is aborted. @@ -2750,7 +2753,7 @@ /*------------------------------------------------------------------------*/ - _.extend(Suite.prototype, { + _.assign(Suite.prototype, { /** * The number of benchmarks in the suite. @@ -2777,7 +2780,7 @@ 'running': false }); - _.extend(Suite.prototype, { + _.assign(Suite.prototype, { 'abort': abortSuite, 'add': add, 'clone': cloneSuite, @@ -2793,16 +2796,16 @@ 'run': runSuite, 'reverse': arrayRef.reverse, 'shift': shift, - 'slice': arrayRef.slice, + 'slice': slice, 'sort': arrayRef.sort, 'splice': arrayRef.splice, - 'unshift': arrayRef.unshift + 'unshift': unshift }); /*------------------------------------------------------------------------*/ // expose Deferred, Event, and Suite - _.extend(Benchmark, { + _.assign(Benchmark, { 'Deferred': Deferred, 'Event': Event, 'Suite': Suite @@ -2837,9 +2840,14 @@ }; }); } - // trigger clock's lazy define early to avoid a security error - if (support.air) { - clock({ '_original': { 'fn': noop, 'count': 1, 'options': {} } }); + // avoid buggy `Array#unshift` in IE < 8 which doesn't return the new + // length of the array + if (!support.unshiftResult) { + Suite.prototype.unshift = function() { + var value = this; + unshift.apply(value, arguments); + return value.length; + }; } return Benchmark; } diff --git a/vendor/docdown/LICENSE.txt b/vendor/docdown/LICENSE.txt index a7501f98de..6cc7b220b3 100644 --- a/vendor/docdown/LICENSE.txt +++ b/vendor/docdown/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2011-2013 John-David Dalton +Copyright 2011-2014 John-David Dalton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/vendor/docdown/docdown.php b/vendor/docdown/docdown.php index b25ea915b3..f031470d34 100644 --- a/vendor/docdown/docdown.php +++ b/vendor/docdown/docdown.php @@ -1,7 +1,7 @@ + * Copyright 2011-2014 John-David Dalton * Available under MIT license */ require(dirname(__FILE__) . '/src/DocDown/MarkdownGenerator.php'); diff --git a/vendor/platform.js/LICENSE.txt b/vendor/platform.js/LICENSE.txt index a7501f98de..6cc7b220b3 100644 --- a/vendor/platform.js/LICENSE.txt +++ b/vendor/platform.js/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2011-2013 John-David Dalton +Copyright 2011-2014 John-David Dalton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/vendor/platform.js/platform.js b/vendor/platform.js/platform.js index 94ec91825a..3f5d1d7534 100644 --- a/vendor/platform.js/platform.js +++ b/vendor/platform.js/platform.js @@ -1,6 +1,6 @@ /*! * Platform.js v1.0.0 - * Copyright 2010-2013 John-David Dalton + * Copyright 2010-2014 John-David Dalton * Available under MIT license */ ;(function(root) { diff --git a/vendor/qunit-extras/LICENSE.txt b/vendor/qunit-extras/LICENSE.txt index a7501f98de..6cc7b220b3 100644 --- a/vendor/qunit-extras/LICENSE.txt +++ b/vendor/qunit-extras/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2011-2013 John-David Dalton +Copyright 2011-2014 John-David Dalton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/vendor/qunit-extras/qunit-extras.js b/vendor/qunit-extras/qunit-extras.js index 074d45f4a5..cef6a658a8 100644 --- a/vendor/qunit-extras/qunit-extras.js +++ b/vendor/qunit-extras/qunit-extras.js @@ -1,6 +1,6 @@ /*! * QUnit Extras v1.0.0 - * Copyright 2011-2012 John-David Dalton + * Copyright 2011-2014 John-David Dalton * Based on a gist by Jörn Zaefferer * Available under MIT license */ From 7beb204b9d816d80531f801741dda30f84072f2d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 1 Jan 2014 23:10:27 -0600 Subject: [PATCH 0094/1608] Remove `forEach` dep from `mixin`. --- dist/lodash.compat.js | 48 +++++++++++++------------ dist/lodash.compat.min.js | 4 +-- dist/lodash.js | 48 +++++++++++++------------ dist/lodash.min.js | 62 ++++++++++++++++---------------- dist/lodash.underscore.js | 32 ++++++++++------- dist/lodash.underscore.min.js | 68 +++++++++++++++++------------------ lodash.js | 46 +++++++++++++----------- 7 files changed, 163 insertions(+), 145 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 33b4dc879e..a404f2353f 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -40,7 +40,7 @@ '\n\r\u2028\u2029' + // unicode category "Zs" space separators - '\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to match empty string literals in compiled template source */ @@ -6415,7 +6415,6 @@ if (options == null) { options = source; } - ctor = lodashWrapper; source = object; object = lodash; methodNames = functions(source); @@ -6425,30 +6424,35 @@ } else if (isObject(options) && 'chain' in options) { chain = options.chain; } - var ctor = object, - isFunc = isFunction(ctor); + var index = -1, + isFunc = isFunction(object), + length = methodNames ? methodNames.length : 0; + + while (++index < length) { + var methodName = methodNames[index], + func = object[methodName] = source[methodName]; - forEach(methodNames, function(methodName) { - var func = object[methodName] = source[methodName]; if (isFunc) { - ctor.prototype[methodName] = function() { - var chainAll = this.__chain__, - value = this.__wrapped__, - args = [value]; - - push.apply(args, arguments); - var result = func.apply(object, args); - if (chain || chainAll) { - if (value === result && isObject(result)) { - return this; + object.prototype[methodName] = (function(func) { + return function() { + var chainAll = this.__chain__, + value = this.__wrapped__, + args = [value]; + + push.apply(args, arguments); + var result = func.apply(object, args); + if (chain || chainAll) { + if (value === result && isObject(result)) { + return this; + } + result = new object(result); + result.__chain__ = chainAll; } - result = new ctor(result); - result.__chain__ = chainAll; - } - return result; - }; + return result; + }; + }(func)); } - }); + } } /** diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 6f8d99f926..df5adbdd42 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -28,8 +28,8 @@ else lt(n,function(n,r,e){a[++u]=t(n,r,e)});return a}function Kt(n,t,r){var o=-1 for(t=e.createCallback(t,r,3);++ae?Vr(0,u+e):e||0}else if(e)return e=Qt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,a=n?n.length:0;for(t=e.createCallback(t,r,3);++o>>1,r(n[u])r?0:r);++t=y; -m?(a&&(a=Sr(a)),s=f,i=n.apply(l,o)):a||(a=Dr(e,y))}return m&&c?c=Sr(c):c||t===g||(c=Dr(u,t)),r&&(m=true,i=n.apply(l,o)),!m||c||a||(o=l=null),i}}function er(n){return n}function ur(n){n||(n={});var t=re(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Tt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function or(n,t,r){var u=true,o=t&&At(t);t&&(r||o.length)||(null==r&&(r=t),a=m,t=n,n=e,o=At(t)),false===r?u=false:Tt(r)&&"chain"in r&&(u=r.chain); -var a=n,i=Nt(a);Lt(o,function(r){var e=n[r]=t[r];i&&(a.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,o=[r];if(Pr.apply(o,arguments),o=e.apply(n,o),u||t){if(r===o&&Tt(o))return this;o=new a(o),o.__chain__=t}return o})})}function ar(){}function ir(n){return function(t){return t[n]}}function fr(){return this.__wrapped__}n=n?ft.defaults(ut.Object(),n,ft.pick(ut,B)):ut;var lr=n.Array,cr=n.Boolean,pr=n.Date,sr=n.Function,gr=n.Math,hr=n.Number,vr=n.Object,yr=n.RegExp,mr=n.String,dr=n.TypeError,br=lr.prototype,_r=n.Error.prototype,wr=vr.prototype,jr=mr.prototype,xr=(xr=n.window)&&xr.document,Cr=n._,kr=wr.toString,Or=yr("^"+mr(kr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Er=gr.ceil,Sr=n.clearTimeout,Ar=gr.floor,Ir=sr.prototype.toString,Nr=_t(Nr=vr.getPrototypeOf)&&Nr,Tr=wr.hasOwnProperty,Pr=br.push,Rr=wr.propertyIsEnumerable,Dr=n.setTimeout,qr=br.splice,Fr=br.unshift,$r=function(){try{var n={},t=_t(t=vr.defineProperty)&&t,r=t(n,n,n)&&t +m?(a&&(a=Sr(a)),s=f,i=n.apply(l,o)):a||(a=Dr(e,y))}return m&&c?c=Sr(c):c||t===g||(c=Dr(u,t)),r&&(m=true,i=n.apply(l,o)),!m||c||a||(o=l=null),i}}function er(n){return n}function ur(n){n||(n={});var t=re(n),r=t[0],e=n[r];return 1!=t.length||e!==e||Tt(e)?function(r){for(var e=t.length,u=false;e--&&(u=pt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function or(n,t,r){var u=true,o=t&&At(t);t&&(r||o.length)||(null==r&&(r=t),t=n,n=e,o=At(t)),false===r?u=false:Tt(r)&&"chain"in r&&(u=r.chain),r=-1; +for(var a=Nt(n),i=o?o.length:0;++rr||13r||8202t||typeof n=="undefined")return 1;if(nr?0:r);++er?0:r);++e=_&&o===t,l=[]; +};case 4:return function(r,e,u,o){return n.call(t,r,e,u,o)}}return Yt(n,t)}function it(n){function t(){var n=f?i:this;if(u){var v=h(u);Ar.apply(v,arguments)}return(o||c)&&(v||(v=h(arguments)),o&&Ar.apply(v,o),c&&v.length=_&&o===t,l=[]; if(f){var c=a(e);c?(o=r,e=c):f=false}for(;++uo(e,c)&&l.push(c);return f&&s(e),l}function ft(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e=_&&i===t,h=u||v?l():c;for(v&&(h=a(h),i=r);++oi(h,y))&&((u||v)&&h.push(y),c.push(g)) -}return v?(p(h.g),s(h)):u&&p(h),c}function vt(n){return function(t,r,e){var u={};r=m.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++e=_&&i===t,v=u||h?l():c;for(h&&(v=a(v),i=r);++oi(v,y))&&((u||h)&&v.push(y),c.push(g)) +}return h?(p(v.g),s(v)):u&&p(v),c}function ht(n){return function(t,r,e){var u={};r=m.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++eo&&(o=a)}}else t=null==t&&St(n)?u:m.createCallback(t,r,3),Bt(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function Pt(n,t,r,e){var u=3>arguments.length;t=m.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=m.createCallback(t,e,4),qt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) -}),r}function Lt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Bt(n,function(n){var r=pt(0,++t);e[t]=e[r],e[r]=n}),e}function Mt(n,t,r){var e;t=m.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?zr(0,u+e):e||0}else if(e)return e=Gt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=g;m?(i&&(i=xr(i)),s=f,a=n.apply(l,o)):i||(i=Ir(e,g))}return m&&c?c=xr(c):c||t===v||(c=Ir(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function nr(n){return n}function tr(n){n||(n={});var t=Jr(n),r=t[0],e=n[r]; -return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=lt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function rr(n,t,r){var e=true,u=t&&Ot(t);t&&(r||u.length)||(null==r&&(r=t),o=w,t=n,n=m,u=Ot(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain);var o=n,i=Nt(o);Bt(u,function(r){var u=n[r]=t[r];i&&(o.prototype[r]=function(){var t=this.__chain__,r=this.__wrapped__,i=[r];if(Ar.apply(i,arguments),i=u.apply(n,i),e||t){if(r===i&&At(i))return this; -i=new o(i),i.__chain__=t}return i})})}function er(){}function ur(n){return function(t){return t[n]}}function or(){return this.__wrapped__}n=n?ot.defaults(tt.Object(),n,ot.pick(tt,q)):tt;var ir=n.Array,ar=n.Boolean,fr=n.Date,lr=n.Function,cr=n.Math,pr=n.Number,sr=n.Object,vr=n.RegExp,hr=n.String,gr=n.TypeError,yr=ir.prototype,mr=sr.prototype,br=hr.prototype,dr=(dr=n.window)&&dr.document,_r=n._,wr=mr.toString,jr=vr("^"+hr(wr).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),kr=cr.ceil,xr=n.clearTimeout,Cr=cr.floor,Or=lr.prototype.toString,Er=mt(Er=sr.getPrototypeOf)&&Er,Nr=mr.hasOwnProperty,Ar=yr.push,Ir=n.setTimeout,Sr=yr.splice,Tr=yr.unshift,Rr=function(){try{var n={},t=mt(t=sr.defineProperty)&&t,r=t(n,n,n)&&t -}catch(e){}return r}(),Dr=mt(Dr=br.contains)&&Dr,Fr=mt(Fr=sr.create)&&Fr,$r=mt($r=ir.isArray)&&$r,Br=n.isFinite,qr=n.isNaN,Wr=mt(Wr=sr.keys)&&Wr,zr=cr.max,Pr=cr.min,Kr=n.parseInt,Lr=cr.random,Mr=mt(Mr=br.trim)&&Mr,Vr={};Vr[z]=ir,Vr[P]=ar,Vr[K]=fr,Vr[L]=lr,Vr[V]=sr,Vr[M]=pr,Vr[U]=vr,Vr[X]=hr,w.prototype=m.prototype;var Ur=m.support={};Ur.funcDecomp=!mt(n.WinRTError)&&$.test(h),Ur.funcNames=typeof lr.name=="string";try{Ur.dom=11===dr.createDocumentFragment().nodeType}catch(Xr){Ur.dom=false}m.templateSettings={escape:N,evaluate:A,interpolate:I,variable:"",imports:{_:m}},Fr||(et=function(){function t(){}return function(r){if(At(r)){t.prototype=r; -var e=new t;t.prototype=null}return e||n.Object()}}());var Gr=Rr?function(n,t){J.value=t,Rr(n,"__bindData__",J)}:er;(!Mr||Mr.call(j))&&(dt=function(n){if(n=null==n?"":hr(n)){for(var t=n.length;t--;){var r=n.charCodeAt(t);if((160r||13r||8202u||13u||8202e?zr(0,u+e):e||0}else if(e)return e=Gt(n,r),n[e]===r?e:-1;return t(n,r,e)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=m.createCallback(t,r,3);++u>>1,r(n[e])r?0:r);++t=g;m?(i&&(i=xr(i)),s=f,a=n.apply(l,o)):i||(i=Ir(e,g))}return m&&c?c=xr(c):c||t===h||(c=Ir(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function nr(n){return n}function tr(n){n||(n={});var t=Jr(n),r=t[0],e=n[r]; +return 1!=t.length||e!==e||At(e)?function(r){for(var e=t.length,u=false;e--&&(u=lt(r[t[e]],n[t[e]],null,true)););return u}:function(n){return n=n[r],e===n&&(0!==e||1/e==1/n)}}function rr(n,t,r){var e=true,u=t&&Ot(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=m,u=Ot(t)),false===r?e=false:At(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=Nt(n),i=u?u.length:0;++rr||13r||8202u||13u||8202--n?t.apply(this,arguments):void 0}},m.assign=jt,m.at=function(n){for(var t=arguments,r=-1,e=ft(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:e.length,u=ir(t);++r=_&&a(e?n[e]:c)))}var f=n[0],h=-1,g=f?f.length:0,y=[];n:for(;++h(m?r(m,v):i(c,v))){for(e=u,(m||c).push(v);--e;)if(m=o[e],0>(m?r(m,v):i(n[e],v)))continue n;y.push(v) -}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var r=-1,e=Jr(n),u=e.length,o={};++r=_&&a(e?n[e]:c)))}var f=n[0],v=-1,g=f?f.length:0,y=[];n:for(;++v(m?r(m,h):i(c,h))){for(e=u,(m||c).push(h);--e;)if(m=o[e],0>(m?r(m,h):i(n[e],h)))continue n;y.push(h) +}}for(;u--;)(m=o[u])&&s(m);return p(o),p(c),y},m.invert=function(n,t){for(var r=-1,e=Jr(n),u=e.length,o={};++rr?zr(0,e+r):Pr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},m.mixin=rr,m.noConflict=function(){return n._=_r,this},m.noop=er,m.now=re,m.parseInt=ee,m.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Lr(),Pr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):pt(n,t) -},m.reduce=Pt,m.reduceRight=Kt,m.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},m.runInContext=h,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Jr(n).length},m.some=Mt,m.sortedIndex=Gt,m.template=function(n,t,r){var e=m.templateSettings;n=hr(n||""),r=kt({},r,e);var u,o=kt({},r.imports,e.imports),e=Jr(o),o=Tt(o),i=0,a=r.interpolate||F,l="__p+='",a=vr((r.escape||F).source+"|"+a.source+"|"+(a===I?S:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(B,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t -}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=lr(e,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=hr(n),0>n.indexOf(";")?n:n.replace(O,_t))},m.uniqueId=function(n){var t=++b; -return hr(null==n?"":n)+t},m.all=Dt,m.any=Mt,m.detect=$t,m.findWhere=$t,m.foldl=Pt,m.foldr=Kt,m.include=Rt,m.inject=Pt,rr(function(){var n={};return xt(m,function(t,r){m.prototype[r]||(n[r]=t)}),n}(),false),m.first=Vt,m.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:g;return v(n,zr(0,u-e))},m.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Tt(n)),null==t||r?n?n[pt(0,n.length-1)]:g:(n=Lt(n),n.length=Pr(zr(0,t),n.length),n) -},m.take=Vt,m.head=Vt,xt(m,function(n,t){var r="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return hr(this.__wrapped__)},m.prototype.value=or,m.prototype.valueOf=or,Bt(["join","pop","shift"],function(n){var t=yr[n];m.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); +},m.reduce=Pt,m.reduceRight=Kt,m.result=function(n,t){if(n){var r=n[t];return Nt(r)?n[t]():r}},m.runInContext=v,m.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Jr(n).length},m.some=Mt,m.sortedIndex=Gt,m.template=function(n,t,r){var e=m.templateSettings;n=vr(n||""),r=kt({},r,e);var u,o=kt({},r.imports,e.imports),e=Jr(o),o=Tt(o),i=0,a=r.interpolate||F,l="__p+='",a=hr((r.escape||F).source+"|"+a.source+"|"+(a===I?S:F).source+"|"+(r.evaluate||F).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),l+=n.slice(i,c).replace(B,f),r&&(l+="'+__e("+r+")+'"),a&&(u=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t +}),l+="';",a=r=r.variable,a||(r="obj",l="with("+r+"){"+l+"}"),l=(u?l.replace(k,""):l).replace(x,"$1").replace(C,"$1;"),l="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=lr(e,"return "+l).apply(g,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},m.unescape=function(n){return null==n?"":(n=vr(n),0>n.indexOf(";")?n:n.replace(O,_t))},m.uniqueId=function(n){var t=++b; +return vr(null==n?"":n)+t},m.all=Dt,m.any=Mt,m.detect=$t,m.findWhere=$t,m.foldl=Pt,m.foldr=Kt,m.include=Rt,m.inject=Pt,rr(function(){var n={};return xt(m,function(t,r){m.prototype[r]||(n[r]=t)}),n}(),false),m.first=Vt,m.last=function(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=m.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:g;return h(n,zr(0,u-e))},m.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Tt(n)),null==t||r?n?n[pt(0,n.length-1)]:g:(n=Lt(n),n.length=Pr(zr(0,t),n.length),n) +},m.take=Vt,m.head=Vt,xt(m,function(n,t){var r="sample"!==t;m.prototype[t]||(m.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new w(o,u):o})}),m.VERSION="2.4.1",m.prototype.chain=function(){return this.__chain__=true,this},m.prototype.toString=function(){return vr(this.__wrapped__)},m.prototype.value=or,m.prototype.valueOf=or,Bt(["join","pop","shift"],function(n){var t=yr[n];m.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments); return n?new w(r,n):r}}),Bt(["push","reverse","sort","unshift"],function(n){var t=yr[n];m.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Bt(["concat","slice","splice"],function(n){var t=yr[n];m.prototype[n]=function(){return new w(t.apply(this.__wrapped__,arguments),this.__chain__)}}),m}var g,y=[],m=[],b=0,d=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",k=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,C=/(__e\(.*?\)|\b__t\))\+'';/g,O=/&(?:amp|lt|gt|quot|#39);/g,E=/[&<>"']/g,N=/<%-([\s\S]+?)%>/g,A=/<%([\s\S]+?)%>/g,I=/<%=([\s\S]+?)%>/g,S=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,T=/\w*$/,R=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,F=/($^)/,$=/\bthis\b/,B=/['\n\r\t\u2028\u2029\\]/g,q="Array Boolean Date Function Math Number Object RegExp String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),W="[object Arguments]",z="[object Array]",P="[object Boolean]",K="[object Date]",L="[object Function]",M="[object Number]",V="[object Object]",U="[object RegExp]",X="[object String]",G={}; G[L]=false,G[W]=G[z]=G[P]=G[K]=G[M]=G[V]=G[U]=G[X]=true;var H={leading:false,maxWait:0,trailing:false},J={configurable:false,enumerable:false,value:null,writable:false},Q={"&":"&","<":"<",">":">",'"':""","'":"'"},Y={"&":"&","<":"<",">":">",""":'"',"'":"'"},Z={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},nt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},tt=Z[typeof window]&&window||this,rt=Z[typeof exports]&&exports&&!exports.nodeType&&exports,et=Z[typeof global]&&global; -!et||et.global!==et&&et.window!==et||(tt=et);var ut=(et=Z[typeof module]&&module&&!module.nodeType&&module)&&et.exports===rt&&rt,ot=h();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):rt&&et?ut?(et.exports=ot)._=ot:rt._=ot:tt._=ot}).call(this); \ No newline at end of file +!et||et.global!==et&&et.window!==et||(tt=et);var ut=(et=Z[typeof module]&&module&&!module.nodeType&&module)&&et.exports===rt&&rt,ot=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=ot, define(function(){return ot})):rt&&et?ut?(et.exports=ot)._=ot:rt._=ot:tt._=ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 5792ceb973..bbe7183575 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -4361,20 +4361,26 @@ * _('fred').capitalize(); * // => 'Fred' */ - function mixin(object) { - forEach(functions(object), function(methodName) { - var func = lodash[methodName] = object[methodName]; - - lodash.prototype[methodName] = function() { - var args = [this.__wrapped__]; - push.apply(args, arguments); + function mixin(source) { + var index = -1, + methodNames = functions(source), + length = methodNames.length; - var result = func.apply(lodash, args); - return this.__chain__ - ? new lodashWrapper(result, true) - : result; - }; - }); + while (++index < length) { + var methodName = methodNames[index]; + lodash.prototype[methodName] = (function() { + var func = lodash[methodName] = source[methodName]; + return function() { + var args = [this.__wrapped__]; + push.apply(args, arguments); + + var result = func.apply(lodash, args); + return this.__chain__ + ? new lodashWrapper(result, true) + : result; + }; + }()); + } } /** diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index 6ee3f6c14f..3f26e5a94f 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -3,37 +3,37 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js` */ -;(function(){function n(n,t,r){r=(r||0)-1;for(var e=n?n.length:0;++re||typeof r=="undefined"){r=1;break n}if(rr?0:r);++ee(t,i)&&o.push(i)}return o}function p(n,t,r,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(r&&f.push(l),i.push(a))}return i}function h(n){return function(t,r,e){var u={};r=X(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++eu&&(u=r); -else t=X(t,r,3),$(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function W(n,t,r,e){var u=3>arguments.length;t=X(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=X(t,e,4),D(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function C(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r;r=++t,r=0+Bt(Ht()*(r-0+1)),e[t]=e[r],e[r]=n -}),e}function P(n,t,r){var e;t=X(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++re?Vt(0,u+e):e||0}else if(e)return e=J(t,r),t[e]===r?e:-1; -return n(t,r,e)}function H(n,t,r){if(typeof t!="number"&&null!=t){var u=0,o=-1,i=n?n.length:0;for(t=X(t,r,3);++o>>1,r(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||t===p||(a=setTimeout(h,t)),r&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,t,r){var e=typeof n;return null==n||"function"==e?a(n,t,r):"object"!=e?tt(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var t=Qt(n);return function(r){for(var e=t.length,u=false;e--&&(u=r[t[e]]===n[t[e]]););return u}}function nt(n){$(T(n),function(t){var r=u[t]=n[t]; -u.prototype[t]=function(){var n=[this.__wrapped__];return Dt.apply(n,arguments),n=r.apply(u,n),this.__chain__?new o(n,true):n}})}function tt(n){return function(t){return t[n]}}var rt,et=0,ut={},ot=+new Date+"",it=/&(?:amp|lt|gt|quot|#x27);/g,ft=/[&<>"']/g,at=/($^)/,lt=/['\n\r\t\u2028\u2029\\]/g,ct="[object Arguments]",pt="[object Array]",st="[object Boolean]",gt="[object Date]",ht="[object Number]",vt="[object Object]",yt="[object RegExp]",mt="[object String]",_t={"&":"&","<":"<",">":">",'"':""","'":"'"},dt={"&":"&","<":"<",">":">",""":'"',"'":"'"},bt={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},wt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},jt=bt[typeof window]&&window||this,xt=bt[typeof exports]&&exports&&!exports.nodeType&&exports,Tt=bt[typeof global]&&global; -!Tt||Tt.global!==Tt&&Tt.window!==Tt||(jt=Tt);var At=bt[typeof module]&&module&&!module.nodeType&&module,Et=At&&At.exports===xt&&xt,Ot=Array.prototype,St=Object.prototype,kt=jt._,Nt=St.toString,qt=RegExp("^"+(Nt+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ft=Math.ceil,Bt=Math.floor,Rt=Function.prototype.toString,$t=St.hasOwnProperty,Dt=Ot.push,It=St.propertyIsEnumerable,Mt=Ot.splice,Wt=_(Wt=Object.create)&&Wt,zt=_(zt=Array.isArray)&&zt,Ct=jt.isFinite,Pt=jt.isNaN,Ut=_(Ut=Object.keys)&&Ut,Vt=Math.max,Gt=Math.min,Ht=Math.random; -o.prototype=u.prototype;var Jt={};!function(){var n={0:1,length:1};Jt.spliceObjects=(Mt.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Wt||(f=function(){function n(){}return function(t){if(O(t)){n.prototype=t;var r=new n;n.prototype=null}return r||jt.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$t.call(n,"callee")&&!It.call(n,"callee")||false});var Kt=zt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nt.call(n)==pt||false -},Lt=function(n){var t=[];if(!n||!bt[typeof n])return t;for(var r in n)$t.call(n,r)&&t.push(r);return t},Qt=Ut?function(n){return O(n)?Ut(n):[]}:Lt,Xt=function(n,t){if(!n||!bt[typeof n])return n;for(var r in n)if(t(n[r],r,n)===ut)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nt.call(n)});var Yt=h(function(n,t,r){$t.call(n,r)?n[r]++:n[r]=1}),Zt=h(function(n,t,r){($t.call(n,r)?n[r]:n[r]=[]).push(t)}),nr=h(function(n,t,r){n[r]=t}),tr=I,rr=_(rr=Date.now)&&rr||function(){return(new Date).getTime() -};u.after=function(n,t){if(!E(t))throw new TypeError;return function(){return 1>--n?t.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var t=1i(a,e)){for(t=r;--t;)if(0>i(n[t],e))continue n;a.push(e)}return a},u.invert=function(n,t){for(var r=-1,e=Qt(n),u=e.length,o={};++rt?0:t);++nr?Vt(0,e+r):Gt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=nt,u.noConflict=function(){return jt._=kt,this},u.random=function(n,t){return null==n&&null==t&&(t=1),n=+n||0,null==t?(t=n,n=0):t=+t||0,n+Bt(Ht()*(t-n+1)) -},u.reduce=W,u.reduceRight=z,u.result=function(n,t){if(n){var r=n[t];return E(r)?n[t]():r}},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Qt(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,t,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||at).source+"|"+(e.interpolate||at).source+"|"+(e.evaluate||at).source+"|$","g"),function(t,e,u,o,i){return a+=n.slice(f,i).replace(lt,r),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+t.length,t -}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return t?l(t):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(it,d))},u.uniqueId=function(n){var t=++et+"";return n?n+t:t},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,t){return U(n,t,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,t,r){var u=0,o=n?n.length:0; -if(typeof t!="number"&&null!=t){var i=o;for(t=X(t,r,3);i--&&t(n[i],i,n);)u++}else if(u=t,null==u||r)return n?n[o-1]:rt;return e(n,Vt(0,o-u))},u.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=N(n)),null==t||r?n?n[0+Bt(Ht()*(n.length-1-0+1))]:rt:(n=C(n),n.length=Gt(Vt(0,t),n.length),n)},u.take=V,u.head=V,nt(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Ot[n]; -u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Jt.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var t=Ot[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jt._=u, define(function(){return u})):xt&&At?Et?(At.exports=u)._=u:xt._=u:jt._=u}).call(this); \ No newline at end of file +;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(tt?0:t);++ee(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++eu(f,l))&&(t&&f.push(l),i.push(a))}return i}function v(n){return function(r,t,e){var u={};t=X(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++eu&&(u=t); +else r=X(r,t,3),$(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function W(n,r,t,e){var u=3>arguments.length;r=X(r,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(t=n[++o]);++oarguments.length;return r=X(r,e,4),D(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return $(n,function(n){var t;t=++r,t=0+Br(Hr()*(t-0+1)),e[r]=e[t],e[t]=n +}),e}function P(n,r,t){var e;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++te?Vr(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1; +return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o>>1,t(n[e])=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(h,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(v,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;return null==n||"function"==e?a(n,r,t):"object"!=e?rr(n):Z(n)}function Y(n){return n}function Z(n){n||(n={});var r=Qr(n);return function(t){for(var e=r.length,u=false;e--&&(u=t[r[e]]===n[r[e]]););return u}}function nr(n){for(var r=-1,t=T(n),e=t.length;++r"']/g,ar=/($^)/,lr=/['\n\r\t\u2028\u2029\\]/g,cr="[object Arguments]",pr="[object Array]",sr="[object Boolean]",gr="[object Date]",vr="[object Number]",hr="[object Object]",yr="[object RegExp]",mr="[object String]",_r={"&":"&","<":"<",">":">",'"':""","'":"'"},dr={"&":"&","<":"<",">":">",""":'"',"'":"'"},br={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},wr={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},jr=br[typeof window]&&window||this,xr=br[typeof exports]&&exports&&!exports.nodeType&&exports,Tr=br[typeof global]&&global; +!Tr||Tr.global!==Tr&&Tr.window!==Tr||(jr=Tr);var Ar=br[typeof module]&&module&&!module.nodeType&&module,Er=Ar&&Ar.exports===xr&&xr,Or=Array.prototype,Sr=Object.prototype,kr=jr._,Nr=Sr.toString,qr=RegExp("^"+(Nr+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Fr=Math.ceil,Br=Math.floor,Rr=Function.prototype.toString,$r=Sr.hasOwnProperty,Dr=Or.push,Ir=Sr.propertyIsEnumerable,Mr=Or.splice,Wr=_(Wr=Object.create)&&Wr,zr=_(zr=Array.isArray)&&zr,Cr=jr.isFinite,Pr=jr.isNaN,Ur=_(Ur=Object.keys)&&Ur,Vr=Math.max,Gr=Math.min,Hr=Math.random; +o.prototype=u.prototype;var Jr={};!function(){var n={0:1,length:1};Jr.spliceObjects=(Mr.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Wr||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||jr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&$r.call(n,"callee")&&!Ir.call(n,"callee")||false});var Kr=zr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n)==pr||false +},Lr=function(n){var r=[];if(!n||!br[typeof n])return r;for(var t in n)$r.call(n,t)&&r.push(t);return r},Qr=Ur?function(n){return O(n)?Ur(n):[]}:Lr,Xr=function(n,r){if(!n||!br[typeof n])return n;for(var t in n)if(r(n[t],t,n)===ur)break;return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Nr.call(n)});var Yr=v(function(n,r,t){$r.call(n,t)?n[t]++:n[t]=1}),Zr=v(function(n,r,t){($r.call(n,t)?n[t]:n[t]=[]).push(r)}),nt=v(function(n,r,t){n[t]=r}),rt=I,tt=_(tt=Date.now)&&tt||function(){return(new Date).getTime() +};u.after=function(n,r){if(!E(r))throw new TypeError;return function(){return 1>--n?r.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var r=1i(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},u.invert=function(n,r){for(var t=-1,e=Qr(n),u=e.length,o={};++tr?0:r);++nt?Vr(0,e+t):Gr(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=nr,u.noConflict=function(){return jr._=kr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Br(Hr()*(r-n+1)) +},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return E(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Qr(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||ar).source+"|"+(e.interpolate||ar).source+"|"+(e.evaluate||ar).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(lr,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r +}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+="",0>n.indexOf(";")?n:n.replace(ir,d))},u.uniqueId=function(n){var r=++er+"";return n?n+r:r},u.all=F,u.any=P,u.detect=R,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=q,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0; +if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:tr;return e(n,Vr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=N(n)),null==r||t?n?n[0+Br(Hr()*(n.length-1-0+1))]:tr:(n=C(n),n.length=Gr(Vr(0,r),n.length),n)},u.take=V,u.head=V,nr(w({},u)),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},$("pop push reverse shift sort splice unshift".split(" "),function(n){var r=Or[n]; +u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Jr.spliceObjects||0!==n.length||delete n[0],this}}),$(["concat","join","slice"],function(n){var r=Or[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(jr._=u, define(function(){return u})):xr&&Ar?Er?(Ar.exports=u)._=u:xr._=u:jr._=u}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index 4619132875..e322461ef9 100644 --- a/lodash.js +++ b/lodash.js @@ -6432,7 +6432,6 @@ if (options == null) { options = source; } - ctor = lodashWrapper; source = object; object = lodash; methodNames = functions(source); @@ -6442,30 +6441,35 @@ } else if (isObject(options) && 'chain' in options) { chain = options.chain; } - var ctor = object, - isFunc = isFunction(ctor); + var index = -1, + isFunc = isFunction(object), + length = methodNames ? methodNames.length : 0; + + while (++index < length) { + var methodName = methodNames[index], + func = object[methodName] = source[methodName]; - forEach(methodNames, function(methodName) { - var func = object[methodName] = source[methodName]; if (isFunc) { - ctor.prototype[methodName] = function() { - var chainAll = this.__chain__, - value = this.__wrapped__, - args = [value]; - - push.apply(args, arguments); - var result = func.apply(object, args); - if (chain || chainAll) { - if (value === result && isObject(result)) { - return this; + object.prototype[methodName] = (function(func) { + return function() { + var chainAll = this.__chain__, + value = this.__wrapped__, + args = [value]; + + push.apply(args, arguments); + var result = func.apply(object, args); + if (chain || chainAll) { + if (value === result && isObject(result)) { + return this; + } + result = new object(result); + result.__chain__ = chainAll; } - result = new ctor(result); - result.__chain__ = chainAll; - } - return result; - }; + return result; + }; + }(func)); } - }); + } } /** From a20c362983d1d4d3629145a8c53c1767e27a3099 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 2 Jan 2014 18:37:23 -0600 Subject: [PATCH 0095/1608] Rearrange source to better match the doc order. --- dist/lodash.compat.js | 5914 +++++++++++++++++---------------- dist/lodash.compat.min.js | 113 +- dist/lodash.js | 5592 +++++++++++++++---------------- dist/lodash.min.js | 104 +- dist/lodash.underscore.js | 4068 +++++++++++------------ dist/lodash.underscore.min.js | 68 +- lodash.js | 5874 ++++++++++++++++---------------- 7 files changed, 10874 insertions(+), 10859 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index a404f2353f..d98f37b17e 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -382,6 +382,17 @@ return result; } + /** + * Used by `escape` to convert characters to HTML entities. + * + * @private + * @param {string} match The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeHtmlChar(match) { + return htmlEscapes[match]; + } + /** * Used by `template` to escape characters for inclusion in compiled * string literals. @@ -539,6 +550,17 @@ return index; } + /** + * Used by `unescape` to convert HTML entities to characters. + * + * @private + * @param {string} match The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + function unescapeHtmlChar(match) { + return htmlUnescapes[match]; + } + /*--------------------------------------------------------------------------*/ /** @@ -1848,17 +1870,6 @@ ); } - /** - * Used by `escape` to convert characters to HTML entities. - * - * @private - * @param {string} match The matched character to escape. - * @returns {string} Returns the escaped character. - */ - function escapeHtmlChar(match) { - return htmlEscapes[match]; - } - /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this method returns the custom method, otherwise it returns @@ -1935,37 +1946,6 @@ return typeof result == 'undefined' || hasOwnProperty.call(value, result); } - /** - * Removes leading and trailing whitespace from a given string. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function trim(string) { - return string == null ? '' : nativeTrim.call(string); - } - // fallback for environments without a proper `String#trim` - if (!nativeTrim || nativeTrim.call(whitespace)) { - trim = function(string) { - string = string == null ? '' : String(string); - return string - ? string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1) - : string; - }; - } - - /** - * Used by `unescape` to convert HTML entities to characters. - * - * @private - * @param {string} match The matched character to unescape. - * @returns {string} Returns the unescaped character. - */ - function unescapeHtmlChar(match) { - return htmlUnescapes[match]; - } - /*--------------------------------------------------------------------------*/ /** @@ -1996,28 +1976,6 @@ }; } - /** - * Checks if `value` is an array. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. - * @example - * - * (function() { return _.isArray(arguments); })(); - * // => false - * - * _.isArray([1, 2, 3]); - * // => true - */ - var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; - }; - /** * A fallback implementation of `Object.keys` which produces an array of the * given object's own enumerable property names. @@ -2035,265 +1993,167 @@ 'useHas': true }); + /*--------------------------------------------------------------------------*/ + /** - * Creates an array composed of the own enumerable property names of an object. + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are all falsey. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. + * @category Arrays + * @param {Array} array The array to compact. + * @returns {Array} Returns a new array of filtered values. * @example * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; - } - if ((support.enumPrototypes && typeof object == 'function') || - (support.nonEnumArgs && object.length && isArguments(object))) { - return shimKeys(object); - } - return nativeKeys(object); - }; + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; - /*--------------------------------------------------------------------------*/ + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } /** - * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with two - * arguments; (objectValue, sourceValue). + * Creates an array excluding all values of the provided arrays using strict + * equality for comparisons, i.e. `===`. * * @static * @memberOf _ - * @alias extend - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize assigning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. + * @category Arrays + * @param {Array} array The array to process. + * @param {...Array} [values] The arrays of values to exclude. + * @returns {Array} Returns a new array of filtered values. * @example * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } - * - * var defaults = _.partialRight(_.assign, function(a, b) { - * return typeof a == 'undefined' ? b : a; - * }); - * - * var object = { 'name': 'barney' }; - * defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); + * // => [1, 3, 4] */ - function assign(object, source, guard) { - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - - if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { - var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2); - } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { - callback = args[--argsLength]; - } - while (++argsIndex < argsLength) { - source = args[argsIndex]; - if (isObject(source)) { - var index = -1, - props = keys(source), - length = props.length; - - while (++index < length) { - var key = props[index]; - object[key] = callback ? callback(object[key], source[key]) : source[key]; - } - } - } - return object; + function difference(array) { + return baseDifference(array, baseFlatten(arguments, true, true, 1)); } /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects will also - * be cloned, otherwise they will be assigned by reference. If a callback - * is provided it will be executed to produce the cloned values. If the - * callback returns `undefined` cloning will be handled by the method instead. - * The callback is bound to `thisArg` and invoked with one argument; (value). + * This method is like `_.find` except that it returns the index of the first + * element that passes the callback check, instead of the element itself. + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to clone. - * @param {boolean} [isDeep=false] Specify a deep clone. - * @param {Function} [callback] The function to customize cloning values. + * @category Arrays + * @param {Array} array The array to search. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the cloned value. + * @returns {number} Returns the index of the found element, else `-1`. * @example * * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * { 'name': 'barney', 'age': 36, 'blocked': false }, + * { 'name': 'fred', 'age': 40, 'blocked': true }, + * { 'name': 'pebbles', 'age': 1, 'blocked': false } * ]; * - * var shallow = _.clone(characters); - * shallow[0] === characters[0]; - * // => true - * - * var deep = _.clone(characters, true); - * deep[0] === characters[0]; - * // => false - * - * _.mixin({ - * 'clone': _.partialRight(_.clone, function(value) { - * return _.isElement(value) ? value.cloneNode(false) : undefined; - * }) + * _.findIndex(characters, function(chr) { + * return chr.age < 20; * }); + * // => 2 * - * var clone = _.clone(document.body); - * clone.childNodes.length; + * // using "_.where" callback shorthand + * _.findIndex(characters, { 'age': 36 }); * // => 0 + * + * // using "_.pluck" callback shorthand + * _.findIndex(characters, 'blocked'); + * // => 1 */ - function clone(value, isDeep, callback, thisArg) { - // allows working with "Collections" methods without using their `index` - // and `collection` arguments for `isDeep` and `callback` - if (typeof isDeep != 'boolean' && isDeep != null) { - thisArg = callback; - callback = isDeep; - isDeep = false; + function findIndex(array, callback, thisArg) { + var index = -1, + length = array ? array.length : 0; + + callback = lodash.createCallback(callback, thisArg, 3); + while (++index < length) { + if (callback(array[index], index, array)) { + return index; + } } - return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); + return -1; } /** - * Creates a deep clone of `value`. If a callback is provided it will be - * executed to produce the cloned values. If the callback returns `undefined` - * cloning will be handled by the method instead. The callback is bound to - * `thisArg` and invoked with one argument; (value). + * This method is like `_.findIndex` except that it iterates over elements + * of a `collection` from right to left. * - * Note: This method is loosely based on the structured clone algorithm. Functions - * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and - * objects created by constructors other than `Object` are cloned to plain `Object` objects. - * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) - * for more details. + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the deep cloned value. + * @category Arrays + * @param {Array} array The array to search. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {number} Returns the index of the found element, else `-1`. * @example * * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * { 'name': 'barney', 'age': 36, 'blocked': true }, + * { 'name': 'fred', 'age': 40, 'blocked': false }, + * { 'name': 'pebbles', 'age': 1, 'blocked': true } * ]; * - * var deep = _.cloneDeep(characters); - * deep[0] === characters[0]; - * // => false - * - * var view = { - * 'label': 'docs', - * 'node': element - * }; - * - * var clone = _.cloneDeep(view, function(value) { - * return _.isElement(value) ? value.cloneNode(true) : undefined; + * _.findLastIndex(characters, function(chr) { + * return chr.age > 30; * }); + * // => 1 * - * clone.node == view.node; - * // => false - */ - function cloneDeep(value, callback, thisArg) { - return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); - } - - /** - * Creates an object that inherits from the given `prototype` object. If a - * `properties` object is provided its own enumerable properties are assigned - * to the created object. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} prototype The object to inherit from. - * @param {Object} [properties] The properties to assign to the object. - * @returns {Object} Returns the new object. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * function Circle() { - * Shape.call(this); - * } - * - * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); - * - * var circle = new Circle; - * circle instanceof Circle; - * // => true - * - * circle instanceof Shape; - * // => true - */ - function create(prototype, properties) { - var result = baseCreate(prototype); - return properties ? assign(result, properties) : result; - } - - /** - * Assigns own enumerable properties of source object(s) to the destination - * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param- {Object} [guard] Allows working with `_.reduce` without using its - * `key` and `object` arguments as sources. - * @returns {Object} Returns the destination object. - * @example + * // using "_.where" callback shorthand + * _.findLastIndex(characters, { 'age': 36 }); + * // => 0 * - * var object = { 'name': 'barney' }; - * _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * // using "_.pluck" callback shorthand + * _.findLastIndex(characters, 'blocked'); + * // => 2 */ - function defaults(object, source, guard) { - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - - while (++argsIndex < argsLength) { - source = args[argsIndex]; - if (isObject(source)) { - var index = -1, - props = keys(source), - length = props.length; - - while (++index < length) { - var key = props[index]; - if (typeof object[key] == 'undefined') { - object[key] = source[key]; - } - } + function findLastIndex(array, callback, thisArg) { + var length = array ? array.length : 0; + callback = lodash.createCallback(callback, thisArg, 3); + while (length--) { + if (callback(array[length], length, array)) { + return length; } } - return object; + return -1; } /** - * This method is like `_.findIndex` except that it returns the key of the - * first element that passes the callback check, instead of the element itself. + * Gets the first element or first `n` elements of an array. If a callback + * is provided elements at the beginning of the array are returned as long + * as the callback returns truey. The callback is bound to `thisArg` and + * invoked with three arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. @@ -2304,49 +2164,69 @@ * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. + * @alias head, take + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|number|string} [callback] The function called + * per element or the number of elements to return. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @returns {*} Returns the first element(s) of `array`. * @example * - * var characters = { - * 'barney': { 'age': 36, 'blocked': false }, - * 'fred': { 'age': 40, 'blocked': true }, - * 'pebbles': { 'age': 1, 'blocked': false } - * }; + * _.first([1, 2, 3]); + * // => 1 * - * _.findKey(characters, function(chr) { - * return chr.age < 40; + * // returns the first two elements + * _.first([1, 2, 3], 2); + * // => [1, 2] + * + * // returns elements from the beginning until the callback result is falsey + * _.first([1, 2, 3], function(num) { + * return num < 3; * }); - * // => 'barney' (property order is not guaranteed across environments) + * // => [1, 2] * - * // using "_.where" callback shorthand - * _.findKey(characters, { 'age': 1 }); - * // => 'pebbles' + * var characters = [ + * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, + * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, + * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } + * ]; * * // using "_.pluck" callback shorthand - * _.findKey(characters, 'blocked'); - * // => 'fred' + * _.first(characters, 'blocked'); + * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }] + * + * // using "_.where" callback shorthand + * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); + * // => ['barney', 'fred'] */ - function findKey(object, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forOwn(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; + function first(array, callback, thisArg) { + var n = 0, + length = array ? array.length : 0; + + if (typeof callback != 'number' && callback != null) { + var index = -1; + callback = lodash.createCallback(callback, thisArg, 3); + while (++index < length && callback(array[index], index, array)) { + n++; } - }); - return result; + } else { + n = callback; + if (n == null || thisArg) { + return array ? array[0] : undefined; + } + } + return slice(array, 0, nativeMin(nativeMax(0, n), length)); } /** - * This method is like `_.findKey` except that it iterates over elements - * of a `collection` in the opposite order. + * Flattens a nested array (the nesting can be to any depth). If `isShallow` + * is truey, the array will only be flattened a single level. If a callback + * is provided each element of the array is passed through the callback before + * flattening. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. @@ -2357,1063 +2237,972 @@ * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. + * @category Arrays + * @param {Array} array The array to flatten. + * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @returns {Array} Returns a new flattened array. * @example * - * var characters = { - * 'barney': { 'age': 36, 'blocked': true }, - * 'fred': { 'age': 40, 'blocked': false }, - * 'pebbles': { 'age': 1, 'blocked': true } - * }; + * _.flatten([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, 4]; * - * _.findLastKey(characters, function(chr) { - * return chr.age < 40; - * }); - * // => returns `pebbles`, assuming `_.findKey` returns `barney` + * // using `isShallow` + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, [[4]]]; * - * // using "_.where" callback shorthand - * _.findLastKey(characters, { 'age': 40 }); - * // => 'fred' + * var characters = [ + * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, + * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } + * ]; * * // using "_.pluck" callback shorthand - * _.findLastKey(characters, 'blocked'); - * // => 'pebbles' + * _.flatten(characters, 'pets'); + * // => ['hoppy', 'baby puss', 'dino'] */ - function findLastKey(object, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forOwnRight(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; - } - }); - return result; - } - - /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. + function flatten(array, isShallow, callback, thisArg) { + // juggle arguments + if (typeof isShallow != 'boolean' && isShallow != null) { + thisArg = callback; + callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow; + isShallow = false; + } + if (callback != null) { + array = map(array, callback, thisArg); + } + return baseFlatten(array, isShallow); + } + + /** + * Gets the index at which the first occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. If the array is already sorted + * providing `true` for `fromIndex` will run a faster binary search. * * @static * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Arrays + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {boolean|number} [fromIndex=0] The index to search from or `true` + * to perform a binary search on a sorted array. + * @returns {number} Returns the index of the matched value or `-1`. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * _.indexOf([1, 2, 3, 1, 2, 3], 2); + * // => 1 * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; + * // using `fromIndex` + * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 4 * - * _.forIn(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) + * // performing a binary search + * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); + * // => 2 */ - var forIn = createIterator({ - 'args': 'object, callback, thisArg', - 'init': 'object', - 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)", - 'loop': 'if (callback(object[key], key, object) === false) {\n return result;\n }', - 'useHas': false - }); + function indexOf(array, value, fromIndex) { + if (typeof fromIndex == 'number') { + var length = array ? array.length : 0; + fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0); + } else if (fromIndex) { + var index = sortedIndex(array, value); + return array[index] === value ? index : -1; + } + return baseIndexOf(array, value, fromIndex); + } /** - * This method is like `_.forIn` except that it iterates over elements - * of a `collection` in the opposite order. + * Gets all but the last element or last `n` elements of an array. If a + * callback is provided elements at the end of the array are excluded from + * the result as long as the callback returns truey. The callback is bound + * to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|number|string} [callback=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @returns {Array} Returns a slice of `array`. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * _.initial([1, 2, 3]); + * // => [1, 2] * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; + * // excludes the last two elements + * _.initial([1, 2, 3], 2); + * // => [1] * - * _.forInRight(new Shape, function(value, key) { - * console.log(key); + * // excludes elements from the end until the callback fails + * _.initial([1, 2, 3], function(num) { + * return num > 1; * }); - * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' + * // => [1] + * + * var characters = [ + * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, + * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, + * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.initial(characters, 'blocked'); + * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }] + * + * // using "_.where" callback shorthand + * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); + * // => ['barney', 'fred'] */ - function forInRight(object, callback, thisArg) { - var pairs = []; - - forIn(object, function(value, key) { - pairs.push(key, value); - }); + function initial(array, callback, thisArg) { + var n = 0, + length = array ? array.length : 0; - var length = pairs.length; - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - if (callback(pairs[length--], pairs[length], object) === false) { - break; + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = lodash.createCallback(callback, thisArg, 3); + while (index-- && callback(array[index], index, array)) { + n++; } + } else { + n = (callback == null || thisArg) ? 1 : callback || n; } - return object; + return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); } /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. + * Creates an array of unique values present in all provided arrays using + * strict equality for comparisons, i.e. `===`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Arrays + * @param {...Array} [array] The arrays to inspect. + * @returns {Array} Returns an array of shared values. * @example * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) + * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); + * // => [1, 2] */ - function forOwn(object, callback, thisArg) { - var index = -1, - props = keys(object), - length = props.length; + function intersection() { + var args = [], + argsIndex = -1, + argsLength = arguments.length, + caches = getArray(), + indexOf = getIndexOf(), + trustIndexOf = indexOf === baseIndexOf, + seen = getArray(); - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); + while (++argsIndex < argsLength) { + var value = arguments[argsIndex]; + if (isArray(value) || isArguments(value)) { + args.push(value); + caches.push(trustIndexOf && value.length >= largeArraySize && + createCache(argsIndex ? args[argsIndex] : seen)); + } + } + var array = args[0], + index = -1, + length = array ? array.length : 0, + result = []; + + outer: while (++index < length) { - var key = props[index]; - if (callback(object[key], key, object) === false) { - break; + var cache = caches[0]; + value = array[index]; + + if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { + argsIndex = argsLength; + (cache || seen).push(value); + while (--argsIndex) { + cache = caches[argsIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { + continue outer; + } + } + result.push(value); } } - return object; + while (argsLength--) { + cache = caches[argsLength]; + if (cache) { + releaseObject(cache); + } + } + releaseArray(caches); + releaseArray(seen); + return result; } /** - * This method is like `_.forOwn` except that it iterates over elements - * of a `collection` in the opposite order. + * Gets the last element or last `n` elements of an array. If a callback is + * provided elements at the end of the array are returned as long as the + * callback returns truey. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|number|string} [callback] The function called + * per element or the number of elements to return. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @returns {*} Returns the last element(s) of `array`. * @example * - * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' - */ - function forOwnRight(object, callback, thisArg) { - var props = keys(object), - length = props.length; - - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - var key = props[length]; - if (callback(object[key], key, object) === false) { - break; + * _.last([1, 2, 3]); + * // => 3 + * + * // returns the last two elements + * _.last([1, 2, 3], 2); + * // => [2, 3] + * + * // returns elements from the end until the callback fails + * _.last([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [2, 3] + * + * var characters = [ + * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, + * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, + * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.last(characters, 'blocked'), 'name'); + * // => ['fred', 'pebbles'] + * + * // using "_.where" callback shorthand + * _.last(characters, { 'employer': 'na' }); + * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + */ + function last(array, callback, thisArg) { + var n = 0, + length = array ? array.length : 0; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = lodash.createCallback(callback, thisArg, 3); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array ? array[length - 1] : undefined; } } - return object; + return slice(array, nativeMax(0, length - n)); } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * Gets the index at which the last occurrence of `value` is found using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @alias methods - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names that have function values. + * @category Arrays + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value or `-1`. * @example * - * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); + * // => 4 + * + * // using `fromIndex` + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 1 */ - function functions(object) { - var result = []; - forIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); + function lastIndexOf(array, value, fromIndex) { + var index = array ? array.length : 0; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + } + while (index--) { + if (array[index] === value) { + return index; } - }); - return result.sort(); + } + return -1; } /** - * Checks if the specified property name exists as a direct property of `object`, - * instead of an inherited property. + * Removes all provided values from the given array using strict equality for + * comparisons, i.e. `===`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @param {string} key The name of the property to check. - * @returns {boolean} Returns `true` if key is a direct property, else `false`. + * @category Arrays + * @param {Array} array The array to modify. + * @param {...*} [value] The values to remove. + * @returns {Array} Returns `array`. * @example * - * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); - * // => true + * var array = [1, 2, 3, 1, 2, 3]; + * _.pull(array, 2, 3); + * console.log(array); + * // => [1, 1] */ - function has(object, key) { - return object ? hasOwnProperty.call(object, key) : false; + function pull(array) { + var args = arguments, + argsIndex = 0, + argsLength = args.length, + length = array ? array.length : 0; + + while (++argsIndex < argsLength) { + var index = -1, + value = args[argsIndex]; + while (++index < length) { + if (array[index] === value) { + splice.call(array, index--, 1); + length--; + } + } + } + return array; } /** - * Creates an object composed of the inverted keys and values of the given - * object. If the given object contains duplicate values, subsequent values - * will overwrite property assignments of previous values unless `multiValue` - * is `true`. + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `end`. If `start` is less than `stop` a + * zero-length range is created unless a negative `step` is specified. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to invert. - * @param {boolean} [multiValue=false] Allow multiple values per key. - * @returns {Object} Returns the created inverted object. + * @category Arrays + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns a new range array. * @example * - * _.invert({ 'first': 'fred', 'second': 'barney' }); - * // => { 'fred': 'first', 'barney': 'second' } + * _.range(4); + * // => [0, 1, 2, 3] * - * // without `multiValue` - * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }); - * // => { 'fred': 'third', 'barney': 'second' } + * _.range(1, 5); + * // => [1, 2, 3, 4] * - * // with `multiValue` - * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); - * // => { 'fred': ['first', 'third'], 'barney': 'second' } + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] */ - function invert(object, multiValue) { + function range(start, end, step) { + start = +start || 0; + step = typeof step == 'number' ? step : (+step || 1); + + if (end == null) { + end = start; + start = 0; + } + // use `Array(length)` so engines like Chakra and V8 avoid slower modes + // http://youtu.be/XAqIpGU8ZZk#t=17m25s var index = -1, - props = keys(object), - length = props.length, - result = {}; + length = nativeMax(0, ceil((end - start) / (step || 1))), + result = Array(length); while (++index < length) { - var key = props[index], - value = object[key]; - - if (multiValue && hasOwnProperty.call(result, value)) { - if (typeof result[value] == 'string') { - result[value] = [result[value]]; - } - result[value].push(key); - } - else { - result[value] = key; - } + result[index] = start; + start += step; } return result; } /** - * Checks if `value` is a boolean value. + * Removes all elements from an array that the callback returns truey for + * and returns an array of removed elements. The callback is bound to `thisArg` + * and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. + * @category Arrays + * @param {Array} array The array to modify. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of removed elements. * @example * - * _.isBoolean(null); - * // => false + * var array = [1, 2, 3, 4, 5, 6]; + * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * + * console.log(array); + * // => [1, 3, 5] + * + * console.log(evens); + * // => [2, 4, 6] */ - function isBoolean(value) { - return value === true || value === false || - value && typeof value == 'object' && toString.call(value) == boolClass || false; + function remove(array, callback, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = []; + + callback = lodash.createCallback(callback, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (callback(value, index, array)) { + result.push(value); + splice.call(array, index--, 1); + length--; + } + } + return result; } /** - * Checks if `value` is a date. + * The opposite of `_.initial`; this method gets all but the first element or + * first `n` elements of an array. If a callback function is provided elements + * at the beginning of the array are excluded from the result as long as the + * callback returns truey. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a date, else `false`. - * @example + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. * - * _.isDate(new Date); - * // => true - */ - function isDate(value) { - return value && typeof value == 'object' && toString.call(value) == dateClass || false; - } - - /** - * Checks if `value` is a DOM element. + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. + * @alias drop, tail + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|number|string} [callback=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. * @example * - * _.isElement(document.body); - * // => true - */ - function isElement(value) { - return value && typeof value == 'object' && value.nodeType === 1 && - (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value)) || false; - } - // fallback for environments without DOM support - if (!support.dom) { - isElement = function(value) { - return value && typeof value == 'object' && value.nodeType === 1 && - !isPlainObject(value) || false; - }; - } - - /** - * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a - * length of `0` and objects with no own enumerable properties are considered - * "empty". + * _.rest([1, 2, 3]); + * // => [2, 3] * - * @static - * @memberOf _ - * @category Objects - * @param {Array|Object|string} value The value to inspect. - * @returns {boolean} Returns `true` if the `value` is empty, else `false`. - * @example + * // excludes the first two elements + * _.rest([1, 2, 3], 2); + * // => [3] * - * _.isEmpty([1, 2, 3]); - * // => false + * // excludes elements from the beginning until the callback fails + * _.rest([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [3] * - * _.isEmpty({}); - * // => true + * var characters = [ + * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, + * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, + * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } + * ]; * - * _.isEmpty(''); - * // => true + * // using "_.pluck" callback shorthand + * _.pluck(_.rest(characters, 'blocked'), 'name'); + * // => ['fred', 'pebbles'] + * + * // using "_.where" callback shorthand + * _.rest(characters, { 'employer': 'slate' }); + * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] */ - function isEmpty(value) { - var result = true; - if (!value) { - return result; - } - var className = toString.call(value), - length = value.length; + function rest(array, callback, thisArg) { + if (typeof callback != 'number' && callback != null) { + var n = 0, + index = -1, + length = array ? array.length : 0; - if ((className == arrayClass || className == stringClass || - (support.argsClass ? className == argsClass : isArguments(value))) || - (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { - return !length; + callback = lodash.createCallback(callback, thisArg, 3); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); } - forOwn(value, function() { - return (result = false); - }); - return result; + return slice(array, n); } /** - * Performs a deep comparison between two values to determine if they are - * equivalent to each other. If a callback is provided it will be executed - * to compare values. If the callback returns `undefined` comparisons will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (a, b). + * Uses a binary search to determine the smallest index at which a value + * should be inserted into a given sorted array in order to maintain the sort + * order of the array. If a callback is provided it will be executed for + * `value` and each element of `array` to compute their sort ranking. The + * callback is bound to `thisArg` and invoked with one argument; (value). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. + * @category Arrays + * @param {Array} array The array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * - * var object = { 'name': 'fred' }; - * var copy = { 'name': 'fred' }; - * - * object == copy; - * // => false + * _.sortedIndex([20, 30, 50], 40); + * // => 2 * - * _.isEqual(object, copy); - * // => true + * var dict = { + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * }; * - * var words = ['hello', 'goodbye']; - * var otherWords = ['hi', 'goodbye']; + * // using `callback` + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return dict.wordToNumber[word]; + * }); + * // => 2 * - * _.isEqual(words, otherWords, function(a, b) { - * var reGreet = /^(?:hello|hi)$/i, - * aGreet = _.isString(a) && reGreet.test(a), - * bGreet = _.isString(b) && reGreet.test(b); + * // using `callback` with `thisArg` + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return this.wordToNumber[word]; + * }, dict); + * // => 2 * - * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; - * }); - * // => true + * // using "_.pluck" callback shorthand + * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 2 */ - function isEqual(a, b, callback, thisArg) { - return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2)); + function sortedIndex(array, value, callback, thisArg) { + var low = 0, + high = array ? array.length : low; + + // explicitly reference `identity` for better inlining in Firefox + callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity; + value = callback(value); + + while (low < high) { + var mid = (low + high) >>> 1; + (callback(array[mid]) < value) + ? low = mid + 1 + : high = mid; + } + return low; } /** - * Checks if `value` is, or can be coerced to, a finite number. - * - * Note: This is not the same as native `isFinite` which will return true for - * booleans and empty strings. See the [ES5 spec](http://es5.github.io/#x15.1.2.5) - * for more details. + * Creates an array of unique values, in order, of the provided arrays using + * strict equality for comparisons, i.e. `===`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is finite, else `false`. + * @category Arrays + * @param {...Array} [array] The arrays to inspect. + * @returns {Array} Returns an array of combined values. * @example * - * _.isFinite(-101); - * // => true - * - * _.isFinite('10'); - * // => true - * - * _.isFinite(true); - * // => false - * - * _.isFinite(''); - * // => false - * - * _.isFinite(Infinity); - * // => false + * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); + * // => [1, 2, 3, 5, 4] */ - function isFinite(value) { - return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + function union() { + return baseUniq(baseFlatten(arguments, true, true)); } /** - * Checks if `value` is a function. + * Creates a duplicate-value-free version of an array using strict equality + * for comparisons, i.e. `===`. If the array is sorted, providing + * `true` for `isSorted` will use a faster algorithm. If a callback is provided + * each element of `array` is passed through the callback before uniqueness + * is computed. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. + * @alias unique + * @category Arrays + * @param {Array} array The array to process. + * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a duplicate-value-free array. * @example * - * _.isFunction(_); - * // => true - */ - function isFunction(value) { - return typeof value == 'function'; - } - // fallback for older versions of Chrome and Safari - if (isFunction(/x/)) { - isFunction = function(value) { - return typeof value == 'function' && toString.call(value) == funcClass; - }; - } - - /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * _.uniq([1, 2, 1, 3, 1]); + * // => [1, 2, 3] * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. - * @example + * // using `isSorted` + * _.uniq([1, 1, 2, 2, 3], true); + * // => [1, 2, 3] * - * _.isObject({}); - * // => true + * // using `callback` + * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); + * // => ['A', 'b', 'C'] * - * _.isObject([1, 2, 3]); - * // => true + * // using `callback` with `thisArg` + * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); + * // => [1, 2.5, 3] * - * _.isObject(1); - * // => false + * // using "_.pluck" callback shorthand + * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); + function uniq(array, isSorted, callback, thisArg) { + // juggle arguments + if (typeof isSorted != 'boolean' && isSorted != null) { + thisArg = callback; + callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted; + isSorted = false; + } + if (callback != null) { + callback = lodash.createCallback(callback, thisArg, 3); + } + return baseUniq(array, isSorted, callback); } /** - * Checks if `value` is `NaN`. - * - * Note: This is not the same as native `isNaN` which will return `true` for - * `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) - * for more details. + * Creates an array excluding all provided values using strict equality for + * comparisons, i.e. `===`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. + * @category Arrays + * @param {Array} array The array to filter. + * @param {...*} [value] The values to exclude. + * @returns {Array} Returns a new array of filtered values. * @example * - * _.isNaN(NaN); - * // => true - * - * _.isNaN(new Number(NaN)); - * // => true - * - * isNaN(undefined); - * // => true - * - * _.isNaN(undefined); - * // => false + * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); + * // => [2, 3, 4] */ - function isNaN(value) { - // `NaN` as a primitive is the only value that is not equal to itself - // (perform the [[Class]] check first to avoid errors with some host objects in IE) - return isNumber(value) && value != +value; + function without(array) { + return baseDifference(array, slice(arguments, 1)); } /** - * Checks if `value` is `null`. + * Creates an array that is the symmetric difference of the provided arrays. + * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. + * @category Arrays + * @param {...Array} [array] The arrays to inspect. + * @returns {Array} Returns an array of values. * @example * - * _.isNull(null); - * // => true + * _.xor([1, 2, 3], [5, 2, 1, 4]); + * // => [3, 5, 4] * - * _.isNull(undefined); - * // => false + * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); + * // => [1, 4, 5] */ - function isNull(value) { - return value === null; + function xor() { + var index = -1, + length = arguments.length; + + while (++index < length) { + var array = arguments[index]; + if (isArray(array) || isArguments(array)) { + var result = result + ? baseDifference(result, array).concat(baseDifference(array, result)) + : array; + } + } + return result ? baseUniq(result) : []; } /** - * Checks if `value` is a number. - * - * Note: `NaN` is considered a number. See the [ES5 spec](http://es5.github.io/#x8.5) - * for more details. + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the second + * elements of the given arrays, and so on. If a zipped value is provided its + * corresponding unzipped value will be returned. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a number, else `false`. + * @alias unzip + * @category Arrays + * @param {...Array} [array] Arrays to process. + * @returns {Array} Returns a new array of grouped elements. * @example * - * _.isNumber(8.4 * 5); - * // => true + * _.zip(['fred', 'barney'], [30, 40], [true, false]); + * // => [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip([['fred', 30, true], ['barney', 40, false]]); + * // => [['fred', 'barney'], [30, 40], [true, false]] */ - function isNumber(value) { - return typeof value == 'number' || - value && typeof value == 'object' && toString.call(value) == numberClass || false; + function zip() { + var array = arguments.length > 1 ? arguments : arguments[0], + index = -1, + length = array ? max(pluck(array, 'length')) : 0, + result = Array(length < 0 ? 0 : length); + + while (++index < length) { + result[index] = pluck(array, index); + } + return result; } /** - * Checks if `value` is an object created by the `Object` constructor. + * Creates an object composed from arrays of `keys` and `values`. Provide + * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` + * or two arrays, one of `keys` and one of corresponding `values`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @alias object + * @category Arrays + * @param {Array} keys The array of keys. + * @param {Array} [values=[]] The array of values. + * @returns {Object} Returns an object composed of the given keys and + * corresponding values. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * _.isPlainObject(new Shape); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true + * _.zipObject(['fred', 'barney'], [30, 40]); + * // => { 'fred': 30, 'barney': 40 } */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { - return false; + function zipObject(keys, values) { + var index = -1, + length = keys ? keys.length : 0, + result = {}; + + if (!values && length && !isArray(keys[0])) { + values = []; } - var valueOf = value.valueOf, - objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + while (++index < length) { + var key = keys[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; + /*--------------------------------------------------------------------------*/ /** - * Checks if `value` is a regular expression. + * Creates a `lodash` object that wraps the given value with explicit + * method chaining enabled. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. + * @category Chaining + * @param {*} value The value to wrap. + * @returns {Object} Returns the wrapper object. * @example * - * _.isRegExp(/fred/); - * // => true + * var characters = [ + * { 'name': 'barney', 'age': 36 }, + * { 'name': 'fred', 'age': 40 }, + * { 'name': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _.chain(characters) + * .sortBy('age') + * .map(function(chr) { return chr.name + ' is ' + chr.age; }) + * .first() + * .value(); + * // => 'pebbles is 1' */ - function isRegExp(value) { - return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false; + function chain(value) { + value = new lodashWrapper(value); + value.__chain__ = true; + return value; } /** - * Checks if `value` is a string. + * This method invokes `interceptor` and returns `value`. The interceptor is + * bound to `thisArg` and invoked with one argument; (value). The purpose of + * this method is to "tap into" a method chain in order to perform operations + * on intermediate results within the chain. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a string, else `false`. + * @category Chaining + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @param {*} [thisArg] The `this` binding of `interceptor`. + * @returns {*} Returns `value`. * @example * - * _.isString('fred'); - * // => true - */ - function isString(value) { - return typeof value == 'string' || - value && typeof value == 'object' && toString.call(value) == stringClass || false; + * _([1, 2, 3, 4]) + * .tap(function(array) { array.pop(); }) + * .reverse() + * .value(); + * // => [3, 2, 1] + */ + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; } /** - * Checks if `value` is `undefined`. + * Enables explicit method chaining on the wrapper object. * - * @static + * @name chain * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. + * @category Chaining + * @returns {*} Returns the wrapper object. * @example * - * _.isUndefined(void 0); - * // => true + * var characters = [ + * { 'name': 'barney', 'age': 36 }, + * { 'name': 'fred', 'age': 40 } + * ]; + * + * // without explicit chaining + * _(characters).first(); + * // => { 'name': 'barney', 'age': 36 } + * + * // with explicit chaining + * _(characters).chain() + * .first() + * .pick('age') + * .value(); + * // => { 'age': 36 } */ - function isUndefined(value) { - return typeof value == 'undefined'; + function wrapperChain() { + this.__chain__ = true; + return this; } /** - * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through the callback. - * The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Produces the `toString` result of the wrapped value. * - * @static + * @name toString * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns a new object with values of the results of each `callback` execution. + * @category Chaining + * @returns {string} Returns the string result. * @example * - * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); - * // => { 'a': 3, 'b': 6, 'c': 9 } - * - * var characters = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; - * - * // using "_.pluck" callback shorthand - * _.mapValues(characters, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } + * _([1, 2, 3]).toString(); + * // => '1,2,3' */ - function mapValues(object, callback, thisArg) { - var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); - - forOwn(object, function(value, key, object) { - result[key] = callback(value, key, object); - }); - return result; + function wrapperToString() { + return String(this.__wrapped__); } /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * will overwrite property assignments of previous sources. If a callback is - * provided it will be executed to produce the merged values of the destination - * and source properties. If the callback returns `undefined` merging will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (objectValue, sourceValue). + * Extracts the wrapped value. * - * @static + * @name valueOf * @memberOf _ - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize merging properties. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. + * @alias value + * @category Chaining + * @returns {*} Returns the wrapped value. * @example * - * var names = { - * 'characters': [ - * { 'name': 'barney' }, - * { 'name': 'fred' } - * ] - * }; - * - * var ages = { - * 'characters': [ - * { 'age': 36 }, - * { 'age': 40 } - * ] - * }; - * - * _.merge(names, ages); - * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } - * - * var food = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var otherFood = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(food, otherFood, function(a, b) { - * return _.isArray(a) ? a.concat(b) : undefined; - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + * _([1, 2, 3]).valueOf(); + * // => [1, 2, 3] */ - function merge(object) { - var args = arguments, - length = 2; - - if (!isObject(object)) { - return object; - } - // allows working with `_.reduce` and `_.reduceRight` without using - // their `index` and `collection` arguments - if (typeof args[2] != 'number') { - length = args.length; - } - if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 2); - } else if (length > 2 && typeof args[length - 1] == 'function') { - callback = args[--length]; - } - var sources = slice(arguments, 1, length), - index = -1, - stackA = getArray(), - stackB = getArray(); - - while (++index < length) { - baseMerge(object, sources[index], callback, stackA, stackB); - } - releaseArray(stackA); - releaseArray(stackB); - return object; + function wrapperValueOf() { + return this.__wrapped__; } + /*--------------------------------------------------------------------------*/ + /** - * Creates a shallow clone of `object` excluding the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` omitting the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * Creates an array of elements from the specified indexes, or keys, of the + * `collection`. Indexes may be specified as individual arguments or as arrays + * of indexes. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The properties to omit or the - * function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object without the omitted properties. + * @category Collections + * @param {Array|Object|string} collection The collection to iterate over. + * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` + * to retrieve, specified as individual indexes or arrays of indexes. + * @returns {Array} Returns a new array of elements corresponding to the + * provided indexes. * @example * - * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); - * // => { 'name': 'fred' } + * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); + * // => ['a', 'c', 'e'] * - * _.omit({ 'name': 'fred', 'age': 40 }, function(value) { - * return typeof value == 'number'; - * }); - * // => { 'name': 'fred' } + * _.at(['fred', 'barney', 'pebbles'], 0, 2); + * // => ['fred', 'pebbles'] */ - function omit(object, callback, thisArg) { - var result = {}; - if (typeof callback != 'function') { - var props = []; - forIn(object, function(value, key) { - props.push(key); - }); - props = baseDifference(props, baseFlatten(arguments, true, false, 1)); - - var index = -1, - length = props.length; + function at(collection) { + var args = arguments, + index = -1, + props = baseFlatten(args, true, false, 1), + length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length, + result = Array(length); - while (++index < length) { - var key = props[index]; - result[key] = object[key]; - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - forIn(object, function(value, key, object) { - if (!callback(value, key, object)) { - result[key] = value; - } - }); + if (support.unindexedChars && isString(collection)) { + collection = collection.split(''); + } + while(++index < length) { + result[index] = collection[props[index]]; } return result; } /** - * Creates a two dimensional array of an object's key-value pairs, - * i.e. `[[key1, value1], [key2, value2]]`. + * Checks if a given value is present in a collection using strict equality + * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the + * offset from the end of the collection. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns new array of key-value pairs. - * @example - * - * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) - */ - function pairs(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - var key = props[index]; - result[index] = [key, object[key]]; - } - return result; - } - - /** - * Creates a shallow clone of `object` composed of the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` picking the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The function called per - * iteration or property names to pick, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object composed of the picked properties. - * @example - * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); - * // => { 'name': 'fred' } - * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { - * return key.charAt(0) != '_'; - * }); - * // => { 'name': 'fred' } - */ - function pick(object, callback, thisArg) { - var result = {}; - if (typeof callback != 'function') { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = isObject(object) ? props.length : 0; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - forIn(object, function(value, key, object) { - if (callback(value, key, object)) { - result[key] = value; - } - }); - } - return result; - } - - /** - * An alternative to `_.reduce` this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable properties through a callback, with each callback execution - * potentially mutating the `accumulator` object. The callback is bound to - * `thisArg` and invoked with four arguments; (accumulator, value, key, object). - * Callbacks may exit iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Array|Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. - * @example - * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; - * } - * }); - * // => [1, 9, 25] - * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; - * }); - * // => { 'a': 3, 'b': 6, 'c': 9 } - */ - function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); - if (accumulator == null) { - if (isArr) { - accumulator = []; - } else { - var ctor = object && object.constructor, - proto = ctor && ctor.prototype; - - accumulator = baseCreate(proto); - } - } - if (callback) { - callback = lodash.createCallback(callback, thisArg, 4); - (isArr ? baseEach : forOwn)(object, function(value, index, object) { - return callback(accumulator, value, index, object); - }); - } - return accumulator; - } - - /** - * Creates an array composed of the own enumerable property values of `object`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property values. - * @example - * - * _.values({ 'one': 1, 'two': 2, 'three': 3 }); - * // => [1, 2, 3] (property order is not guaranteed across environments) - */ - function values(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; - } - return result; - } - - /*--------------------------------------------------------------------------*/ - - /** - * Creates an array of elements from the specified indexes, or keys, of the - * `collection`. Indexes may be specified as individual arguments or as arrays - * of indexes. - * - * @static - * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` - * to retrieve, specified as individual indexes or arrays of indexes. - * @returns {Array} Returns a new array of elements corresponding to the - * provided indexes. - * @example - * - * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); - * // => ['a', 'c', 'e'] - * - * _.at(['fred', 'barney', 'pebbles'], 0, 2); - * // => ['fred', 'pebbles'] - */ - function at(collection) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), - length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length, - result = Array(length); - - if (support.unindexedChars && isString(collection)) { - collection = collection.split(''); - } - while(++index < length) { - result[index] = collection[props[index]]; - } - return result; - } - - /** - * Checks if a given value is present in a collection using strict equality - * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. - * - * @static - * @memberOf _ - * @alias include - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {*} target The value to check for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if the `target` element is found, else `false`. + * @alias include + * @category Collections + * @param {Array|Object|string} collection The collection to iterate over. + * @param {*} target The value to check for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {boolean} Returns `true` if the `target` element is found, else `false`. * @example * * _.contains([1, 2, 3], 1); @@ -4559,867 +4348,869 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array with all falsey values removed. The values `false`, `null`, - * `0`, `""`, `undefined`, and `NaN` are all falsey. + * Creates a function that executes `func`, with the `this` binding and + * arguments of the created function, only after being called `n` times. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to compact. - * @returns {Array} Returns a new array of filtered values. + * @category Functions + * @param {number} n The number of times the function must be called before + * `func` is executed. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. * @example * - * _.compact([0, 1, false, 2, '', 3]); - * // => [1, 2, 3] + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('Done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => logs 'Done saving!', after all saves have completed */ - function compact(array) { - var index = -1, - length = array ? array.length : 0, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index]; - if (value) { - result[resIndex++] = value; - } + function after(n, func) { + if (!isFunction(func)) { + throw new TypeError; } - return result; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any additional `bind` arguments to those + * provided to the bound function. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to process. - * @param {...Array} [values] The arrays of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @category Functions + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {...*} [arg] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. * @example * - * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); - * // => [1, 3, 4] - */ - function difference(array) { - return baseDifference(array, baseFlatten(arguments, true, true, 1)); - } - - /** - * This method is like `_.find` except that it returns the index of the first - * element that passes the callback check, instead of the element itself. - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * var func = function(greeting) { + * return greeting + ' ' + this.name; + * }; * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * func = _.bind(func, { 'name': 'fred' }, 'hi'); + * func(); + * // => 'hi fred' + */ + function bind(func, thisArg) { + return arguments.length > 2 + ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) + : createWrapper(func, 1, null, null, thisArg); + } + + /** + * Binds methods of an object to the object itself, overwriting the existing + * method. Method names may be specified as individual arguments or as arrays + * of method names. If no method names are provided all the function properties + * of `object` will be bound. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index of the found element, else `-1`. + * @category Functions + * @param {Object} object The object to bind and assign the bound methods to. + * @param {...string} [methodName] The object method names to + * bind, specified as individual method names or arrays of method names. + * @returns {Object} Returns `object`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true }, - * { 'name': 'pebbles', 'age': 1, 'blocked': false } - * ]; - * - * _.findIndex(characters, function(chr) { - * return chr.age < 20; - * }); - * // => 2 - * - * // using "_.where" callback shorthand - * _.findIndex(characters, { 'age': 36 }); - * // => 0 + * var view = { + * 'label': 'docs', + * 'onClick': function() { console.log('clicked ' + this.label); } + * }; * - * // using "_.pluck" callback shorthand - * _.findIndex(characters, 'blocked'); - * // => 1 + * _.bindAll(view); + * jQuery('#docs').on('click', view.onClick); + * // => logs 'clicked docs', when the button is clicked */ - function findIndex(array, callback, thisArg) { - var index = -1, - length = array ? array.length : 0; + function bindAll(object) { + var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object), + index = -1, + length = funcs.length; - callback = lodash.createCallback(callback, thisArg, 3); while (++index < length) { - if (callback(array[index], index, array)) { - return index; - } + var key = funcs[index]; + object[key] = createWrapper(object[key], 1, null, null, object); } - return -1; + return object; } /** - * This method is like `_.findIndex` except that it iterates over elements - * of a `collection` from right to left. - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates a function that, when called, invokes the method at `object[key]` + * and prepends any additional `bindKey` arguments to those provided to the bound + * function. This method differs from `_.bind` by allowing bound functions to + * reference methods that will be redefined or don't yet exist. + * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) + * for more details. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index of the found element, else `-1`. + * @category Functions + * @param {Object} object The object the method belongs to. + * @param {string} key The key of the method. + * @param {...*} [arg] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': true }, - * { 'name': 'fred', 'age': 40, 'blocked': false }, - * { 'name': 'pebbles', 'age': 1, 'blocked': true } - * ]; + * var object = { + * 'name': 'fred', + * 'greet': function(greeting) { + * return greeting + ' ' + this.name; + * } + * }; * - * _.findLastIndex(characters, function(chr) { - * return chr.age > 30; - * }); - * // => 1 + * var func = _.bindKey(object, 'greet', 'hi'); + * func(); + * // => 'hi fred' * - * // using "_.where" callback shorthand - * _.findLastIndex(characters, { 'age': 36 }); - * // => 0 + * object.greet = function(greeting) { + * return greeting + 'ya ' + this.name + '!'; + * }; * - * // using "_.pluck" callback shorthand - * _.findLastIndex(characters, 'blocked'); - * // => 2 + * func(); + * // => 'hiya fred!' */ - function findLastIndex(array, callback, thisArg) { - var length = array ? array.length : 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (length--) { - if (callback(array[length], length, array)) { - return length; - } - } - return -1; + function bindKey(object, key) { + return arguments.length > 2 + ? createWrapper(key, 19, slice(arguments, 2), null, object) + : createWrapper(key, 3, null, null, object); } /** - * Gets the first element or first `n` elements of an array. If a callback - * is provided elements at the beginning of the array are returned as long - * as the callback returns truey. The callback is bound to `thisArg` and - * invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates a function that is the composition of the provided functions, + * where each function consumes the return value of the function that follows. + * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. + * Each function is executed with the `this` binding of the composed function. * * @static * @memberOf _ - * @alias head, take - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the first element(s) of `array`. + * @category Functions + * @param {...Function} [func] Functions to compose. + * @returns {Function} Returns the new composed function. * @example * - * _.first([1, 2, 3]); - * // => 1 - * - * // returns the first two elements - * _.first([1, 2, 3], 2); - * // => [1, 2] - * - * // returns elements from the beginning until the callback result is falsey - * _.first([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [1, 2] + * var realNameMap = { + * 'pebbles': 'penelope' + * }; * - * var characters = [ - * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * var format = function(name) { + * name = realNameMap[name.toLowerCase()] || name; + * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); + * }; * - * // using "_.pluck" callback shorthand - * _.first(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }] + * var greet = function(formatted) { + * return 'Hiya ' + formatted + '!'; + * }; * - * // using "_.where" callback shorthand - * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); - * // => ['barney', 'fred'] + * var welcome = _.compose(greet, format); + * welcome('pebbles'); + * // => 'Hiya Penelope!' */ - function first(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; + function compose() { + var funcs = arguments, + length = funcs.length; - if (typeof callback != 'number' && callback != null) { - var index = -1; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[0] : undefined; + while (length--) { + if (!isFunction(funcs[length])) { + throw new TypeError; } } - return slice(array, 0, nativeMin(nativeMax(0, n), length)); + return function() { + var args = arguments, + length = funcs.length; + + while (length--) { + args = [funcs[length].apply(this, args)]; + } + return args[0]; + }; } /** - * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truey, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before - * flattening. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates a function which accepts one or more arguments of `func` that when + * invoked either executes `func` returning its result, if all `func` arguments + * have been provided, or returns a function that accepts one or more of the + * remaining `func` arguments, and so on. The arity of `func` can be specified + * if `func.length` is not sufficient. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new flattened array. + * @category Functions + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @returns {Function} Returns the new curried function. * @example * - * _.flatten([1, [2], [3, [[4]]]]); - * // => [1, 2, 3, 4]; + * var curried = _.curry(function(a, b, c) { + * console.log(a + b + c); + * }); * - * // using `isShallow` - * _.flatten([1, [2], [3, [[4]]]], true); - * // => [1, 2, 3, [[4]]]; + * curried(1)(2)(3); + * // => 6 * - * var characters = [ - * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } - * ]; + * curried(1, 2)(3); + * // => 6 * - * // using "_.pluck" callback shorthand - * _.flatten(characters, 'pets'); - * // => ['hoppy', 'baby puss', 'dino'] + * curried(1, 2, 3); + * // => 6 */ - function flatten(array, isShallow, callback, thisArg) { - // juggle arguments - if (typeof isShallow != 'boolean' && isShallow != null) { - thisArg = callback; - callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow; - isShallow = false; - } - if (callback != null) { - array = map(array, callback, thisArg); - } - return baseFlatten(array, isShallow); + function curry(func, arity) { + arity = typeof arity == 'number' ? arity : (+arity || func.length); + return createWrapper(func, 4, null, null, null, arity); } /** - * Gets the index at which the first occurrence of `value` is found using - * strict equality for comparisons, i.e. `===`. If the array is already sorted - * providing `true` for `fromIndex` will run a faster binary search. + * Creates a function that will delay the execution of `func` until after + * `wait` milliseconds have elapsed since the last time it was invoked. + * 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 will return the result of the last `func` call. + * + * Note: If `leading` and `trailing` options are `true` `func` will be called + * on the trailing edge of the timeout only if the the debounced function is + * invoked more than once during the `wait` timeout. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {boolean|number} [fromIndex=0] The index to search from or `true` - * to perform a binary search on a sorted array. - * @returns {number} Returns the index of the matched value or `-1`. + * @category Functions + * @param {Function} func The function to debounce. + * @param {number} wait The number of milliseconds to delay. + * @param {Object} [options] The options object. + * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout. + * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called. + * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. * @example * - * _.indexOf([1, 2, 3, 1, 2, 3], 2); - * // => 1 + * // avoid costly calculations while the window size is in flux + * var lazyLayout = _.debounce(calculateLayout, 150); + * jQuery(window).on('resize', lazyLayout); * - * // using `fromIndex` - * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); - * // => 4 + * // execute `sendMail` when the click event is fired, debouncing subsequent calls + * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * }); * - * // performing a binary search - * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); - * // => 2 + * // ensure `batchLog` is executed once after 1 second of debounced calls + * var source = new EventSource('/stream'); + * source.addEventListener('message', _.debounce(batchLog, 250, { + * 'maxWait': 1000 + * }, false); */ - function indexOf(array, value, fromIndex) { - if (typeof fromIndex == 'number') { - var length = array ? array.length : 0; - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0); - } else if (fromIndex) { - var index = sortedIndex(array, value); - return array[index] === value ? index : -1; + function debounce(func, wait, options) { + var args, + maxTimeoutId, + result, + stamp, + thisArg, + timeoutId, + trailingCall, + lastCalled = 0, + maxWait = false, + trailing = true; + + if (!isFunction(func)) { + throw new TypeError; } - return baseIndexOf(array, value, fromIndex); + wait = nativeMax(0, wait) || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = options.leading; + maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0); + trailing = 'trailing' in options ? options.trailing : trailing; + } + var delayed = function() { + var remaining = wait - (now() - stamp); + if (remaining <= 0) { + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + var isCalled = trailingCall; + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + } + } else { + timeoutId = setTimeout(delayed, remaining); + } + }; + + var maxDelayed = function() { + if (timeoutId) { + clearTimeout(timeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (trailing || (maxWait !== wait)) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + } + }; + + return function() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), + isCalled = remaining <= 0; + + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } + else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } + else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + return result; + }; } /** - * Gets all but the last element or last `n` elements of an array. If a - * callback is provided elements at the end of the array are excluded from - * the result as long as the callback returns truey. The callback is bound - * to `thisArg` and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Defers executing the `func` function until the current call stack has cleared. + * Additional arguments will be provided to `func` when it is invoked. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @category Functions + * @param {Function} func The function to defer. + * @param {...*} [arg] Arguments to invoke the function with. + * @returns {number} Returns the timer id. * @example * - * _.initial([1, 2, 3]); - * // => [1, 2] + * _.defer(function(text) { console.log(text); }, 'deferred'); + * // logs 'deferred' after one or more milliseconds + */ + function defer(func) { + if (!isFunction(func)) { + throw new TypeError; + } + var args = slice(arguments, 1); + return setTimeout(function() { func.apply(undefined, args); }, 1); + } + + /** + * Executes the `func` function after `wait` milliseconds. Additional arguments + * will be provided to `func` when it is invoked. * - * // excludes the last two elements - * _.initial([1, 2, 3], 2); - * // => [1] + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay execution. + * @param {...*} [arg] Arguments to invoke the function with. + * @returns {number} Returns the timer id. + * @example * - * // excludes elements from the end until the callback fails - * _.initial([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [1] - * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; - * - * // using "_.pluck" callback shorthand - * _.initial(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }] - * - * // using "_.where" callback shorthand - * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); - * // => ['barney', 'fred'] + * _.delay(function(text) { console.log(text); }, 1000, 'later'); + * // => logs 'later' after one second */ - function initial(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; - - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; - } - } else { - n = (callback == null || thisArg) ? 1 : callback || n; + function delay(func, wait) { + if (!isFunction(func)) { + throw new TypeError; } - return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); + var args = slice(arguments, 2); + return setTimeout(function() { func.apply(undefined, args); }, wait); } /** - * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided it will be used to determine the cache key for storing the result + * based on the arguments provided to the memoized function. By default, the + * first argument provided to the memoized function is used as the cache key. + * The `func` is executed with the `this` binding of the memoized function. + * The result cache is exposed as the `cache` property on the memoized function. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of shared values. + * @category Functions + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] A function used to resolve the cache key. + * @returns {Function} Returns the new memoizing function. * @example * - * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); - * // => [1, 2] + * var fibonacci = _.memoize(function(n) { + * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); + * }); + * + * fibonacci(9) + * // => 34 + * + * var data = { + * 'fred': { 'name': 'fred', 'age': 40 }, + * 'pebbles': { 'name': 'pebbles', 'age': 1 } + * }; + * + * // modifying the result cache + * var get = _.memoize(function(name) { return data[name]; }, _.identity); + * get('pebbles'); + * // => { 'name': 'pebbles', 'age': 1 } + * + * get.cache.pebbles.name = 'penelope'; + * get('pebbles'); + * // => { 'name': 'penelope', 'age': 1 } */ - function intersection() { - var args = [], - argsIndex = -1, - argsLength = arguments.length, - caches = getArray(), - indexOf = getIndexOf(), - trustIndexOf = indexOf === baseIndexOf, - seen = getArray(); - - while (++argsIndex < argsLength) { - var value = arguments[argsIndex]; - if (isArray(value) || isArguments(value)) { - args.push(value); - caches.push(trustIndexOf && value.length >= largeArraySize && - createCache(argsIndex ? args[argsIndex] : seen)); - } + function memoize(func, resolver) { + if (!isFunction(func)) { + throw new TypeError; } - var array = args[0], - index = -1, - length = array ? array.length : 0, - result = []; - - outer: - while (++index < length) { - var cache = caches[0]; - value = array[index]; + var memoized = function() { + var cache = memoized.cache, + key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { - argsIndex = argsLength; - (cache || seen).push(value); - while (--argsIndex) { - cache = caches[argsIndex]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { - continue outer; - } - } - result.push(value); - } - } - while (argsLength--) { - cache = caches[argsLength]; - if (cache) { - releaseObject(cache); - } + return hasOwnProperty.call(cache, key) + ? cache[key] + : (cache[key] = func.apply(this, arguments)); } - releaseArray(caches); - releaseArray(seen); - return result; + memoized.cache = {}; + return memoized; } /** - * Gets the last element or last `n` elements of an array. If a callback is - * provided elements at the end of the array are returned as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates a function that is restricted to execute `func` once. Repeat calls to + * the function will return the value of the first call. The `func` is executed + * with the `this` binding of the created function. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the last element(s) of `array`. + * @category Functions + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. * @example * - * _.last([1, 2, 3]); - * // => 3 - * - * // returns the last two elements - * _.last([1, 2, 3], 2); - * // => [2, 3] - * - * // returns elements from the end until the callback fails - * _.last([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [2, 3] - * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.last(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.last(characters, { 'employer': 'na' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` executes `createApplication` once */ - function last(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; + function once(func) { + var ran, + result; - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[length - 1] : undefined; - } + if (!isFunction(func)) { + throw new TypeError; } - return slice(array, nativeMax(0, length - n)); + return function() { + if (ran) { + return result; + } + ran = true; + result = func.apply(this, arguments); + + // clear the `func` variable so the function may be garbage collected + func = null; + return result; + }; } /** - * Gets the index at which the last occurrence of `value` is found using strict - * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used - * as the offset from the end of the collection. + * Creates a function that, when called, invokes `func` with any additional + * `partial` arguments prepended to those provided to the new function. This + * method is similar to `_.bind` except it does **not** alter the `this` binding. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [arg] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var hi = _.partial(greet, 'hi'); + * hi('fred'); + * // => 'hi fred' + */ + function partial(func) { + return createWrapper(func, 16, slice(arguments, 1)); + } + + /** + * This method is like `_.partial` except that `partial` arguments are + * appended to those provided to the new function. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [arg] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. * @example * - * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); - * // => 4 + * var defaultsDeep = _.partialRight(_.merge, _.defaults); * - * // using `fromIndex` - * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); - * // => 1 + * var options = { + * 'variable': 'data', + * 'imports': { 'jq': $ } + * }; + * + * defaultsDeep(options, _.templateSettings); + * + * options.variable + * // => 'data' + * + * options.imports + * // => { '_': _, 'jq': $ } */ - function lastIndexOf(array, value, fromIndex) { - var index = array ? array.length : 0; - if (typeof fromIndex == 'number') { - index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; - } - while (index--) { - if (array[index] === value) { - return index; - } - } - return -1; + function partialRight(func) { + return createWrapper(func, 32, null, slice(arguments, 1)); } /** - * Removes all provided values from the given array using strict equality for - * comparisons, i.e. `===`. + * Creates a function that, when executed, will only call the `func` function + * at most once per every `wait` milliseconds. 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 will + * return the result of the last `func` call. + * + * Note: If `leading` and `trailing` options are `true` `func` will be called + * on the trailing edge of the timeout only if the the throttled function is + * invoked more than once during the `wait` timeout. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {...*} [value] The values to remove. - * @returns {Array} Returns `array`. + * @category Functions + * @param {Function} func The function to throttle. + * @param {number} wait The number of milliseconds to throttle executions to. + * @param {Object} [options] The options object. + * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. * @example * - * var array = [1, 2, 3, 1, 2, 3]; - * _.pull(array, 2, 3); - * console.log(array); - * // => [1, 1] + * // avoid excessively updating the position while scrolling + * var throttled = _.throttle(updatePosition, 100); + * jQuery(window).on('scroll', throttled); + * + * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes + * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { + * 'trailing': false + * })); */ - function pull(array) { - var args = arguments, - argsIndex = 0, - argsLength = args.length, - length = array ? array.length : 0; + function throttle(func, wait, options) { + var leading = true, + trailing = true; - while (++argsIndex < argsLength) { - var index = -1, - value = args[argsIndex]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } - } + if (!isFunction(func)) { + throw new TypeError; } - return array; + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = 'leading' in options ? options.leading : leading; + trailing = 'trailing' in options ? options.trailing : trailing; + } + debounceOptions.leading = leading; + debounceOptions.maxWait = wait; + debounceOptions.trailing = trailing; + + return debounce(func, wait, debounceOptions); } /** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to but not including `end`. If `start` is less than `stop` a - * zero-length range is created unless a negative `step` is specified. + * Creates a function that provides `value` to the wrapper function as its + * first argument. Additional arguments provided to the function are appended + * to those provided to the wrapper function. The wrapper is executed with + * the `this` binding of the created function. * * @static * @memberOf _ - * @category Arrays - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns a new range array. + * @category Functions + * @param {*} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. * @example * - * _.range(4); - * // => [0, 1, 2, 3] - * - * _.range(1, 5); - * // => [1, 2, 3, 4] - * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] - * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] - * - * _.range(1, 4, 0); - * // => [1, 1, 1] + * var p = _.wrap(_.escape, function(func, text) { + * return '

    ' + func(text) + '

    '; + * }); * - * _.range(0); - * // => [] + * p('Fred, Wilma, & Pebbles'); + * // => '

    Fred, Wilma, & Pebbles

    ' */ - function range(start, end, step) { - start = +start || 0; - step = typeof step == 'number' ? step : (+step || 1); - - if (end == null) { - end = start; - start = 0; - } - // use `Array(length)` so engines like Chakra and V8 avoid slower modes - // http://youtu.be/XAqIpGU8ZZk#t=17m25s - var index = -1, - length = nativeMax(0, ceil((end - start) / (step || 1))), - result = Array(length); - - while (++index < length) { - result[index] = start; - start += step; - } - return result; + function wrap(value, wrapper) { + return createWrapper(wrapper, 16, [value]); } + /*--------------------------------------------------------------------------*/ + /** - * Removes all elements from an array that the callback returns truey for - * and returns an array of removed elements. The callback is bound to `thisArg` - * and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Assigns own enumerable properties of source object(s) to the destination + * object. Subsequent sources will overwrite property assignments of previous + * sources. If a callback is provided it will be executed to produce the + * assigned values. The callback is bound to `thisArg` and invoked with two + * arguments; (objectValue, sourceValue). * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @alias extend + * @category Objects + * @param {Object} object The destination object. + * @param {...Object} [source] The source objects. + * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of removed elements. + * @returns {Object} Returns the destination object. * @example * - * var array = [1, 2, 3, 4, 5, 6]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); + * // => { 'name': 'fred', 'employer': 'slate' } * - * console.log(array); - * // => [1, 3, 5] + * var defaults = _.partialRight(_.assign, function(a, b) { + * return typeof a == 'undefined' ? b : a; + * }); * - * console.log(evens); - * // => [2, 4, 6] + * var object = { 'name': 'barney' }; + * defaults(object, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'employer': 'slate' } */ - function remove(array, callback, thisArg) { - var index = -1, - length = array ? array.length : 0, - result = []; + function assign(object, source, guard) { + var args = arguments, + argsIndex = 0, + argsLength = typeof guard == 'number' ? 2 : args.length; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length) { - var value = array[index]; - if (callback(value, index, array)) { - result.push(value); - splice.call(array, index--, 1); - length--; + if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { + var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2); + } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { + callback = args[--argsLength]; + } + while (++argsIndex < argsLength) { + source = args[argsIndex]; + if (isObject(source)) { + var index = -1, + props = keys(source), + length = props.length; + + while (++index < length) { + var key = props[index]; + object[key] = callback ? callback(object[key], source[key]) : source[key]; + } } } - return result; + return object; } /** - * The opposite of `_.initial`; this method gets all but the first element or - * first `n` elements of an array. If a callback function is provided elements - * at the beginning of the array are excluded from the result as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates a clone of `value`. If `isDeep` is `true` nested objects will also + * be cloned, otherwise they will be assigned by reference. If a callback + * is provided it will be executed to produce the cloned values. If the + * callback returns `undefined` cloning will be handled by the method instead. + * The callback is bound to `thisArg` and invoked with one argument; (value). * * @static * @memberOf _ - * @alias drop, tail - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. + * @category Objects + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @param {Function} [callback] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @returns {*} Returns the cloned value. * @example * - * _.rest([1, 2, 3]); - * // => [2, 3] - * - * // excludes the first two elements - * _.rest([1, 2, 3], 2); - * // => [3] - * - * // excludes elements from the beginning until the callback fails - * _.rest([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [3] - * * var characters = [ - * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } + * { 'name': 'barney', 'age': 36 }, + * { 'name': 'fred', 'age': 40 } * ]; * - * // using "_.pluck" callback shorthand - * _.pluck(_.rest(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] + * var shallow = _.clone(characters); + * shallow[0] === characters[0]; + * // => true * - * // using "_.where" callback shorthand - * _.rest(characters, { 'employer': 'slate' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + * var deep = _.clone(characters, true); + * deep[0] === characters[0]; + * // => false + * + * _.mixin({ + * 'clone': _.partialRight(_.clone, function(value) { + * return _.isElement(value) ? value.cloneNode(false) : undefined; + * }) + * }); + * + * var clone = _.clone(document.body); + * clone.childNodes.length; + * // => 0 */ - function rest(array, callback, thisArg) { - if (typeof callback != 'number' && callback != null) { - var n = 0, - index = -1, - length = array ? array.length : 0; - - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { - n++; - } - } else { - n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); + function clone(value, isDeep, callback, thisArg) { + // allows working with "Collections" methods without using their `index` + // and `collection` arguments for `isDeep` and `callback` + if (typeof isDeep != 'boolean' && isDeep != null) { + thisArg = callback; + callback = isDeep; + isDeep = false; } - return slice(array, n); + return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); } /** - * Uses a binary search to determine the smallest index at which a value - * should be inserted into a given sorted array in order to maintain the sort - * order of the array. If a callback is provided it will be executed for - * `value` and each element of `array` to compute their sort ranking. The - * callback is bound to `thisArg` and invoked with one argument; (value). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Creates a deep clone of `value`. If a callback is provided it will be + * executed to produce the cloned values. If the callback returns `undefined` + * cloning will be handled by the method instead. The callback is bound to + * `thisArg` and invoked with one argument; (value). * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Note: This method is loosely based on the structured clone algorithm. Functions + * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and + * objects created by constructors other than `Object` are cloned to plain `Object` objects. + * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) + * for more details. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to inspect. - * @param {*} value The value to evaluate. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @category Objects + * @param {*} value The value to deep clone. + * @param {Function} [callback] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. + * @returns {*} Returns the deep cloned value. * @example * - * _.sortedIndex([20, 30, 50], 40); - * // => 2 + * var characters = [ + * { 'name': 'barney', 'age': 36 }, + * { 'name': 'fred', 'age': 40 } + * ]; * - * var dict = { - * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * var deep = _.cloneDeep(characters); + * deep[0] === characters[0]; + * // => false + * + * var view = { + * 'label': 'docs', + * 'node': element * }; * - * // using `callback` - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { - * return dict.wordToNumber[word]; + * var clone = _.cloneDeep(view, function(value) { + * return _.isElement(value) ? value.cloneNode(true) : undefined; * }); - * // => 2 - * - * // using `callback` with `thisArg` - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { - * return this.wordToNumber[word]; - * }, dict); - * // => 2 * - * // using "_.pluck" callback shorthand - * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); - * // => 2 + * clone.node == view.node; + * // => false */ - function sortedIndex(array, value, callback, thisArg) { - var low = 0, - high = array ? array.length : low; - - // explicitly reference `identity` for better inlining in Firefox - callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity; - value = callback(value); + function cloneDeep(value, callback, thisArg) { + return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); + } - while (low < high) { - var mid = (low + high) >>> 1; - (callback(array[mid]) < value) - ? low = mid + 1 - : high = mid; - } - return low; + /** + * Creates an object that inherits from the given `prototype` object. If a + * `properties` object is provided its own enumerable properties are assigned + * to the created object. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties ? assign(result, properties) : result; } /** - * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * Assigns own enumerable properties of source object(s) to the destination + * object for all destination properties that resolve to `undefined`. Once a + * property is set, additional defaults of the same property will be ignored. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of combined values. + * @category Objects + * @param {Object} object The destination object. + * @param {...Object} [source] The source objects. + * @param- {Object} [guard] Allows working with `_.reduce` without using its + * `key` and `object` arguments as sources. + * @returns {Object} Returns the destination object. * @example * - * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); - * // => [1, 2, 3, 5, 4] + * var object = { 'name': 'barney' }; + * _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'employer': 'slate' } */ - function union() { - return baseUniq(baseFlatten(arguments, true, true)); + function defaults(object, source, guard) { + var args = arguments, + argsIndex = 0, + argsLength = typeof guard == 'number' ? 2 : args.length; + + while (++argsIndex < argsLength) { + source = args[argsIndex]; + if (isObject(source)) { + var index = -1, + props = keys(source), + length = props.length; + + while (++index < length) { + var key = props[index]; + if (typeof object[key] == 'undefined') { + object[key] = source[key]; + } + } + } + } + return object; } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing - * `true` for `isSorted` will use a faster algorithm. If a callback is provided - * each element of `array` is passed through the callback before uniqueness - * is computed. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). + * This method is like `_.findIndex` except that it returns the key of the + * first element that passes the callback check, instead of the element itself. * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. @@ -5430,1618 +5221,1831 @@ * * @static * @memberOf _ - * @alias unique - * @category Arrays - * @param {Array} array The array to process. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @category Objects + * @param {Object} object The object to search. + * @param {Function|Object|string} [callback=identity] The function called per + * iteration. If a property name or object is provided it will be used to + * create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a duplicate-value-free array. + * @returns {string|undefined} Returns the key of the found element, else `undefined`. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] + * var characters = { + * 'barney': { 'age': 36, 'blocked': false }, + * 'fred': { 'age': 40, 'blocked': true }, + * 'pebbles': { 'age': 1, 'blocked': false } + * }; * - * // using `isSorted` - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] + * _.findKey(characters, function(chr) { + * return chr.age < 40; + * }); + * // => 'barney' (property order is not guaranteed across environments) * - * // using `callback` - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] - * - * // using `callback` with `thisArg` - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] + * // using "_.where" callback shorthand + * _.findKey(characters, { 'age': 1 }); + * // => 'pebbles' * * // using "_.pluck" callback shorthand - * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] + * _.findKey(characters, 'blocked'); + * // => 'fred' */ - function uniq(array, isSorted, callback, thisArg) { - // juggle arguments - if (typeof isSorted != 'boolean' && isSorted != null) { - thisArg = callback; - callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted; - isSorted = false; - } - if (callback != null) { - callback = lodash.createCallback(callback, thisArg, 3); - } - return baseUniq(array, isSorted, callback); + function findKey(object, callback, thisArg) { + var result; + callback = lodash.createCallback(callback, thisArg, 3); + forOwn(object, function(value, key, object) { + if (callback(value, key, object)) { + result = key; + return false; + } + }); + return result; } /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * This method is like `_.findKey` except that it iterates over elements + * of a `collection` in the opposite order. + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to filter. - * @param {...*} [value] The values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @category Objects + * @param {Object} object The object to search. + * @param {Function|Object|string} [callback=identity] The function called per + * iteration. If a property name or object is provided it will be used to + * create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {string|undefined} Returns the key of the found element, else `undefined`. * @example * - * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); - * // => [2, 3, 4] + * var characters = { + * 'barney': { 'age': 36, 'blocked': true }, + * 'fred': { 'age': 40, 'blocked': false }, + * 'pebbles': { 'age': 1, 'blocked': true } + * }; + * + * _.findLastKey(characters, function(chr) { + * return chr.age < 40; + * }); + * // => returns `pebbles`, assuming `_.findKey` returns `barney` + * + * // using "_.where" callback shorthand + * _.findLastKey(characters, { 'age': 40 }); + * // => 'fred' + * + * // using "_.pluck" callback shorthand + * _.findLastKey(characters, 'blocked'); + * // => 'pebbles' */ - function without(array) { - return baseDifference(array, slice(arguments, 1)); + function findLastKey(object, callback, thisArg) { + var result; + callback = lodash.createCallback(callback, thisArg, 3); + forOwnRight(object, function(value, key, object) { + if (callback(value, key, object)) { + result = key; + return false; + } + }); + return result; } /** - * Creates an array that is the symmetric difference of the provided arrays. - * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. + * Iterates over own and inherited enumerable properties of an object, + * executing the callback for each property. The callback is bound to `thisArg` + * and invoked with three arguments; (value, key, object). Callbacks may exit + * iteration early by explicitly returning `false`. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of values. + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. * @example * - * _.xor([1, 2, 3], [5, 2, 1, 4]); - * // => [3, 5, 4] + * function Shape() { + * this.x = 0; + * this.y = 0; + * } * - * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); - * // => [1, 4, 5] + * Shape.prototype.move = function(x, y) { + * this.x += x; + * this.y += y; + * }; + * + * _.forIn(new Shape, function(value, key) { + * console.log(key); + * }); + * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) */ - function xor() { - var index = -1, - length = arguments.length; - - while (++index < length) { - var array = arguments[index]; - if (isArray(array) || isArguments(array)) { - var result = result - ? baseDifference(result, array).concat(baseDifference(array, result)) - : array; - } - } - return result ? baseUniq(result) : []; - } + var forIn = createIterator({ + 'args': 'object, callback, thisArg', + 'init': 'object', + 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)", + 'loop': 'if (callback(object[key], key, object) === false) {\n return result;\n }', + 'useHas': false + }); /** - * Creates an array of grouped elements, the first of which contains the - * first elements of the given arrays, the second of which contains the second - * elements of the given arrays, and so on. If a zipped value is provided its - * corresponding unzipped value will be returned. + * This method is like `_.forIn` except that it iterates over elements + * of a `collection` in the opposite order. * * @static * @memberOf _ - * @alias unzip - * @category Arrays - * @param {...Array} [array] Arrays to process. - * @returns {Array} Returns a new array of grouped elements. + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. * @example * - * _.zip(['fred', 'barney'], [30, 40], [true, false]); - * // => [['fred', 30, true], ['barney', 40, false]] + * function Shape() { + * this.x = 0; + * this.y = 0; + * } * - * _.unzip([['fred', 30, true], ['barney', 40, false]]); - * // => [['fred', 'barney'], [30, 40], [true, false]] + * Shape.prototype.move = function(x, y) { + * this.x += x; + * this.y += y; + * }; + * + * _.forInRight(new Shape, function(value, key) { + * console.log(key); + * }); + * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' */ - function zip() { - var array = arguments.length > 1 ? arguments : arguments[0], - index = -1, - length = array ? max(pluck(array, 'length')) : 0, - result = Array(length < 0 ? 0 : length); + function forInRight(object, callback, thisArg) { + var pairs = []; - while (++index < length) { - result[index] = pluck(array, index); + forIn(object, function(value, key) { + pairs.push(key, value); + }); + + var length = pairs.length; + callback = baseCreateCallback(callback, thisArg, 3); + while (length--) { + if (callback(pairs[length--], pairs[length], object) === false) { + break; + } } - return result; + return object; } /** - * Creates an object composed from arrays of `keys` and `values`. Provide - * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` - * or two arrays, one of `keys` and one of corresponding `values`. + * Iterates over own enumerable properties of an object, executing the callback + * for each property. The callback is bound to `thisArg` and invoked with three + * arguments; (value, key, object). Callbacks may exit iteration early by + * explicitly returning `false`. * * @static * @memberOf _ - * @alias object - * @category Arrays - * @param {Array} keys The array of keys. - * @param {Array} [values=[]] The array of values. - * @returns {Object} Returns an object composed of the given keys and - * corresponding values. + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. * @example * - * _.zipObject(['fred', 'barney'], [30, 40]); - * // => { 'fred': 30, 'barney': 40 } + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * console.log(key); + * }); + * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) */ - function zipObject(keys, values) { + function forOwn(object, callback, thisArg) { var index = -1, - length = keys ? keys.length : 0, - result = {}; + props = keys(object), + length = props.length; - if (!values && length && !isArray(keys[0])) { - values = []; - } + callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); while (++index < length) { - var key = keys[index]; - if (values) { - result[key] = values[index]; - } else if (key) { - result[key[0]] = key[1]; + var key = props[index]; + if (callback(object[key], key, object) === false) { + break; } } - return result; + return object; } - /*--------------------------------------------------------------------------*/ - /** - * Creates a function that executes `func`, with the `this` binding and - * arguments of the created function, only after being called `n` times. + * This method is like `_.forOwn` except that it iterates over elements + * of a `collection` in the opposite order. * * @static * @memberOf _ - * @category Functions - * @param {number} n The number of times the function must be called before - * `func` is executed. - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. * @example * - * var saves = ['profile', 'settings']; - * - * var done = _.after(saves.length, function() { - * console.log('Done saving!'); - * }); - * - * _.forEach(saves, function(type) { - * asyncSave({ 'type': type, 'complete': done }); + * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * console.log(key); * }); - * // => logs 'Done saving!', after all saves have completed + * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ - function after(n, func) { - if (!isFunction(func)) { - throw new TypeError; - } - return function() { - if (--n < 1) { - return func.apply(this, arguments); + function forOwnRight(object, callback, thisArg) { + var props = keys(object), + length = props.length; + + callback = baseCreateCallback(callback, thisArg, 3); + while (length--) { + var key = props[length]; + if (callback(object[key], key, object) === false) { + break; } - }; + } + return object; } /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. + * Creates a sorted array of property names of all enumerable properties, + * own and inherited, of `object` that have function values. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. + * @alias methods + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns an array of property names that have function values. * @example * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; - * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' + * _.functions(_); + * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); + function functions(object) { + var result = []; + forIn(object, function(value, key) { + if (isFunction(value)) { + result.push(key); + } + }); + return result.sort(); } /** - * Binds methods of an object to the object itself, overwriting the existing - * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * Checks if the specified property name exists as a direct property of `object`, + * instead of an inherited property. * * @static * @memberOf _ - * @category Functions - * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. - * @returns {Object} Returns `object`. + * @category Objects + * @param {Object} object The object to inspect. + * @param {string} key The name of the property to check. + * @returns {boolean} Returns `true` if key is a direct property, else `false`. * @example * - * var view = { - * 'label': 'docs', - * 'onClick': function() { console.log('clicked ' + this.label); } - * }; - * - * _.bindAll(view); - * jQuery('#docs').on('click', view.onClick); - * // => logs 'clicked docs', when the button is clicked + * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); + * // => true */ - function bindAll(object) { - var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object), - index = -1, - length = funcs.length; - - while (++index < length) { - var key = funcs[index]; - object[key] = createWrapper(object[key], 1, null, null, object); - } - return object; + function has(object, key) { + return object ? hasOwnProperty.call(object, key) : false; } /** - * Creates a function that, when called, invokes the method at `object[key]` - * and prepends any additional `bindKey` arguments to those provided to the bound - * function. This method differs from `_.bind` by allowing bound functions to - * reference methods that will be redefined or don't yet exist. - * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) - * for more details. + * Creates an object composed of the inverted keys and values of the given + * object. If the given object contains duplicate values, subsequent values + * will overwrite property assignments of previous values unless `multiValue` + * is `true`. * * @static * @memberOf _ - * @category Functions - * @param {Object} object The object the method belongs to. - * @param {string} key The key of the method. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. + * @category Objects + * @param {Object} object The object to invert. + * @param {boolean} [multiValue=false] Allow multiple values per key. + * @returns {Object} Returns the created inverted object. * @example * - * var object = { - * 'name': 'fred', - * 'greet': function(greeting) { - * return greeting + ' ' + this.name; - * } - * }; - * - * var func = _.bindKey(object, 'greet', 'hi'); - * func(); - * // => 'hi fred' + * _.invert({ 'first': 'fred', 'second': 'barney' }); + * // => { 'fred': 'first', 'barney': 'second' } * - * object.greet = function(greeting) { - * return greeting + 'ya ' + this.name + '!'; - * }; + * // without `multiValue` + * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }); + * // => { 'fred': 'third', 'barney': 'second' } * - * func(); - * // => 'hiya fred!' + * // with `multiValue` + * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); + * // => { 'fred': ['first', 'third'], 'barney': 'second' } */ - function bindKey(object, key) { - return arguments.length > 2 - ? createWrapper(key, 19, slice(arguments, 2), null, object) - : createWrapper(key, 3, null, null, object); + function invert(object, multiValue) { + var index = -1, + props = keys(object), + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index], + value = object[key]; + + if (multiValue && hasOwnProperty.call(result, value)) { + if (typeof result[value] == 'string') { + result[value] = [result[value]]; + } + result[value].push(key); + } + else { + result[value] = key; + } + } + return result; } /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. + * Checks if `value` is an array. * * @static * @memberOf _ - * @category Functions - * @param {...Function} [func] Functions to compose. - * @returns {Function} Returns the new composed function. + * @type Function + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is an array, else `false`. * @example * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; - * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; - * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; + * (function() { return _.isArray(arguments); })(); + * // => false * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' + * _.isArray([1, 2, 3]); + * // => true */ - function compose() { - var funcs = arguments, - length = funcs.length; - - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError; - } - } - return function() { - var args = arguments, - length = funcs.length; - - while (length--) { - args = [funcs[length].apply(this, args)]; - } - return args[0]; - }; - } + var isArray = nativeIsArray || function(value) { + return value && typeof value == 'object' && typeof value.length == 'number' && + toString.call(value) == arrayClass || false; + }; /** - * Creates a function which accepts one or more arguments of `func` that when - * invoked either executes `func` returning its result, if all `func` arguments - * have been provided, or returns a function that accepts one or more of the - * remaining `func` arguments, and so on. The arity of `func` can be specified - * if `func.length` is not sufficient. + * Checks if `value` is a boolean value. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to curry. - * @param {number} [arity=func.length] The arity of `func`. - * @returns {Function} Returns the new curried function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. * @example * - * var curried = _.curry(function(a, b, c) { - * console.log(a + b + c); - * }); - * - * curried(1)(2)(3); - * // => 6 - * - * curried(1, 2)(3); - * // => 6 - * - * curried(1, 2, 3); - * // => 6 + * _.isBoolean(null); + * // => false */ - function curry(func, arity) { - arity = typeof arity == 'number' ? arity : (+arity || func.length); - return createWrapper(func, 4, null, null, null, arity); + function isBoolean(value) { + return value === true || value === false || + value && typeof value == 'object' && toString.call(value) == boolClass || false; } /** - * Creates a function that will delay the execution of `func` until after - * `wait` milliseconds have elapsed since the last time it was invoked. - * 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 will return the result of the last `func` call. - * - * Note: If `leading` and `trailing` options are `true` `func` will be called - * on the trailing edge of the timeout only if the the debounced function is - * invoked more than once during the `wait` timeout. + * Checks if `value` is a date. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to debounce. - * @param {number} wait The number of milliseconds to delay. - * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout. - * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a date, else `false`. * @example * - * // avoid costly calculations while the window size is in flux - * var lazyLayout = _.debounce(calculateLayout, 150); - * jQuery(window).on('resize', lazyLayout); - * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls - * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * }); - * - * // ensure `batchLog` is executed once after 1 second of debounced calls - * var source = new EventSource('/stream'); - * source.addEventListener('message', _.debounce(batchLog, 250, { - * 'maxWait': 1000 - * }, false); + * _.isDate(new Date); + * // => true */ - function debounce(func, wait, options) { - var args, - maxTimeoutId, - result, - stamp, - thisArg, - timeoutId, - trailingCall, - lastCalled = 0, - maxWait = false, - trailing = true; - - if (!isFunction(func)) { - throw new TypeError; - } - wait = nativeMax(0, wait) || 0; - if (options === true) { - var leading = true; - trailing = false; - } else if (isObject(options)) { - leading = options.leading; - maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0); - trailing = 'trailing' in options ? options.trailing : trailing; - } - var delayed = function() { - var remaining = wait - (now() - stamp); - if (remaining <= 0) { - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } - } else { - timeoutId = setTimeout(delayed, remaining); - } - }; - - var maxDelayed = function() { - if (timeoutId) { - clearTimeout(timeoutId); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (trailing || (maxWait !== wait)) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } - }; - - return function() { - args = arguments; - stamp = now(); - thisArg = this; - trailingCall = trailing && (timeoutId || !leading); - - if (maxWait === false) { - var leadingCall = leading && !timeoutId; - } else { - if (!maxTimeoutId && !leading) { - lastCalled = stamp; - } - var remaining = maxWait - (stamp - lastCalled), - isCalled = remaining <= 0; - - if (isCalled) { - if (maxTimeoutId) { - maxTimeoutId = clearTimeout(maxTimeoutId); - } - lastCalled = stamp; - result = func.apply(thisArg, args); - } - else if (!maxTimeoutId) { - maxTimeoutId = setTimeout(maxDelayed, remaining); - } - } - if (isCalled && timeoutId) { - timeoutId = clearTimeout(timeoutId); - } - else if (!timeoutId && wait !== maxWait) { - timeoutId = setTimeout(delayed, wait); - } - if (leadingCall) { - isCalled = true; - result = func.apply(thisArg, args); - } - if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - return result; - }; + function isDate(value) { + return value && typeof value == 'object' && toString.call(value) == dateClass || false; } /** - * Defers executing the `func` function until the current call stack has cleared. - * Additional arguments will be provided to `func` when it is invoked. + * Checks if `value` is a DOM element. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to defer. - * @param {...*} [arg] Arguments to invoke the function with. - * @returns {number} Returns the timer id. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. * @example * - * _.defer(function(text) { console.log(text); }, 'deferred'); - * // logs 'deferred' after one or more milliseconds + * _.isElement(document.body); + * // => true */ - function defer(func) { - if (!isFunction(func)) { - throw new TypeError; - } - var args = slice(arguments, 1); - return setTimeout(function() { func.apply(undefined, args); }, 1); + function isElement(value) { + return value && typeof value == 'object' && value.nodeType === 1 && + (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value)) || false; + } + // fallback for environments without DOM support + if (!support.dom) { + isElement = function(value) { + return value && typeof value == 'object' && value.nodeType === 1 && + !isPlainObject(value) || false; + }; } /** - * Executes the `func` function after `wait` milliseconds. Additional arguments - * will be provided to `func` when it is invoked. + * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a + * length of `0` and objects with no own enumerable properties are considered + * "empty". * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay execution. - * @param {...*} [arg] Arguments to invoke the function with. - * @returns {number} Returns the timer id. + * @category Objects + * @param {Array|Object|string} value The value to inspect. + * @returns {boolean} Returns `true` if the `value` is empty, else `false`. * @example * - * _.delay(function(text) { console.log(text); }, 1000, 'later'); - * // => logs 'later' after one second + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({}); + * // => true + * + * _.isEmpty(''); + * // => true */ - function delay(func, wait) { - if (!isFunction(func)) { - throw new TypeError; + function isEmpty(value) { + var result = true; + if (!value) { + return result; } - var args = slice(arguments, 2); - return setTimeout(function() { func.apply(undefined, args); }, wait); + var className = toString.call(value), + length = value.length; + + if ((className == arrayClass || className == stringClass || + (support.argsClass ? className == argsClass : isArguments(value))) || + (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + return !length; + } + forOwn(value, function() { + return (result = false); + }); + return result; } /** - * Creates a function that memoizes the result of `func`. If `resolver` is - * provided it will be used to determine the cache key for storing the result - * based on the arguments provided to the memoized function. By default, the - * first argument provided to the memoized function is used as the cache key. - * The `func` is executed with the `this` binding of the memoized function. - * The result cache is exposed as the `cache` property on the memoized function. + * Performs a deep comparison between two values to determine if they are + * equivalent to each other. If a callback is provided it will be executed + * to compare values. If the callback returns `undefined` comparisons will + * be handled by the method instead. The callback is bound to `thisArg` and + * invoked with two arguments; (a, b). * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] A function used to resolve the cache key. - * @returns {Function} Returns the new memoizing function. + * @category Objects + * @param {*} a The value to compare. + * @param {*} b The other value to compare. + * @param {Function} [callback] The function to customize comparing values. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * - * var fibonacci = _.memoize(function(n) { - * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); - * }); + * var object = { 'name': 'fred' }; + * var copy = { 'name': 'fred' }; * - * fibonacci(9) - * // => 34 + * object == copy; + * // => false * - * var data = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; + * _.isEqual(object, copy); + * // => true * - * // modifying the result cache - * var get = _.memoize(function(name) { return data[name]; }, _.identity); - * get('pebbles'); - * // => { 'name': 'pebbles', 'age': 1 } + * var words = ['hello', 'goodbye']; + * var otherWords = ['hi', 'goodbye']; * - * get.cache.pebbles.name = 'penelope'; - * get('pebbles'); - * // => { 'name': 'penelope', 'age': 1 } + * _.isEqual(words, otherWords, function(a, b) { + * var reGreet = /^(?:hello|hi)$/i, + * aGreet = _.isString(a) && reGreet.test(a), + * bGreet = _.isString(b) && reGreet.test(b); + * + * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; + * }); + * // => true */ - function memoize(func, resolver) { - if (!isFunction(func)) { - throw new TypeError; - } - var memoized = function() { - var cache = memoized.cache, - key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0]; - - return hasOwnProperty.call(cache, key) - ? cache[key] - : (cache[key] = func.apply(this, arguments)); - } - memoized.cache = {}; - return memoized; + function isEqual(a, b, callback, thisArg) { + return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2)); } /** - * Creates a function that is restricted to execute `func` once. Repeat calls to - * the function will return the value of the first call. The `func` is executed - * with the `this` binding of the created function. + * Checks if `value` is, or can be coerced to, a finite number. + * + * Note: This is not the same as native `isFinite` which will return true for + * booleans and empty strings. See the [ES5 spec](http://es5.github.io/#x15.1.2.5) + * for more details. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is finite, else `false`. * @example * - * var initialize = _.once(createApplication); - * initialize(); - * initialize(); - * // `initialize` executes `createApplication` once + * _.isFinite(-101); + * // => true + * + * _.isFinite('10'); + * // => true + * + * _.isFinite(true); + * // => false + * + * _.isFinite(''); + * // => false + * + * _.isFinite(Infinity); + * // => false */ - function once(func) { - var ran, - result; - - if (!isFunction(func)) { - throw new TypeError; - } - return function() { - if (ran) { - return result; - } - ran = true; - result = func.apply(this, arguments); - - // clear the `func` variable so the function may be garbage collected - func = null; - return result; - }; + function isFinite(value) { + return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); } /** - * Creates a function that, when called, invokes `func` with any additional - * `partial` arguments prepended to those provided to the new function. This - * method is similar to `_.bind` except it does **not** alter the `this` binding. + * Checks if `value` is a function. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to partially apply arguments to. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new partially applied function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a function, else `false`. * @example * - * var greet = function(greeting, name) { return greeting + ' ' + name; }; - * var hi = _.partial(greet, 'hi'); - * hi('fred'); - * // => 'hi fred' + * _.isFunction(_); + * // => true */ - function partial(func) { - return createWrapper(func, 16, slice(arguments, 1)); + function isFunction(value) { + return typeof value == 'function'; + } + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return typeof value == 'function' && toString.call(value) == funcClass; + }; } /** - * This method is like `_.partial` except that `partial` arguments are - * appended to those provided to the new function. + * Checks if `value` is the language type of Object. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to partially apply arguments to. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new partially applied function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is an object, else `false`. * @example * - * var defaultsDeep = _.partialRight(_.merge, _.defaults); - * - * var options = { - * 'variable': 'data', - * 'imports': { 'jq': $ } - * }; - * - * defaultsDeep(options, _.templateSettings); + * _.isObject({}); + * // => true * - * options.variable - * // => 'data' + * _.isObject([1, 2, 3]); + * // => true * - * options.imports - * // => { '_': _, 'jq': $ } + * _.isObject(1); + * // => false */ - function partialRight(func) { - return createWrapper(func, 32, null, slice(arguments, 1)); + function isObject(value) { + // check if the value is the ECMAScript language type of Object + // http://es5.github.io/#x8 + // and avoid a V8 bug + // http://code.google.com/p/v8/issues/detail?id=2291 + return !!(value && objectTypes[typeof value]); } /** - * Creates a function that, when executed, will only call the `func` function - * at most once per every `wait` milliseconds. 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 will - * return the result of the last `func` call. + * Checks if `value` is `NaN`. * - * Note: If `leading` and `trailing` options are `true` `func` will be called - * on the trailing edge of the timeout only if the the throttled function is - * invoked more than once during the `wait` timeout. + * Note: This is not the same as native `isNaN` which will return `true` for + * `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) + * for more details. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to throttle. - * @param {number} wait The number of milliseconds to throttle executions to. - * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. - * @returns {Function} Returns the new throttled function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. * @example * - * // avoid excessively updating the position while scrolling - * var throttled = _.throttle(updatePosition, 100); - * jQuery(window).on('scroll', throttled); + * _.isNaN(NaN); + * // => true * - * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes - * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { - * 'trailing': false - * })); + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false */ - function throttle(func, wait, options) { - var leading = true, - trailing = true; - - if (!isFunction(func)) { - throw new TypeError; - } - if (options === false) { - leading = false; - } else if (isObject(options)) { - leading = 'leading' in options ? options.leading : leading; - trailing = 'trailing' in options ? options.trailing : trailing; - } - debounceOptions.leading = leading; - debounceOptions.maxWait = wait; - debounceOptions.trailing = trailing; - - return debounce(func, wait, debounceOptions); + function isNaN(value) { + // `NaN` as a primitive is the only value that is not equal to itself + // (perform the [[Class]] check first to avoid errors with some host objects in IE) + return isNumber(value) && value != +value; } /** - * Creates a function that provides `value` to the wrapper function as its - * first argument. Additional arguments provided to the function are appended - * to those provided to the wrapper function. The wrapper is executed with - * the `this` binding of the created function. + * Checks if `value` is `null`. * * @static * @memberOf _ - * @category Functions - * @param {*} value The value to wrap. - * @param {Function} wrapper The wrapper function. - * @returns {Function} Returns the new function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. * @example * - * var p = _.wrap(_.escape, function(func, text) { - * return '

    ' + func(text) + '

    '; - * }); + * _.isNull(null); + * // => true * - * p('Fred, Wilma, & Pebbles'); - * // => '

    Fred, Wilma, & Pebbles

    ' + * _.isNull(undefined); + * // => false */ - function wrap(value, wrapper) { - return createWrapper(wrapper, 16, [value]); + function isNull(value) { + return value === null; } - /*--------------------------------------------------------------------------*/ - /** - * Creates a function that returns `value`. + * Checks if `value` is a number. + * + * Note: `NaN` is considered a number. See the [ES5 spec](http://es5.github.io/#x8.5) + * for more details. * * @static * @memberOf _ - * @category Utilities - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a number, else `false`. * @example * - * var object = { 'name': 'fred' }; - * var getter = _.constant(object); - * getter() === object; + * _.isNumber(8.4 * 5); * // => true */ - function constant(value) { - return function() { - return value; - }; + function isNumber(value) { + return typeof value == 'number' || + value && typeof value == 'object' && toString.call(value) == numberClass || false; } /** - * Produces a callback bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. + * Checks if `value` is an object created by the `Object` constructor. * * @static * @memberOf _ - * @category Utilities - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * function Shape() { + * this.x = 0; + * this.y = 0; + * } * - * // wrap to create custom callback shorthands - * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { - * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); - * return !match ? func(callback, thisArg) : function(object) { - * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; - * }; - * }); + * _.isPlainObject(new Shape); + * // => false * - * _.filter(characters, 'age__gt38'); - * // => [{ 'name': 'fred', 'age': 40 }] + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true */ - function createCallback(func, thisArg, argCount) { - var type = typeof func; - if (func == null || type == 'function') { - return baseCreateCallback(func, thisArg, argCount); + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { + return false; } - // handle "_.pluck" and "_.where" style callback shorthands - return type != 'object' ? property(func) : match(func); - } + var valueOf = value.valueOf, + objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + + return objProto + ? (value == objProto || getPrototypeOf(value) == objProto) + : shimIsPlainObject(value); + }; /** - * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their - * corresponding HTML entities. - * - * Note: No other characters are escaped. To escape additional characters - * use a third-party library like [_he_](http://mths.be/he). + * Checks if `value` is a regular expression. * * @static * @memberOf _ - * @category Utilities - * @param {string} string The string to escape. - * @returns {string} Returns the escaped string. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. * @example * - * _.escape('Fred, Wilma, & Pebbles'); - * // => 'Fred, Wilma, & Pebbles' + * _.isRegExp(/fred/); + * // => true */ - function escape(string) { - return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); + function isRegExp(value) { + return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false; } /** - * This method returns the first argument provided to it. + * Checks if `value` is a string. * * @static * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a string, else `false`. * @example * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; + * _.isString('fred'); * // => true */ - function identity(value) { - return value; + function isString(value) { + return typeof value == 'string' || + value && typeof value == 'object' && toString.call(value) == stringClass || false; } /** - * Creates a "_.where" style function, which performs a deep comparison - * between a given object and the `props` object, returning `true` if the - * given object has equivalent property values, else `false`. + * Checks if `value` is `undefined`. * * @static * @memberOf _ - * @category Utilities - * @param {Object} props The object of property values to match. - * @returns {Function} Returns the new function. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. * @example * - * var characters = [ - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'barney', 'age': 36 } - * ]; - * - * var matchAge = _.match({ 'age': 36 }); - * - * _.filter(characters, matchAge); - * // => [{ 'name': 'barney', 'age': 36 }] - * - * _.find(characters, matchAge); - * // => { 'name': 'barney', 'age': 36 } + * _.isUndefined(void 0); + * // => true */ - function match(source) { - source || (source = {}); - - var props = keys(source), - key = props[0], - a = source[key]; - - // fast path the common case of providing an object with a single - // property containing a primitive value - if (props.length == 1 && a === a && !isObject(a)) { - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = baseIsEqual(object[props[length]], source[props[length]], null, true))) { - break; - } - } - return result; - }; + function isUndefined(value) { + return typeof value == 'undefined'; } /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. + * Creates an array composed of the own enumerable property names of an object. * * @static * @memberOf _ - * @category Utilities - * @param {Function|Object} [object=lodash] object The destination object. - * @param {Object} source The object of functions to add. - * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added are chainable. + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns an array of property names. * @example * - * function capitalize(string) { - * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); - * } - * - * _.mixin({ 'capitalize': capitalize }); - * _.capitalize('fred'); - * // => 'Fred' - * - * _('fred').capitalize().value(); - * // => 'Fred' - * - * _.mixin({ 'capitalize': capitalize }, { 'chain': false }); - * _('fred').capitalize(); - * // => 'Fred' + * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); + * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) */ - function mixin(object, source, options) { - var chain = true, - methodNames = source && functions(source); - - if (!source || (!options && !methodNames.length)) { - if (options == null) { - options = source; - } - source = object; - object = lodash; - methodNames = functions(source); - } - if (options === false) { - chain = false; - } else if (isObject(options) && 'chain' in options) { - chain = options.chain; + var keys = !nativeKeys ? shimKeys : function(object) { + if (!isObject(object)) { + return []; } - var index = -1, - isFunc = isFunction(object), - length = methodNames ? methodNames.length : 0; - - while (++index < length) { - var methodName = methodNames[index], - func = object[methodName] = source[methodName]; - - if (isFunc) { - object.prototype[methodName] = (function(func) { - return function() { - var chainAll = this.__chain__, - value = this.__wrapped__, - args = [value]; - - push.apply(args, arguments); - var result = func.apply(object, args); - if (chain || chainAll) { - if (value === result && isObject(result)) { - return this; - } - result = new object(result); - result.__chain__ = chainAll; - } - return result; - }; - }(func)); - } + if ((support.enumPrototypes && typeof object == 'function') || + (support.nonEnumArgs && object.length && isArguments(object))) { + return shimKeys(object); } - } + return nativeKeys(object); + }; /** - * Reverts the '_' variable to its previous value and returns a reference to - * the `lodash` function. + * Creates an object with the same keys as `object` and values generated by + * running each own enumerable property of `object` through the callback. + * The callback is bound to `thisArg` and invoked with three arguments; + * (value, key, object). * - * @static - * @memberOf _ - * @category Utilities - * @returns {Function} Returns the `lodash` function. - * @example + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. * - * var lodash = _.noConflict(); - */ - function noConflict() { - context._ = oldDash; - return this; - } - - /** - * A no-operation function. + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @category Utilities + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns a new object with values of the results of each `callback` execution. * @example * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true - */ - function noop() { - // no operation performed + * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); + * // => { 'a': 3, 'b': 6, 'c': 9 } + * + * var characters = { + * 'fred': { 'name': 'fred', 'age': 40 }, + * 'pebbles': { 'name': 'pebbles', 'age': 1 } + * }; + * + * // using "_.pluck" callback shorthand + * _.mapValues(characters, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } + */ + function mapValues(object, callback, thisArg) { + var result = {}; + callback = lodash.createCallback(callback, thisArg, 3); + + forOwn(object, function(value, key, object) { + result[key] = callback(value, key, object); + }); + return result; + } + + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined` into the destination object. Subsequent sources + * will overwrite property assignments of previous sources. If a callback is + * provided it will be executed to produce the merged values of the destination + * and source properties. If the callback returns `undefined` merging will + * be handled by the method instead. The callback is bound to `thisArg` and + * invoked with two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {...Object} [source] The source objects. + * @param {Function} [callback] The function to customize merging properties. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the destination object. + * @example + * + * var names = { + * 'characters': [ + * { 'name': 'barney' }, + * { 'name': 'fred' } + * ] + * }; + * + * var ages = { + * 'characters': [ + * { 'age': 36 }, + * { 'age': 40 } + * ] + * }; + * + * _.merge(names, ages); + * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } + * + * var food = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var otherFood = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(food, otherFood, function(a, b) { + * return _.isArray(a) ? a.concat(b) : undefined; + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + */ + function merge(object) { + var args = arguments, + length = 2; + + if (!isObject(object)) { + return object; + } + // allows working with `_.reduce` and `_.reduceRight` without using + // their `index` and `collection` arguments + if (typeof args[2] != 'number') { + length = args.length; + } + if (length > 3 && typeof args[length - 2] == 'function') { + var callback = baseCreateCallback(args[--length - 1], args[length--], 2); + } else if (length > 2 && typeof args[length - 1] == 'function') { + callback = args[--length]; + } + var sources = slice(arguments, 1, length), + index = -1, + stackA = getArray(), + stackB = getArray(); + + while (++index < length) { + baseMerge(object, sources[index], callback, stackA, stackB); + } + releaseArray(stackA); + releaseArray(stackB); + return object; + } + + /** + * Creates a shallow clone of `object` excluding the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a callback is provided it will be executed for each + * property of `object` omitting the properties the callback returns truey + * for. The callback is bound to `thisArg` and invoked with three arguments; + * (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|...string|string[]} [callback] The properties to omit or the + * function called per iteration. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object without the omitted properties. + * @example + * + * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); + * // => { 'name': 'fred' } + * + * _.omit({ 'name': 'fred', 'age': 40 }, function(value) { + * return typeof value == 'number'; + * }); + * // => { 'name': 'fred' } + */ + function omit(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var props = []; + forIn(object, function(value, key) { + props.push(key); + }); + props = baseDifference(props, baseFlatten(arguments, true, false, 1)); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + result[key] = object[key]; + } + } else { + callback = lodash.createCallback(callback, thisArg, 3); + forIn(object, function(value, key, object) { + if (!callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + + /** + * Creates a two dimensional array of an object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns new array of key-value pairs. + * @example + * + * _.pairs({ 'barney': 36, 'fred': 40 }); + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + */ + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; + } + + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a callback is provided it will be executed for each + * property of `object` picking the properties the callback returns truey + * for. The callback is bound to `thisArg` and invoked with three arguments; + * (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|...string|string[]} [callback] The function called per + * iteration or property names to pick, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. + * @example + * + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); + * // => { 'name': 'fred' } + * + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'fred' } + */ + function pick(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var index = -1, + props = baseFlatten(arguments, true, false, 1), + length = isObject(object) ? props.length : 0; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = lodash.createCallback(callback, thisArg, 3); + forIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + + /** + * An alternative to `_.reduce` this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable properties through a callback, with each callback execution + * potentially mutating the `accumulator` object. The callback is bound to + * `thisArg` and invoked with four arguments; (accumulator, value, key, object). + * Callbacks may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Array|Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the accumulated value. + * @example + * + * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) { + * num *= num; + * if (num % 2) { + * return result.push(num) < 3; + * } + * }); + * // => [1, 9, 25] + * + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { + * result[key] = num * 3; + * }); + * // => { 'a': 3, 'b': 6, 'c': 9 } + */ + function transform(object, callback, accumulator, thisArg) { + var isArr = isArray(object); + if (accumulator == null) { + if (isArr) { + accumulator = []; + } else { + var ctor = object && object.constructor, + proto = ctor && ctor.prototype; + + accumulator = baseCreate(proto); + } + } + if (callback) { + callback = lodash.createCallback(callback, thisArg, 4); + (isArr ? baseEach : forOwn)(object, function(value, index, object) { + return callback(accumulator, value, index, object); + }); + } + return accumulator; + } + + /** + * Creates an array composed of the own enumerable property values of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns an array of property values. + * @example + * + * _.values({ 'one': 1, 'two': 2, 'three': 3 }); + * // => [1, 2, 3] (property order is not guaranteed across environments) + */ + function values(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their + * corresponding HTML entities. + * + * Note: No other characters are escaped. To escape additional characters + * use a third-party library like [_he_](http://mths.be/he). + * + * @static + * @memberOf _ + * @category Strings + * @param {string} string The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('Fred, Wilma, & Pebbles'); + * // => 'Fred, Wilma, & Pebbles' + */ + function escape(string) { + return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); + } + + /** + * A micro-templating method that handles arbitrary delimiters, preserves + * whitespace, and correctly escapes quotes within interpolated code. + * + * Note: In the development build, `_.template` utilizes sourceURLs for easier + * debugging. See [HTML5 Rocks' article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl). + * + * For more information on precompiling templates see + * [Lo-Dash's custom builds documentation](http://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](http://developer.chrome.com/stable/extensions/sandboxingEval.html). + * + * @static + * @memberOf _ + * @category Strings + * @param {string} text The template text. + * @param {Object} data The data object used to populate the text. + * @param {Object} [options] The options object. + * @param {RegExp} [options.escape] The "escape" delimiter. + * @param {RegExp} [options.evaluate] The "evaluate" delimiter. + * @param {Object} [options.imports] An object to import into the template as local variables. + * @param {RegExp} [options.interpolate] The "interpolate" delimiter. + * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. + * @param {string} [options.variable] The data object variable name. + * @returns {Function|string} Returns a compiled function when no `data` object + * is given, else it returns the interpolated text. + * @example + * + * // using the "interpolate" delimiter to create a compiled template + * var compiled = _.template('hello <%= name %>'); + * compiled({ 'name': 'fred' }); + * // => 'hello fred' + * + * // using the "escape" delimiter to escape HTML in data property values + * _.template('<%- value %>', { 'value': ' +
    @@ -51,14 +52,11 @@ Function.prototype._method = function() {}; // allow bypassing native checks - setProperty(Function.prototype, 'toString', (function() { - function toString() { - return this.toString !== toString ? this.toString() : func.call(this); - } - var func = Function.prototype.toString; - setProperty(Function.prototype, '_toString', func); - return toString; - }())); + var _toString = Function.prototype.toString; + setProperty(Function.prototype, '_toString', _toString); + setProperty(Function.prototype, 'toString', function() { + return this === Set ? this.toString() : _toString.call(this); + }); // set bad shims setProperty(Array, '_isArray', Array.isArray); @@ -91,7 +89,6 @@ setProperty(String.prototype, '_trimRight', String.prototype.trimRight); setProperty(String.prototype, 'trimRight', String.prototype._trimRight ? function() {} : String); - setProperty(window, '_Set', window.Set); setProperty(window, 'WinRTError', Error); setProperty(document, '_createDocumentFragment', document.createDocumentFragment); @@ -129,11 +126,6 @@ } else { delete Object.keys; } - if (window._Set) { - setProperty(window, 'Set', _Set); - } else { - setProperty(window, 'Set', undefined); - } for (var key in { 'contains': true, 'trim': true, @@ -164,11 +156,11 @@ delete Object._keys; } - addBizarroMethods(); - // load Lo-Dash and expose it to the bad extensions/shims - document.write(' diff --git a/test/index.html b/test/index.html index 76190b887a..89bb9cb2d6 100644 --- a/test/index.html +++ b/test/index.html @@ -159,12 +159,6 @@ " + ' ); iDoc.close(); - test("isElement", function() { + test('isElement', function() { ok(!_.isElement('div'), 'strings are not dom elements'); - ok(_.isElement($('html')[0]), 'the html tag is a DOM element'); + ok(_.isElement(document.body), 'the body tag is a DOM element'); ok(_.isElement(iElement), 'even from another frame'); }); - test("isArguments", function() { + test('isArguments', function() { var args = (function(){ return arguments; })(1, 2, 3); ok(!_.isArguments('string'), 'a string is not an arguments object'); ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); @@ -416,10 +431,10 @@ $(document).ready(function() { ok(_.isArguments(iArguments), 'even from another frame'); }); - test("isObject", function() { + test('isObject', function() { ok(_.isObject(arguments), 'the arguments object is object'); ok(_.isObject([1, 2, 3]), 'and arrays'); - ok(_.isObject($('html')[0]), 'and DOM element'); + ok(_.isObject(document.body), 'and DOM element'); ok(_.isObject(iElement), 'even from another frame'); ok(_.isObject(function () {}), 'and functions'); ok(_.isObject(iFunction), 'even from another frame'); @@ -431,23 +446,23 @@ $(document).ready(function() { ok(_.isObject(new String('string')), 'but new String()'); }); - test("isArray", function() { + test('isArray', function() { ok(!_.isArray(undefined), 'undefined vars are not arrays'); ok(!_.isArray(arguments), 'the arguments object is not an array'); ok(_.isArray([1, 2, 3]), 'but arrays are'); ok(_.isArray(iArray), 'even from another frame'); }); - test("isString", function() { - var obj = new String("I am a string object"); + test('isString', function() { + var obj = new String('I am a string object'); ok(!_.isString(document.body), 'the document body is not a string'); ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); ok(_.isString(iString), 'even from another frame'); - ok(_.isString("I am a string literal"), 'string literals are'); + ok(_.isString('I am a string literal'), 'string literals are'); ok(_.isString(obj), 'so are String objects'); }); - test("isNumber", function() { + test('isNumber', function() { ok(!_.isNumber('string'), 'a string is not a number'); ok(!_.isNumber(arguments), 'the arguments object is not a number'); ok(!_.isNumber(undefined), 'undefined is not a number'); @@ -458,11 +473,11 @@ $(document).ready(function() { ok(!_.isNumber('1'), 'numeric strings are not numbers'); }); - test("isBoolean", function() { + test('isBoolean', function() { ok(!_.isBoolean(2), 'a number is not a boolean'); - ok(!_.isBoolean("string"), 'a string is not a boolean'); - ok(!_.isBoolean("false"), 'the string "false" is not a boolean'); - ok(!_.isBoolean("true"), 'the string "true" is not a boolean'); + ok(!_.isBoolean('string'), 'a string is not a boolean'); + ok(!_.isBoolean('false'), 'the string "false" is not a boolean'); + ok(!_.isBoolean('true'), 'the string "true" is not a boolean'); ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); ok(!_.isBoolean(undefined), 'undefined is not a boolean'); ok(!_.isBoolean(NaN), 'NaN is not a boolean'); @@ -472,7 +487,7 @@ $(document).ready(function() { ok(_.isBoolean(iBoolean), 'even from another frame'); }); - test("isFunction", function() { + test('isFunction', function() { ok(!_.isFunction(undefined), 'undefined vars are not functions'); ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); ok(!_.isFunction('moe'), 'strings are not functions'); @@ -481,36 +496,36 @@ $(document).ready(function() { ok(_.isFunction(function(){}), 'even anonymous ones'); }); - test("isDate", function() { + test('isDate', function() { ok(!_.isDate(100), 'numbers are not dates'); ok(!_.isDate({}), 'objects are not dates'); ok(_.isDate(new Date()), 'but dates are'); ok(_.isDate(iDate), 'even from another frame'); }); - test("isRegExp", function() { + test('isRegExp', function() { ok(!_.isRegExp(_.identity), 'functions are not RegExps'); ok(_.isRegExp(/identity/), 'but RegExps are'); ok(_.isRegExp(iRegExp), 'even from another frame'); }); - test("isFinite", function() { - ok(!_.isFinite(undefined), 'undefined is not Finite'); - ok(!_.isFinite(null), 'null is not Finite'); - ok(!_.isFinite(NaN), 'NaN is not Finite'); - ok(!_.isFinite(Infinity), 'Infinity is not Finite'); - ok(!_.isFinite(-Infinity), '-Infinity is not Finite'); + test('isFinite', function() { + ok(!_.isFinite(undefined), 'undefined is not finite'); + ok(!_.isFinite(null), 'null is not finite'); + ok(!_.isFinite(NaN), 'NaN is not finite'); + ok(!_.isFinite(Infinity), 'Infinity is not finite'); + ok(!_.isFinite(-Infinity), '-Infinity is not finite'); ok(_.isFinite('12'), 'Numeric strings are numbers'); ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); ok(!_.isFinite(''), 'Empty strings are not numbers'); var obj = new Number(5); ok(_.isFinite(obj), 'Number instances can be finite'); - ok(_.isFinite(0), '0 is Finite'); - ok(_.isFinite(123), 'Ints are Finite'); - ok(_.isFinite(-12.44), 'Floats are Finite'); + ok(_.isFinite(0), '0 is finite'); + ok(_.isFinite(123), 'Ints are finite'); + ok(_.isFinite(-12.44), 'Floats are finite'); }); - test("isNaN", function() { + test('isNaN', function() { ok(!_.isNaN(undefined), 'undefined is not NaN'); ok(!_.isNaN(null), 'null is not NaN'); ok(!_.isNaN(0), '0 is not NaN'); @@ -519,14 +534,14 @@ $(document).ready(function() { ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); }); - test("isNull", function() { + test('isNull', function() { ok(!_.isNull(undefined), 'undefined is not null'); ok(!_.isNull(NaN), 'NaN is not null'); ok(_.isNull(null), 'but null is'); ok(_.isNull(iNull), 'even from another frame'); }); - test("isUndefined", function() { + test('isUndefined', function() { ok(!_.isUndefined(1), 'numbers are defined'); ok(!_.isUndefined(null), 'null is defined'); ok(!_.isUndefined(false), 'false is defined'); @@ -537,8 +552,8 @@ $(document).ready(function() { }); if (window.ActiveXObject) { - test("IE host objects", function() { - var xml = new ActiveXObject("Msxml2.DOMDocument.3.0"); + test('IE host objects', function() { + var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); ok(!_.isNumber(xml)); ok(!_.isBoolean(xml)); ok(!_.isNaN(xml)); @@ -548,12 +563,12 @@ $(document).ready(function() { }); } - test("tap", function() { + test('tap', function() { var intercepted = null; var interceptor = function(obj) { intercepted = obj; }; var returned = _.tap(1, interceptor); - equal(intercepted, 1, "passes tapped object to interceptor"); - equal(returned, 1, "returns tapped object"); + equal(intercepted, 1, 'passes tapped object to interceptor'); + equal(returned, 1, 'returns tapped object'); returned = _([1,2,3]).chain(). map(function(n){ return n * 2; }). @@ -564,14 +579,22 @@ $(document).ready(function() { }); test("has", function () { - var obj = {foo: "bar", func: function () {} }; - ok (_.has(obj, "foo"), "has() checks that the object has a property."); - ok (_.has(obj, "baz") == false, "has() returns false if the object doesn't have the property."); - ok (_.has(obj, "func"), "has() works for functions too."); - obj.hasOwnProperty = null; - ok (_.has(obj, "foo"), "has() works even when the hasOwnProperty method is deleted."); - var child = {}; - child.prototype = obj; - ok (_.has(child, "foo") == false, "has() does not check the prototype chain for a property.") + var obj = {foo: "bar", func: function () {} }; + ok(_.has(obj, "foo"), "has() checks that the object has a property."); + ok(_.has(obj, "baz") == false, "has() returns false if the object doesn't have the property."); + ok(_.has(obj, "func"), "has() works for functions too."); + obj.hasOwnProperty = null; + ok(_.has(obj, "foo"), "has() works even when the hasOwnProperty method is deleted."); + var child = {}; + child.prototype = obj; + ok(_.has(child, "foo") == false, "has() does not check the prototype chain for a property.") }); -}); + + test("matches", function() { + var moe = {name: 'Moe Howard', hair: true}, + curly = {name: 'Curly Howard', hair: false}, + stooges = [moe, curly]; + ok(_.find(stooges, _.matches({hair: false})) === curly, "returns a predicate that can be used by finding functions.") + ok(_.find(stooges, _.matches(moe)) === moe, "can be used to locate an object exists in a collection.") + }) +})(); diff --git a/vendor/underscore/test/utility.js b/vendor/underscore/test/utility.js index 52c5495fbd..513b8341af 100644 --- a/vendor/underscore/test/utility.js +++ b/vendor/underscore/test/utility.js @@ -1,8 +1,8 @@ -$(document).ready(function() { +(function() { var templateSettings; - module("Utility", { + module('Utility', { setup: function() { templateSettings = _.clone(_.templateSettings); @@ -14,54 +14,69 @@ $(document).ready(function() { }); - test("#750 - Return _ instance.", 2, function() { + test('#750 - Return _ instance.', 2, function() { var instance = _([]); ok(_(instance) === instance); ok(new _(instance) === instance); }); - test("identity", function() { + test('identity', function() { var moe = {name : 'moe'}; equal(_.identity(moe), moe, 'moe is the same as his identity'); }); - test("random", function() { + test('constant', function() { + var moe = {name : 'moe'}; + equal(_.constant(moe)(), moe, 'should create a function that returns moe'); + }); + + test('property', function() { + var moe = {name : 'moe'}; + equal(_.property('name')(moe), 'moe', 'should return the property with the given name'); + }); + + test('random', function() { var array = _.range(1000); var min = Math.pow(2, 31); var max = Math.pow(2, 62); ok(_.every(array, function() { return _.random(min, max) >= min; - }), "should produce a random number greater than or equal to the minimum number"); + }), 'should produce a random number greater than or equal to the minimum number'); ok(_.some(array, function() { return _.random(Number.MAX_VALUE) > 0; - }), "should produce a random number when passed `Number.MAX_VALUE`"); + }), 'should produce a random number when passed `Number.MAX_VALUE`'); + }); + + test('now', function() { + var diff = _.now() - new Date().getTime(); + ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms }); - test("uniqueId", function() { + test('uniqueId', function() { var ids = [], i = 0; while(i++ < 100) ids.push(_.uniqueId()); equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); }); - test("times", function() { + test('times', function() { var vals = []; _.times(3, function (i) { vals.push(i); }); - ok(_.isEqual(vals, [0,1,2]), "is 0 indexed"); + ok(_.isEqual(vals, [0,1,2]), 'is 0 indexed'); // vals = []; _(3).times(function(i) { vals.push(i); }); - ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); + ok(_.isEqual(vals, [0,1,2]), 'works as a wrapper'); // collects return values - ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values"); + ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), 'collects return values'); deepEqual(_.times(0, _.identity), []); deepEqual(_.times(-1, _.identity), []); deepEqual(_.times(parseFloat('-Infinity'), _.identity), []); }); - test("mixin", function() { + test('mixin', function() { _.mixin({ myReverse: function(string) { return string.split('').reverse().join(''); @@ -71,60 +86,60 @@ $(document).ready(function() { equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); }); - test("_.escape", function() { - equal(_.escape("Curly & Moe"), "Curly & Moe"); + test('_.escape', function() { + equal(_.escape('Curly & Moe'), 'Curly & Moe'); equal(_.escape('Curly & Moe\'s'), '<a href="http://moe.com">Curly & Moe's</a>'); - equal(_.escape("Curly & Moe"), "Curly &amp; Moe"); + equal(_.escape('Curly & Moe'), 'Curly &amp; Moe'); equal(_.escape(null), ''); }); - test("_.unescape", function() { - var string = "Curly & Moe"; - equal(_.unescape("Curly & Moe"), string); + test('_.unescape', function() { + var string = 'Curly & Moe'; + equal(_.unescape('Curly & Moe'), string); equal(_.unescape('<a href="http://moe.com">Curly & Moe's</a>'), 'Curly & Moe\'s'); - equal(_.unescape("Curly &amp; Moe"), "Curly & Moe"); + equal(_.unescape('Curly &amp; Moe'), 'Curly & Moe'); equal(_.unescape(null), ''); equal(_.unescape(_.escape(string)), string); }); - test("template", function() { + test('template', function() { var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); var result = basicTemplate({thing : 'This'}); equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); - var sansSemicolonTemplate = _.template("A <% this %> B"); - equal(sansSemicolonTemplate(), "A B"); + var sansSemicolonTemplate = _.template('A <% this %> B'); + equal(sansSemicolonTemplate(), 'A B'); - var backslashTemplate = _.template("<%= thing %> is \\ridanculous"); - equal(backslashTemplate({thing: 'This'}), "This is \\ridanculous"); + var backslashTemplate = _.template('<%= thing %> is \\ridanculous'); + equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous'); var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); - var fancyTemplate = _.template("
      <% \ + var fancyTemplate = _.template('
        <% \ for (var key in people) { \ - %>
      • <%= people[key] %>
      • <% } %>
      "); - result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); - equal(result, "
      • Moe
      • Larry
      • Curly
      ", 'can run arbitrary javascript in templates'); + %>
    • <%= people[key] %>
    • <% } %>
    '); + result = fancyTemplate({people : {moe : 'Moe', larry : 'Larry', curly : 'Curly'}}); + equal(result, '
    • Moe
    • Larry
    • Curly
    ', 'can run arbitrary javascript in templates'); - var escapedCharsInJavascriptTemplate = _.template("
      <% _.each(numbers.split('\\n'), function(item) { %>
    • <%= item %>
    • <% }) %>
    "); - result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"}); - equal(result, "
    • one
    • two
    • three
    • four
    ", 'Can use escaped characters (e.g. \\n) in Javascript'); + var escapedCharsInJavascriptTemplate = _.template('
      <% _.each(numbers.split("\\n"), function(item) { %>
    • <%= item %>
    • <% }) %>
    '); + result = escapedCharsInJavascriptTemplate({numbers: 'one\ntwo\nthree\nfour'}); + equal(result, '
    • one
    • two
    • three
    • four
    ', 'Can use escaped characters (e.g. \\n) in JavaScript'); - var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
    \">
    <% }); %>"); + var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
    <% }); %>'); result = namespaceCollisionTemplate({ pageCount: 3, thumbnails: { - 1: "p1-thumbnail.gif", - 2: "p2-thumbnail.gif", - 3: "p3-thumbnail.gif" + 1: 'p1-thumbnail.gif', + 2: 'p2-thumbnail.gif', + 3: 'p3-thumbnail.gif' } }); - equal(result, "3 p3-thumbnail.gif
    "); + equal(result, '3 p3-thumbnail.gif
    '); - var noInterpolateTemplate = _.template("

    Just some text. Hey, I know this is silly but it aids consistency.

    "); + var noInterpolateTemplate = _.template('

    Just some text. Hey, I know this is silly but it aids consistency.

    '); result = noInterpolateTemplate(); - equal(result, "

    Just some text. Hey, I know this is silly but it aids consistency.

    "); + equal(result, '

    Just some text. Hey, I know this is silly but it aids consistency.

    '); var quoteTemplate = _.template("It's its, not it's"); equal(quoteTemplate({}), "It's its, not it's"); @@ -132,65 +147,68 @@ $(document).ready(function() { var quoteInStatementAndBody = _.template("<%\ if(foo == 'bar'){ \ %>Statement quotes and 'quotes'.<% } %>"); - equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'."); + equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); - var template = _.template("<%- value %>"); - var result = template({value: " - - - - - - - - - - \ No newline at end of file diff --git a/test/index.html b/test/index.html index f4c06fb07a..629d8958a0 100644 --- a/test/index.html +++ b/test/index.html @@ -165,7 +165,7 @@ window._ = undefined; removeBizarroMethods(); } - // load Lo-Dash and test scripts + // load test scripts document.write(ui.urlParams.loader == 'none' ? ' - \ No newline at end of file + diff --git a/test/index.html b/test/index.html index 9e44b13e39..1982ab7eb1 100644 --- a/test/index.html +++ b/test/index.html @@ -185,6 +185,12 @@ if (!window.require) { return; } + // avoid reporting tests to Sauce Labs when errors occur + if (ui.isSauceLabs) { + window.onerror = function() { + QUnit.config.done.length = 0; + }; + } var reBasename = /[\w.-]+$/, basePath = ('//' + location.host + location.pathname.replace(reBasename, '')).replace(/\btest\/$/, ''), modulePath = ui.buildPath.replace(/\.js$/, ''), @@ -303,4 +309,4 @@ }; - \ No newline at end of file + diff --git a/test/underscore.html b/test/underscore.html index 022049de0d..ac31ff2cc2 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -124,7 +124,7 @@ }; // only excuse in Sauce Labs (buggy Safari and timers) - if (location.port != '9001') { + if (!ui.isSauceLabs) { delete QUnit.config.excused.Chaining['select/reject/sortBy']; delete QUnit.config.excused.Chaining['select/reject/sortBy in functional style']; delete QUnit.config.excused.Functions['throttle repeatedly with results']; @@ -176,6 +176,12 @@ if (!window.require) { return; } + // avoid reporting tests to Sauce Labs when errors occur + if (ui.isSauceLabs) { + window.onerror = function() { + QUnit.config.done.length = 0; + }; + } var reBasename = /[\w.-]+$/, basePath = ('//' + location.host + location.pathname.replace(reBasename, '')).replace(/\btest\/$/, ''), modulePath = ui.buildPath.replace(/\.js$/, ''), @@ -239,4 +245,4 @@
  • <%= data %>
  • - \ No newline at end of file + From 849cf30b95f272113df25a57da2cc29f557273ce Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 00:27:41 -0700 Subject: [PATCH 0599/1608] Rebuild dist. --- dist/lodash.compat.js | 27 +++++++++++++-------------- dist/lodash.compat.min.js | 4 ++-- dist/lodash.js | 27 +++++++++++++-------------- dist/lodash.min.js | 2 +- dist/lodash.underscore.js | 5 ++++- dist/lodash.underscore.min.js | 2 +- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 989a02a355..171c8782f0 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -802,7 +802,8 @@ /** * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers; forced `false` for Windows 8 apps). + * (all but Firefox OS certified apps, older Opera mobile browsers, and + * the PlayStation 3; forced `false` for Windows 8 apps). * * @memberOf _.support * @type boolean @@ -5415,20 +5416,15 @@ * @returns {Function} Returns the new partially applied function. * @example * - * var defaultsDeep = _.partialRight(_.merge, _.defaults); - * - * var options = { - * 'variable': 'data', - * 'imports': { 'jq': $ } - * }; - * - * defaultsDeep(options, _.templateSettings); + * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { + * return _.merge(value, other, deep); + * }); * - * options.variable - * // => 'data' + * var object = { 'a': { 'b': { 'c': 1 } } }, + * source = { 'a': { 'b': { 'c': 2, 'd': 2 } } }; * - * options.imports - * // => { '_': _, 'jq': $ } + * defaultsDeep(object, source); + * // => { 'a': { 'b': { 'c': 1, 'd': 2 } } } */ function partialRight(func) { if (func) { @@ -5731,6 +5727,9 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property will be ignored. * + * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * for a deep version of this method. + * * @static * @memberOf _ * @category Objects @@ -7791,7 +7790,7 @@ function createCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function' || func == null) { - return (typeof thisArg == 'undefined' || !('prototype' in func)) && + return (typeof thisArg == 'undefined' || !(func && 'prototype' in func)) && func || baseCreateCallback(func, thisArg, argCount); } // handle "_.pluck" and "_.where" style callback shorthands diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index b34d68d50c..381b63ae1c 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -32,8 +32,8 @@ if(t=c.createCallback(t,e,4),$e(n)){var o=-1,i=n.length;for(u&&i&&(r=n[++o]);++o var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,i=r-1,e=Pr(r),a=0t||null==n||!_e(t))return r;n=Vr(n);do t%2&&(r+=n),t=ie(t/2),n+=n;while(t);return r}function Rr(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(h(n),v(n)+1):(t=Vr(t),n.slice(o(n,t),i(n,t)+1)):n}function Nr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!("prototype"in n))&&n||ht(n,t,r):"object"==e?Lr(n):$r(n)}function Tr(n){return n}function Lr(n){var t=ze(n),r=t.length,e=t[0],u=r&&n[e]; -return 1!=r||u!==u||xr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=fe.call(e,o)&&At(e[o],n[o],null,true)););return o}:function(n){return n&&fe.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function Wr(n,t,r){var e=true,u=t&&dr(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=dr(t)),false===r?e=false:xr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=wr(n),i=u?u.length:0;++rt||null==n||!_e(t))return r;n=Vr(n);do t%2&&(r+=n),t=ie(t/2),n+=n;while(t);return r}function Rr(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(h(n),v(n)+1):(t=Vr(t),n.slice(o(n,t),i(n,t)+1)):n}function Nr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||ht(n,t,r):"object"==e?Lr(n):$r(n)}function Tr(n){return n +}function Lr(n){var t=ze(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||xr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=fe.call(e,o)&&At(e[o],n[o],null,true)););return o}:function(n){return n&&fe.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function Wr(n,t,r){var e=true,u=t&&dr(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=dr(t)),false===r?e=false:xr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=wr(n),i=u?u.length:0;++r 'data' + * var object = { 'a': { 'b': { 'c': 1 } } }, + * source = { 'a': { 'b': { 'c': 2, 'd': 2 } } }; * - * options.imports - * // => { '_': _, 'jq': $ } + * defaultsDeep(object, source); + * // => { 'a': { 'b': { 'c': 1, 'd': 2 } } } */ function partialRight(func) { if (func) { @@ -5552,6 +5548,9 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property will be ignored. * + * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * for a deep version of this method. + * * @static * @memberOf _ * @category Objects @@ -7575,7 +7574,7 @@ function createCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function' || func == null) { - return (typeof thisArg == 'undefined' || !('prototype' in func)) && + return (typeof thisArg == 'undefined' || !(func && 'prototype' in func)) && func || baseCreateCallback(func, thisArg, argCount); } // handle "_.pluck" and "_.where" style callback shorthands diff --git a/dist/lodash.min.js b/dist/lodash.min.js index daf0fb0a97..f39a589898 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -31,7 +31,7 @@ a>o&&(o=a)}else t=null==t&&ke(n)?u:c.createCallback(t,e,3),mt(n,function(n,e,u){ }}function he(n){if(!be(n))throw new Ke(O);return function(){return!n.apply(this,arguments)}}function ge(n,t,e){var r=arguments;if(!n||2>r.length)return n;var u=0,o=r.length,i=typeof e;if("number"!=i&&"string"!=i||!r[3]||r[3][e]!==t||(o=2),3>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,i=$e(e),a=0t||null==n||!yr(t))return e;n=Pe(n);do t%2&&(e+=n),t=er(t/2),n+=n;while(t);return e}function Ie(n,t){return(n=null==n?"":Pe(n))?null==t?n.slice(h(n),g(n)+1):(t=Pe(t),n.slice(o(n,t),i(n,t)+1)):n}function Re(n,t,e){var r=typeof n;return"function"==r||null==n?(typeof t=="undefined"||!("prototype"in n))&&n||st(n,t,e):"object"==r?Se(n):Fe(n) +}else t=c.createCallback(t,e,3),kt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r}function Oe(n){return Rt(n,Wr)}function Ae(n){return null==n?"":Pe(n).replace(Z,"\\$&")}function Ee(n,t){var e="";if(t=+t,1>t||null==n||!yr(t))return e;n=Pe(n);do t%2&&(e+=n),t=er(t/2),n+=n;while(t);return e}function Ie(n,t){return(n=null==n?"":Pe(n))?null==t?n.slice(h(n),g(n)+1):(t=Pe(t),n.slice(o(n,t),i(n,t)+1)):n}function Re(n,t,e){var r=typeof n;return"function"==r||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||st(n,t,e):"object"==r?Se(n):Fe(n) }function Ne(n){return n}function Se(n){var t=Wr(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||_e(u)?function(r){var u=e;if(u&&!r)return false;for(var o=true;u--&&(o=t[u],o=or.call(r,o)&&Ot(r[o],n[o],null,true)););return o}:function(n){return n&&or.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function Te(n,t,e){var r=true,u=t&&ye(t);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=ye(t)),false===e?r=false:_e(e)&&"chain"in e&&(r=e.chain),e=-1;for(var o=be(n),i=u?u.length:0;++earguments.length?x(n,pr,r):x(n,pr|gr,r,N(arguments,2))}function H(n,r,t){function e(){l&&clearTimeout(l),i=l=p=lr,(h||g!==r)&&(s=yt(),f=n.apply(c,o),l||i||(o=c=null))}function u(){var t=r-(yt()-a);0>=t||t>r?(i&&clearTimeout(i),t=p,i=l=p=lr,t&&(s=yt(),f=n.apply(c,o),l||i||(o=c=null))):l=setTimeout(u,t)}var o,i,f,a,c,l,p,s=0,g=false,h=true;if(!Y(n))throw new TypeError(vr);if(r=0>r?0:r,true===t)var v=true,h=false;else Z(t)&&(v=t.leading,g="maxWait"in t&&et(r,+t.maxWait||0),h="trailing"in t?t.trailing:h); return function(){if(o=arguments,a=yt(),c=this,p=h&&(l||!v),false===g)var t=v&&!l;else{i||v||(s=a);var y=g-(a-s),m=0>=y||y>g;m?(i&&(i=clearTimeout(i)),s=a,f=n.apply(c,o)):i||(i=setTimeout(e,y))}return m&&l?l=clearTimeout(l):l||r===g||(l=setTimeout(u,r)),t&&(m=true,f=n.apply(c,o)),!m||l||i||(o=c=null),f}}function J(n){if(!Y(n))throw new TypeError(vr);return function(){return!n.apply(this,arguments)}}function K(n,r,t){if(!n)return n;var e=arguments,u=0,o=e.length,i=typeof t;for("number"!=i&&"string"!=i||!e[3]||e[3][t]!==r||(o=2);++u"']/g,dr=/($^)/,_r=/[.*+?^${}()|[\]\/\\]/g,wr=/['\n\r\u2028\u2029\\]/g,jr="[object Arguments]",xr="[object Array]",Tr="[object Boolean]",Ar="[object Date]",Er="[object Number]",Or="[object Object]",kr="[object RegExp]",Sr="[object String]",Nr={"&":"&","<":"<",">":">",'"':""","'":"'"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'"},Fr={"function":true,object:true},Br={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mr=Fr[typeof window]&&window||this,Rr=Fr[typeof exports]&&exports&&!exports.nodeType&&exports,$r=Fr[typeof module]&&module&&!module.nodeType&&module,Ir=Rr&&$r&&typeof global=="object"&&global; !Ir||Ir.global!==Ir&&Ir.window!==Ir&&Ir.self!==Ir||(Mr=Ir);var Dr=$r&&$r.exports===Rr&&Rr,Wr=Array.prototype,zr=Object.prototype,Cr=Mr._,Pr=Math.pow(2,53)-1,Ur=zr.toString,Vr=RegExp("^"+(null==Ur?"":(Ur+"").replace(_r,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Gr=Math.ceil,Hr=Math.floor,Jr=Function.prototype.toString,Kr=zr.hasOwnProperty,Lr=Wr.push,Qr=zr.propertyIsEnumerable,Xr=Wr.splice,Yr=A(Yr=Object.create)&&Yr,Zr=A(Zr=Array.isArray)&&Zr,nt=Mr.isFinite,rt=Mr.isNaN,tt=A(tt=Object.keys)&&tt,et=Math.max,ut=Math.min,ot=A(ot=Date.now)&&ot,it=Math.random; i.prototype=o.prototype;var ft={};!function(){var n={0:1,length:1};ft.spliceObjects=(Xr.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Yr||(c=function(){function n(){}return function(r){if(Z(r)){n.prototype=r;var t=new n;n.prototype=null}return t||Mr.Object()}}());var at=S,ct=O,lt=j(function(n,r,t){Kr.call(n,t)?n[t]++:n[t]=1}),pt=j(function(n,r,t){Kr.call(n,t)?n[t].push(r):n[t]=[r]}),st=j(function(n,r,t){n[t]=r From cf468fc4d14c783fbee0c1417d86111c3df3c7b7 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 00:27:59 -0700 Subject: [PATCH 0600/1608] Update tested version of Node in readme. [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a467e8edf8..42d36db0a2 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ A list of upcoming features is available on our [roadmap](https://github.com/lod ## Support -Tested in Chrome (19, 33-34), Firefox (3, 20, 27-28), IE 6-11, Opera (10, 12, 19-20), Safari 5-7, Node.js 0.6.21~0.10.26, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 33-34), Firefox (3, 20, 27-28), IE 6-11, Opera (10, 12, 19-20), Safari 5-7, Node.js 0.6.21~0.10.28, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test results [are available](https://saucelabs.com/u/lodash) as well as [Travis CI](https://travis-ci.org/) builds for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). From e3f94156f1dc3b0c913f6049078e3defc9281c27 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 06:30:30 -0700 Subject: [PATCH 0601/1608] Update tested version of Firefox in readme. [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42d36db0a2..fe2b14d2ba 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ A list of upcoming features is available on our [roadmap](https://github.com/lod ## Support -Tested in Chrome (19, 33-34), Firefox (3, 20, 27-28), IE 6-11, Opera (10, 12, 19-20), Safari 5-7, Node.js 0.6.21~0.10.28, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 33-34), Firefox (3, 20, 28-29), IE 6-11, Opera (10, 12, 19-20), Safari 5-7, Node.js 0.6.21~0.10.28, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test results [are available](https://saucelabs.com/u/lodash) as well as [Travis CI](https://travis-ci.org/) builds for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). From 0f8db11f53aa3ae96008e562deb316a7adf47eb8 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 07:55:11 -0700 Subject: [PATCH 0602/1608] Restrict script load error excusal a bit. --- test/asset/test-ui.js | 9 +++++++++ test/backbone.html | 7 +++++-- test/index.html | 7 +++++-- test/underscore.html | 7 +++++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/test/asset/test-ui.js b/test/asset/test-ui.js index 5b9a72128a..c4f038b5d9 100644 --- a/test/asset/test-ui.js +++ b/test/asset/test-ui.js @@ -121,6 +121,10 @@ var buildList = span1.lastChild, loaderList = span2.lastChild; + setTimeout(function() { + ui.timing.loadEventEnd = +new Date; + }, 1); + init(); }); @@ -161,6 +165,11 @@ 'loader': loader }; + // expose page load timestamps + ui.timing = { + 'loadEventEnd': 0 + }; + // used to indicate testing a modularized build ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|node)|modularize|npm)\b/.test([location.pathname, location.search, ui.buildPath]); diff --git a/test/backbone.html b/test/backbone.html index 10b59cc358..0b0ec233e8 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -64,10 +64,13 @@

    Test

    mixinPrereqs(_); return; } - // avoid reporting tests to Sauce Labs when errors occur + // avoid reporting tests to Sauce Labs when script load errors occur if (ui.isSauceLabs) { window.onerror = function() { - QUnit.config.done.length = 0; + var loadEventEnd = ui.timing.loadEventEnd; + if (loadEventEnd && (new Date - loadEventEnd > 5000)) { + QUnit.config.done.length = 0; + } }; } var reBasename = /[\w.-]+$/, diff --git a/test/index.html b/test/index.html index 1982ab7eb1..8c7def3021 100644 --- a/test/index.html +++ b/test/index.html @@ -185,10 +185,13 @@ if (!window.require) { return; } - // avoid reporting tests to Sauce Labs when errors occur + // avoid reporting tests to Sauce Labs when script load errors occur if (ui.isSauceLabs) { window.onerror = function() { - QUnit.config.done.length = 0; + var loadEventEnd = ui.timing.loadEventEnd; + if (loadEventEnd && (new Date - loadEventEnd > 5000)) { + QUnit.config.done.length = 0; + } }; } var reBasename = /[\w.-]+$/, diff --git a/test/underscore.html b/test/underscore.html index ac31ff2cc2..58c0876654 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -176,10 +176,13 @@ if (!window.require) { return; } - // avoid reporting tests to Sauce Labs when errors occur + // avoid reporting tests to Sauce Labs when script load errors occur if (ui.isSauceLabs) { window.onerror = function() { - QUnit.config.done.length = 0; + var loadEventEnd = ui.timing.loadEventEnd; + if (loadEventEnd && (new Date - loadEventEnd > 5000)) { + QUnit.config.done.length = 0; + } }; } var reBasename = /[\w.-]+$/, From fb20dae0a868fa65198a05d9a250704bc7e9fcd1 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 21:27:32 -0700 Subject: [PATCH 0603/1608] Whitespace nits. [ci skip] --- test/saucelabs.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 9b5af76096..02a50e2c8a 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -490,6 +490,7 @@ Job.prototype.reset = function(callback) { this.once('start', _.callback(callback, this)); _.defer(_.bind(this.emit, this, 'reset')); + return this; }; @@ -522,8 +523,8 @@ Job.prototype.restart = function(callback) { */ Job.prototype.start = function(callback) { var tunnel = this.tunnel; - this.once('start', _.callback(callback, this)); + this.once('start', _.callback(callback, this)); if (this.starting || this.running || tunnel.starting || tunnel.stopping) { return this; } @@ -545,8 +546,8 @@ Job.prototype.start = function(callback) { */ Job.prototype.status = function(callback) { var tunnel = this.tunnel; - this.once('status', _.callback(callback, this)); + this.once('status', _.callback(callback, this)); if (this.checking || this.starting || this.stopping || tunnel.starting || tunnel.stopping) { return this; } @@ -568,13 +569,12 @@ Job.prototype.status = function(callback) { */ Job.prototype.stop = function(callback) { this.once('stop', _.callback(callback, this)); - if (this.stopping || this.tunnel.starting) { return this; } var onStop = _.bind(onJobStop, this); - this.stopping = true; + this.stopping = true; if (this.statusId) { this.checking = false; this.statusId = clearTimeout(this.statusId); @@ -674,7 +674,6 @@ Tunnel.prototype.restart = function(callback) { */ Tunnel.prototype.start = function(callback) { this.once('start', _.callback(callback, this)); - if (!(this.starting || this.running)) { console.log('Opening Sauce Connect tunnel...'); this.starting = true; From 3de50e8dd4ae9440c616aa5f2b087e724bdb085f Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 21:28:19 -0700 Subject: [PATCH 0604/1608] Emit `restart` events for `Job` and `Tunnel`. --- test/saucelabs.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/saucelabs.js b/test/saucelabs.js index 02a50e2c8a..29df925ad9 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -510,7 +510,9 @@ Job.prototype.restart = function(callback) { logInline(); console.log(label + ' ' + description + ' restart #%d of %d', ++this.attempts, this.retries); + _.defer(_.bind(this.emit, this, 'restart')); this.stop(_.partial(this.start, callback)); + return this; }; @@ -661,7 +663,9 @@ Tunnel.prototype.restart = function(callback) { logInline(); console.log('Tunnel ' + this.id + ': restart #%d of %d', ++this.attempts, this.retries); + _.defer(_.bind(this.emit, this, 'restart')); this.stop(_.partial(this.start, callback)); + return this; }; From c19f87134edc5ef9c070c9523af9fd15f0bad057 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 21:41:02 -0700 Subject: [PATCH 0605/1608] Restart tunnel if all jobs have restarted. --- test/saucelabs.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/saucelabs.js b/test/saucelabs.js index 29df925ad9..d08b26b894 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -624,6 +624,7 @@ function Tunnel(properties) { }, this); var completed = 0, + restarted = [], success = true, total = all.length, tunnel = this; @@ -641,9 +642,20 @@ function Tunnel(properties) { tunnel.dequeue(); }); + _.invoke(all, 'on', 'restart', function() { + if (!_.contains(restarted, this)) { + restarted.push(this); + } + // restart tunnel if all jobs have restarted + if (_.isEmpty(_.difference(all, restarted))) { + tunnel.restart(); + } + }); + this.on('stop', function() { completed = 0; success = true; + restarted.length = 0; _.invoke(all, 'reset'); }); From 695d6e14d49b0e9561938e2fff65de4a651d52af Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 21:42:19 -0700 Subject: [PATCH 0606/1608] Remove `_.at` guard for `_.map` use. --- lodash.js | 9 ++------- test/test.js | 7 ------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/lodash.js b/lodash.js index 9651ec14ad..05589fcb03 100644 --- a/lodash.js +++ b/lodash.js @@ -3610,17 +3610,12 @@ * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ - function at(collection, guard) { + function at(collection) { var args = arguments, index = -1, props = baseFlatten(args, true, false, 1), - length = props.length, - type = typeof guard; + length = props.length; - // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) { - length = 1; - } if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } diff --git a/test/test.js b/test/test.js index df75717443..68b4f3a26d 100644 --- a/test/test.js +++ b/test/test.js @@ -693,13 +693,6 @@ deepEqual(actual, [1, 3]); }); - test('should work when used as a callback for `_.map`', 1, function() { - var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], - actual = _.map(array, _.at); - - deepEqual(actual, [[1], [5], [9]]); - }); - _.each({ 'literal': 'abc', 'object': Object('abc') From 4c690b9d4c9f09325be72428df705b2039cff6df Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 21:44:43 -0700 Subject: [PATCH 0607/1608] Make documented args names of methods that accept more than one plural. [ci skip] --- lodash.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lodash.js b/lodash.js index 05589fcb03..13b9c21331 100644 --- a/lodash.js +++ b/lodash.js @@ -3599,8 +3599,8 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes to retrieve, - * specified as individual indexes or arrays of indexes. + * @param {...(number|number[]|string|string[])} [keys] The keys of elements + * to pick, specified as individual keys or arrays of keys. * @returns {Array} Returns the array of picked elements. * @example * @@ -4904,8 +4904,8 @@ * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. + * @param {...string} [methodNames] The object method names to bind, specified + * as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * @@ -5520,7 +5520,7 @@ * @alias extend * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -5728,7 +5728,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example @@ -6718,7 +6718,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. From a5e91385b08bc5ba3501102969d4491fb149fc88 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 21:55:18 -0700 Subject: [PATCH 0608/1608] Expand the excuse window of load errors to 3 seconds or more. --- test/backbone.html | 2 +- test/index.html | 2 +- test/underscore.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/backbone.html b/test/backbone.html index 0b0ec233e8..5dc65b3098 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -68,7 +68,7 @@

    Test

    if (ui.isSauceLabs) { window.onerror = function() { var loadEventEnd = ui.timing.loadEventEnd; - if (loadEventEnd && (new Date - loadEventEnd > 5000)) { + if (loadEventEnd && (new Date - loadEventEnd > 3000)) { QUnit.config.done.length = 0; } }; diff --git a/test/index.html b/test/index.html index 8c7def3021..9606cf2a8a 100644 --- a/test/index.html +++ b/test/index.html @@ -189,7 +189,7 @@ if (ui.isSauceLabs) { window.onerror = function() { var loadEventEnd = ui.timing.loadEventEnd; - if (loadEventEnd && (new Date - loadEventEnd > 5000)) { + if (loadEventEnd && (new Date - loadEventEnd > 3000)) { QUnit.config.done.length = 0; } }; diff --git a/test/underscore.html b/test/underscore.html index 58c0876654..3a2180c80f 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -180,7 +180,7 @@ if (ui.isSauceLabs) { window.onerror = function() { var loadEventEnd = ui.timing.loadEventEnd; - if (loadEventEnd && (new Date - loadEventEnd > 5000)) { + if (loadEventEnd && (new Date - loadEventEnd > 3000)) { QUnit.config.done.length = 0; } }; From 702a82bb382c08fee21019b3abe59fb29d632765 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 22:05:26 -0700 Subject: [PATCH 0609/1608] Remove `args` var from `_.at`. --- lodash.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index 13b9c21331..02cac1c28a 100644 --- a/lodash.js +++ b/lodash.js @@ -3611,9 +3611,8 @@ * // => ['fred', 'pebbles'] */ function at(collection) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), + var index = -1, + props = baseFlatten(arguments, true, false, 1), length = props.length; if (support.unindexedChars && isString(collection)) { From 6ad31a54413da1ff47f87c5a606bc7e9767b1632 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 3 May 2014 22:09:15 -0700 Subject: [PATCH 0610/1608] Restart tunnel if all *active* jobs have restarted. --- test/saucelabs.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index d08b26b894..a884d0df8a 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -646,8 +646,9 @@ function Tunnel(properties) { if (!_.contains(restarted, this)) { restarted.push(this); } - // restart tunnel if all jobs have restarted - if (_.isEmpty(_.difference(all, restarted))) { + // restart tunnel if all active jobs have restarted + var threshold = _.isFinite(throttled) ? throttled : 3; + if (active.length >= threshold && _.isEmpty(_.difference(active, restarted))) { tunnel.restart(); } }); From 95bd2dde195cc6d5e654735f7ae1b57b1000fa4c Mon Sep 17 00:00:00 2001 From: Dan Allison Date: Fri, 28 Feb 2014 22:26:22 -0800 Subject: [PATCH 0611/1608] add `removeAt` function (cherry picked from commit 06b3eae373484618b58f70f3cd6ecda319bfd977) --- lodash.js | 4053 +++++++++++++++++++++----------------------------- test/test.js | 3096 ++++++++++++-------------------------- 2 files changed, 2611 insertions(+), 4538 deletions(-) diff --git a/lodash.js b/lodash.js index 02cac1c28a..673d907494 100644 --- a/lodash.js +++ b/lodash.js @@ -3,7 +3,7 @@ * Lo-Dash 2.4.1 * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 - * Copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ ;(function() { @@ -25,15 +25,9 @@ /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; - /** Used as the TypeError message for "Functions" methods */ - var funcErrorText = 'Expected a function'; - /** Used to generate unique IDs */ var idCounter = 0; - /** Used to detect words composed of all capital letters */ - var reAllCaps = /^[A-Z]+$/; - /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, @@ -49,13 +43,12 @@ reInterpolate = /<%=([\s\S]+?)%>/g; /** - * Used to match ES6 template delimiters. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) - * for more details. + * Used to match ES6 template delimiters + * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; - /** Used to match `RegExp` flags from their coerced string values */ + /** Used to match regexp flags from their coerced string values */ var reFlags = /\w*$/; /** Used to detected named functions */ @@ -64,27 +57,14 @@ /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; - /** Used to match latin-1 supplement letters */ - var reLatin1 = /[\xC0-\xFF]/g; - /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; - /** - * Used to match `RegExp` special characters. - * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) - * for more details. - */ - var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g; - /** Used to detect functions containing a `this` reference */ var reThis = /\bthis\b/; /** Used to match unescaped characters in compiled string literals */ - var reUnescapedString = /['\n\r\u2028\u2029\\]/g; - - /** Used to match words to create compound words */ - var reWords = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g; + var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; /** Used to detect and test whitespace */ var whitespace = ( @@ -105,13 +85,13 @@ 'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError' ]; - /** Used to fix the JScript `[[DontEnum]]` bug */ + /** Used to fix the JScript [[DontEnum]] bug */ var shadowedProps = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; - /** Used to make template `sourceURL`s easier to identify */ + /** Used to make template sourceURLs easier to identify */ var templateCounter = 0; /** `Object#toString` result shortcuts */ @@ -134,7 +114,7 @@ cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; - /** Used as an internal `_.debounce` options object by `_.throttle` */ + /** Used as an internal `_.debounce` options object */ var debounceOptions = { 'leading': false, 'maxWait': 0, @@ -175,32 +155,7 @@ ''': "'" }; - /** - * Used to convert latin-1 supplement letters to basic latin (ASCII) letters. - * See [Wikipedia](http://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * for more details. - */ - var deburredLetters = { - '\xC0': 'A', '\xC1': 'A', '\xC2': 'A', '\xC3': 'A', '\xC4': 'A', '\xC5': 'A', - '\xE0': 'a', '\xE1': 'a', '\xE2': 'a', '\xE3': 'a', '\xE4': 'a', '\xE5': 'a', - '\xC7': 'C', '\xE7': 'c', - '\xD0': 'D', '\xF0': 'd', - '\xC8': 'E', '\xC9': 'E', '\xCA': 'E', '\xCB': 'E', - '\xE8': 'e', '\xE9': 'e', '\xEA': 'e', '\xEB': 'e', - '\xCC': 'I', '\xCD': 'I', '\xCE': 'I', '\xCF': 'I', - '\xEC': 'i', '\xED': 'i', '\xEE': 'i', '\xEF': 'i', - '\xD1': 'N', '\xF1': 'n', - '\xD2': 'O', '\xD3': 'O', '\xD4': 'O', '\xD5': 'O', '\xD6': 'O', '\xD8': 'O', - '\xF2': 'o', '\xF3': 'o', '\xF4': 'o', '\xF5': 'o', '\xF6': 'o', '\xF8': 'o', - '\xD9': 'U', '\xDA': 'U', '\xDB': 'U', '\xDC': 'U', - '\xF9': 'u', '\xFA': 'u', '\xFB': 'u', '\xFC': 'u', - '\xDD': 'Y', '\xFD': 'y', '\xFF': 'y', - '\xC6': 'AE', '\xE6': 'ae', - '\xDE': 'Th', '\xFE': 'th', - '\xDF': 'ss', '\xD7': ' ', '\xF7': ' ' - }; - - /** Used to determine if values are of the language type `Object` */ + /** Used to determine if values are of the language type Object */ var objectTypes = { 'function': true, 'object': true @@ -212,6 +167,7 @@ "'": "'", '\n': 'n', '\r': 'r', + '\t': 't', '\u2028': 'u2028', '\u2029': 'u2029' }; @@ -236,33 +192,21 @@ /*--------------------------------------------------------------------------*/ - /** - * Used by `_.defaults` to customize its `_.assign` use. - * - * @private - * @param {*} objectValue The destination object property value. - * @param {*} sourceValue The source object property value. - * @returns {*} Returns the value to assign to the destination object. - */ - function assignDefaults(objectValue, sourceValue) { - return typeof objectValue == 'undefined' ? sourceValue : objectValue; - } - /** * The base implementation of `compareAscending` used to compare values and * sort 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`. - * @returns {number} Returns the sort order indicator for `value`. + * @param {*} a The value to compare to `b`. + * @param {*} b The value to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. */ - function baseCompareAscending(value, other) { - if (value !== other) { - if (value > other || typeof value == 'undefined') { + function baseCompareAscending(a, b) { + if (a !== b) { + if (a > b || typeof a == 'undefined') { return 1; } - if (value < other || typeof other == 'undefined') { + if (a < b || typeof b == 'undefined') { return -1; } } @@ -276,7 +220,7 @@ * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. + * @returns {number} Returns the index of the matched value or `-1`. */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, @@ -304,24 +248,22 @@ } /** - * Used by `_.max` and `_.min` as the default callback when a given collection - * is a string value. + * Used by `_.max` and `_.min` as the default callback when a given + * collection is a string value. * * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the code unit of the first character of the string. + * @param {string} value The character to inspect. + * @returns {number} Returns the code unit of given character. */ - function charAtCallback(string) { - return string.charCodeAt(0); + function charAtCallback(value) { + return value.charCodeAt(0); } /** - * Used by `_.trim` and `_.trimLeft` to get the index of the first character - * of `string` that is not found in `chars`. + * Gets the index of the first character of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. - * @param {string} chars The characters to find. * @returns {number} Returns the index of the first character not found in `chars`. */ function charsLeftIndex(string, chars) { @@ -337,12 +279,10 @@ } /** - * Used by `_.trim` and `_.trimRight` to get the index of the last character - * of `string` that is not found in `chars`. + * Gets the index of the last character of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. - * @param {string} chars The characters to find. * @returns {number} Returns the index of the last character not found in `chars`. */ function charsRightIndex(string, chars) { @@ -356,121 +296,149 @@ } /** - * Used by `_.sortBy` to compare transformed elements of a collection and stable + * Used by `sortBy` to compare transformed elements of a collection and stable * sort them in ascending order. * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. - * @returns {number} Returns the sort order indicator for `object`. + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. */ - function compareAscending(object, other) { - return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + function compareAscending(a, b) { + return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; } /** - * Used by `_.sortBy` to compare multiple properties of each element in a + * Used by `sortBy` to compare multiple properties of each element in a * collection and stable sort them in ascending order. * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. - * @returns {number} Returns the sort order indicator for `object`. + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {number} Returns the sort order indicator for `a`. */ - function compareMultipleAscending(object, other) { - var index = -1, - objCriteria = object.criteria, - othCriteria = other.criteria, - length = objCriteria.length; + function compareMultipleAscending(a, b) { + var ac = a.criteria, + bc = b.criteria, + index = -1, + length = ac.length; while (++index < length) { - var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + var result = baseCompareAscending(ac[index], bc[index]); if (result) { return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to provide the same value - // for `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provided the same value + // for `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See https://code.google.com/p/v8/issues/detail?id=90 - return object.index - other.index; + return a.index - b.index; } /** - * Creates a function that produces compound words out of the words in a - * given string. + * Used by `escape` to convert characters to HTML entities. * * @private - * @param {Function} callback The function called to combine each word. - * @returns {Function} Returns the new compounder function. + * @param {string} match The matched character to escape. + * @returns {string} Returns the escaped character. */ - function createCompounder(callback) { - return function(string) { - var index = -1, - words = string != null && String(string).replace(reLatin1, deburrLetter).match(reWords), - length = words ? words.length : 0, - result = ''; + function escapeHtmlChar(match) { + return htmlEscapes[match]; + } - while (++index < length) { - result = callback(result, words[index], index, words); - } - return result; - }; + /** + * Used by `template` to escape characters for inclusion in compiled + * string literals. + * + * @private + * @param {string} match The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(match) { + return '\\' + stringEscapes[match]; } /** - * Used by `createCompounder` to convert latin-1 supplement letters to basic - * latin (ASCII) letters. + * Checks if `value` is a DOM node in IE < 9. * * @private - * @param {string} letter The matched letter to deburr. - * @returns {string} Returns the deburred letter. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`. */ - function deburrLetter(letter) { - return deburredLetters[letter]; + function isNode(value) { + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings + return typeof value.toString != 'function' && typeof (value + '') == 'string'; } /** - * Used by `_.escape` to convert characters to HTML entities. + * A fallback implementation of `trim` to remove leading and trailing + * whitespace or specified characters from `string`. * * @private - * @param {string} chr The matched character to escape. - * @returns {string} Returns the escaped character. + * @param {string} string The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @returns {string} Returns the trimmed string. */ - function escapeHtmlChar(chr) { - return htmlEscapes[chr]; + function shimTrim(string, chars) { + string = string == null ? '' : String(string); + if (!string) { + return string; + } + if (chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = String(chars); + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); } /** - * Used by `_.template` to escape characters for inclusion in compiled - * string literals. + * A fallback implementation of `trimLeft` to remove leading whitespace or + * specified characters from `string`. * * @private - * @param {string} chr The matched character to escape. - * @returns {string} Returns the escaped character. + * @param {string} string The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @returns {string} Returns the trimmed string. */ - function escapeStringChar(chr) { - return '\\' + stringEscapes[chr]; + function shimTrimLeft(string, chars) { + string = string == null ? '' : String(string); + if (!string) { + return string; + } + if (chars == null) { + return string.slice(trimmedLeftIndex(string)) + } + chars = String(chars); + return string.slice(charsLeftIndex(string, chars)); } /** - * Checks if `value` is a DOM node in IE < 9. + * A fallback implementation of `trimRight` to remove trailing whitespace or + * specified characters from `string`. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM node, else `false`. + * @param {string} string The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @returns {string} Returns the trimmed string. */ - function isNode(value) { - // IE < 9 presents DOM nodes as `Object` objects except they have `toString` - // methods that are `typeof` "string" and still can coerce nodes to strings - return typeof value.toString != 'function' && typeof (value + '') == 'string'; + function shimTrimRight(string, chars) { + string = string == null ? '' : String(string); + if (!string) { + return string; + } + if (chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1) + } + chars = String(chars); + return string.slice(0, charsRightIndex(string, chars) + 1); } /** - * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace - * character of `string`. + * Gets the index of the first non-whitespace character of `string`. * * @private * @param {string} string The string to inspect. @@ -491,8 +459,7 @@ } /** - * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace - * character of `string`. + * Gets the index of the last non-whitespace character of `string`. * * @private * @param {string} string The string to inspect. @@ -511,20 +478,20 @@ } /** - * Used by `_.unescape` to convert HTML entities to characters. + * Used by `unescape` to convert HTML entities to characters. * * @private - * @param {string} chr The matched character to unescape. + * @param {string} match The matched character to unescape. * @returns {string} Returns the unescaped character. */ - function unescapeHtmlChar(chr) { - return htmlUnescapes[chr]; + function unescapeHtmlChar(match) { + return htmlUnescapes[match]; } /*--------------------------------------------------------------------------*/ /** - * Create a new `lodash` function using the given `context` object. + * Create a new `lodash` function using the given context object. * * @static * @memberOf _ @@ -561,23 +528,17 @@ /** Used to detect DOM support */ var document = (document = context.window) && document.document; - /** Used to restore the original `_` reference in `_.noConflict` */ + /** Used to restore the original `_` reference in `noConflict` */ var oldDash = context._; - /** - * Used as the maximum length of an array-like object. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. - */ - var maxSafeInteger = Math.pow(2, 53) - 1; - - /** Used to resolve the internal `[[Class]]` of values */ + /** Used to resolve the internal [[Class]] of values */ var toString = objectProto.toString; /** Used to detect if a method is native */ var reNative = RegExp('^' + - escapeRegExp(toString) - .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + String(toString) + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method shortcuts */ @@ -594,7 +555,7 @@ splice = arrayRef.splice, unshift = arrayRef.unshift; - /** Used to set metadata on functions */ + /** Used to set meta data on functions */ var defineProperty = (function() { // IE 8 only accepts DOM elements try { @@ -616,9 +577,12 @@ nativeMin = Math.min, nativeNow = isNative(nativeNow = Date.now) && nativeNow, nativeParseInt = context.parseInt, - nativeRandom = Math.random; + nativeRandom = Math.random, + nativeTrim = isNative(nativeTrim = stringProto.trim) && !nativeTrim.call(whitespace) && nativeTrim, + nativeTrimLeft = isNative(nativeTrimLeft = stringProto.trimLeft) && !nativeTrimLeft.call(whitespace) && nativeTrimLeft, + nativeTrimRight = isNative(nativeTrimRight = stringProto.trimRight) && !nativeTrimRight.call(whitespace) && nativeTrimRight; - /** Used to lookup built-in constructors by `[[Class]]` */ + /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; ctorByClass[arrayClass] = Array; ctorByClass[boolClass] = Boolean; @@ -629,7 +593,7 @@ ctorByClass[regexpClass] = RegExp; ctorByClass[stringClass] = String; - /** Used to avoid iterating over non-enumerable properties in IE < 9 */ + /** Used to avoid iterating non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true }; @@ -662,18 +626,18 @@ * implicitly or explicitly included in the build. * * The chainable wrapper functions are: - * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, + * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, * `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`, * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, - * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, - * `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, - * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, - * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, - * `xor`, and `zip` + * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, + * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, + * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, + * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, + * and `zip` * * The non-chainable wrapper functions are: * `capitalize`, `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, @@ -681,10 +645,10 @@ * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, * `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, * `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, - * `isUndefined`, `join`, `lastIndexOf`, `noConflict`, `now`, `parseInt`, - * `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`, - * `sortedIndex`, `runInContext`, `template`, `trim`, `trimLeft`, `trimRight`, - * `unescape`, `uniqueId`, and `value` + * `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `now`, + * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, + * `size`, `some`, `sortedIndex`, `runInContext`, `template`, `trim`, + * `trimLeft`, `trimRight`, `unescape`, `uniqueId`, and `value` * * The wrapper functions `first`, `last`, and `sample` return wrapped values * when `n` is provided, otherwise they return unwrapped values. @@ -729,7 +693,7 @@ * * @private * @param {*} value The value to wrap in a `lodash` instance. - * @param {boolean} [chainAll=false] A flag to enable chaining for all methods. + * @param {boolean} [chainAll=false] A flag to enable chaining for all methods * @returns {Object} Returns a `lodash` instance. */ function lodashWrapper(value, chainAll) { @@ -748,19 +712,17 @@ */ var support = lodash.support = {}; - (function(x) { + (function() { var ctor = function() { this.x = 1; }, object = { '0': 1, 'length': 1 }, props = []; ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new ctor) { props.push(key); } - for (var argsKey in arguments) { } - for (var strKey in 'x') { } + for (key in arguments) { } /** - * Detect if the `[[Class]]` of `arguments` objects is resolvable - * (all but Firefox < 4, IE < 9). + * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9). * * @memberOf _.support * @type boolean @@ -768,8 +730,7 @@ support.argsClass = toString.call(arguments) == argsClass; /** - * Detect if `arguments` objects are `Object` objects - * (all but Narwhal and Opera < 10.5). + * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5). * * @memberOf _.support * @type boolean @@ -778,21 +739,20 @@ /** * Detect if `name` or `message` properties of `Error.prototype` are - * enumerable by default (IE < 9, Safari < 5.1). + * enumerable by default. (IE < 9, Safari < 5.1) * * @memberOf _.support * @type boolean */ - support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || - propertyIsEnumerable.call(errorProto, 'name'); + support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name'); /** * Detect if `prototype` properties are enumerable by default. * * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 * (if the prototype or a property on the prototype has been set) - * incorrectly sets the `[[Enumerable]]` value of a function's `prototype` - * property to `true`. + * incorrectly sets a function's `prototype` property [[Enumerable]] + * value to `true`. * * @memberOf _.support * @type boolean @@ -801,8 +761,7 @@ /** * 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). + * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). * * @memberOf _.support * @type boolean @@ -818,20 +777,19 @@ support.funcNames = typeof Function.name == 'string'; /** - * Detect if string indexes are non-enumerable - * (IE < 9, RingoJS, Rhino, Narwhal). + * Detect if `arguments` object indexes are non-enumerable + * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1). * * @memberOf _.support * @type boolean */ - support.nonEnumStrings = strKey != '0'; + support.nonEnumArgs = key != 0; /** - * Detect if properties shadowing those on `Object.prototype` are - * non-enumerable. + * Detect if properties shadowing those on `Object.prototype` are non-enumerable. * - * In IE < 9 an object's own properties, shadowing non-enumerable ones, - * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). + * In IE < 9 an objects own properties, shadowing non-enumerable ones, are + * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug). * * @memberOf _.support * @type boolean @@ -839,8 +797,7 @@ support.nonEnumShadows = !/valueOf/.test(props); /** - * Detect if own properties are iterated after inherited properties - * (all but IE < 9). + * Detect if own properties are iterated after inherited properties (all but IE < 9). * * @memberOf _.support * @type boolean @@ -848,15 +805,13 @@ support.ownLast = props[0] != 'x'; /** - * Detect if `Array#shift` and `Array#splice` augment array-like objects - * correctly. + * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. * * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` * and `splice()` functions that fail to remove the last element, `value[0]`, * of array-like objects even though the `length` property is set to `0`. * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` - * is buggy regardless of mode in IE < 9 and buggy in compatibility mode - * in IE 9. + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. * * @memberOf _.support * @type boolean @@ -866,8 +821,8 @@ /** * Detect lack of support for accessing string characters by index. * - * IE < 8 can't access characters by index. IE 8 can only access characters - * by index on string literals, not string objects. + * IE < 8 can't access characters by index and IE 8 can only access + * characters by index on string literals. * * @memberOf _.support * @type boolean @@ -887,9 +842,9 @@ } /** - * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9) - * and that the JS engine errors when attempting to coerce an object to a - * string without a `toString` function. + * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9) + * and that the JS engine errors when attempting to coerce an object to + * a string without a `toString` function. * * @memberOf _.support * @type boolean @@ -899,31 +854,12 @@ } catch(e) { support.nodeClass = true; } - - /** - * 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 their function's formal parameters with - * associated values of `0`. - * - * @memberOf _.support - * @type boolean - */ - try { - support.nonEnumArgs = !(argsKey == '1' && hasOwnProperty.call(arguments, argsKey) && - propertyIsEnumerable.call(arguments, argsKey)); - } catch(e) { - support.nonEnumArgs = true; - } - }(0, 0)); + }(1)); /** - * By default, the template delimiters used by Lo-Dash are similar to those - * in embedded Ruby (ERB). Change the following template settings to use - * alternative delimiters. + * By default, the template delimiters used by Lo-Dash are similar to those in + * embedded Ruby (ERB). Change the following template settings to use alternative + * delimiters. * * @static * @memberOf _ @@ -984,68 +920,88 @@ /*--------------------------------------------------------------------------*/ /** - * A specialized version of `_.forEach` for arrays without support for - * callback shorthands or `this` binding. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Array} Returns `array`. - */ - function arrayEach(array, callback) { - var index = -1, - length = array ? array.length : 0; - - while (++index < length) { - if (callback(array[index], index, array) === false) { - break; - } - } - return array; - } - - /** - * A specialized version of `_.forEachRight` for arrays without support for - * callback shorthands or `this` binding. + * The template used to create iterator functions. * * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Array} Returns `array`. - */ - function arrayEachRight(array, callback) { - var length = array ? array.length : 0; - while (length--) { - if (callback(array[length], length, array) === false) { - break; - } - } - return array; - } + * @param {Object} data The data object used to populate the text. + * @returns {string} Returns the interpolated text. + */ + var iteratorTemplate = template( + // assign the `result` variable an initial value + 'var result = <%= init %>;\n' + + + // exit early if the first argument is not an object + "if (!isObject(object)) {\n" + + ' return result;\n' + + '}' + + + // add support for iterating over `arguments` objects if needed + '<% if (support.nonEnumArgs) { %>\n' + + 'var length = object.length;\n' + + 'if (length && isArguments(object)) {\n' + + ' key = -1;\n' + + ' while (++key < length) {\n' + + " key += '';\n" + + ' <%= loop %>;\n' + + ' }\n' + + ' return result;\n' + + '}' + + '<% } %>' + + + // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari + '<% if (support.enumPrototypes) { %>\n' + + "var skipProto = typeof object == 'function';\n" + + '<% } %>' + + + // avoid iterating over `Error.prototype` properties in older IE and Safari + '<% if (support.enumErrorProps) { %>\n' + + 'var skipErrorProps = object === errorProto || object instanceof Error;\n' + + '<% } %>' + + + // define conditions used in the loop + '<%' + + 'var conditions = [];\n' + + "if (support.enumPrototypes) { conditions.push('!(skipProto && key == \\'prototype\\')'); }\n" + + "if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (key == \\'message\\' || key == \\'name\\'))'); }" + + '%>\n' + + + // iterate over the object + 'for (var key in object) {\n<%' + + " if (useHas) { conditions.push('hasOwnProperty.call(object, key)'); }\n" + + " if (conditions.length) { %> if (<%= conditions.join(' && ') %>) {\n <% } %>" + + ' <%= loop %>;' + + ' <% if (conditions.length) { %>\n }<% } %>\n' + + '}\n' + - /** - * A specialized version of `_.map` for arrays without support for callback - * shorthands or `this` binding. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Array} Returns the new mapped array. - */ - function arrayMap(array, callback) { - var index = -1, - length = array ? array.length >>> 0 : 0, - result = Array(length); + // Lo-Dash skips the `constructor` property when it infers it's iterating + // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` + // attribute of an existing property and the `constructor` property of a + // prototype defaults to non-enumerable. + '<% if (support.nonEnumShadows) { %>\n' + + 'if (object !== objectProto) {\n' + + " var ctor = object.constructor,\n" + + ' isProto = object === (ctor && ctor.prototype),\n' + + ' className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object),\n' + + ' nonEnum = nonEnumProps[className];\n' + + ' <% for (var index = 0; index < 7; index++) { %>\n' + + " key = '<%= shadowedProps[index] %>';\n" + + ' if ((!(isProto && nonEnum[key]) && hasOwnProperty.call(object, key))<%' + + ' if (!useHas) { %> || (!nonEnum[key] && object[key] !== objectProto[key])<% }' + + ' %>) {\n' + + ' <%= loop %>;\n' + + ' }' + + ' <% } %>\n' + + '}' + + '<% } %>\n' + + + 'return result;' + ); - while (++index < length) { - result[index] = callback(array[index], index, array); - } - return result; - } + /*--------------------------------------------------------------------------*/ /** * The base implementation of `_.bind` that creates the bound function and - * sets its metadata. + * sets its meta data. * * @private * @param {Array} data The metadata array. @@ -1064,8 +1020,8 @@ // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` var index = -1, - length = arguments.length, - args = Array(length); + length = arguments.length, + args = Array(length); while (++index < length) { args[index] = arguments[index]; @@ -1089,7 +1045,7 @@ /** * The base implementation of `_.clone` without argument juggling or support - * for `this` binding. + * for `thisArg` binding. * * @private * @param {*} value The value to clone. @@ -1106,6 +1062,7 @@ return result; } } + // inspect [[Class]] var isObj = isObject(value); if (isObj) { var className = toString.call(value); @@ -1133,6 +1090,7 @@ var isArr = isArray(value); if (isDeep) { // check for circular references and return corresponding clone + var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); @@ -1166,8 +1124,8 @@ stackB.push(result); // recursively populate clone (susceptible to call stack limits) - (isArr ? arrayEach : baseForOwn)(value, function(valValue, key) { - result[key] = baseClone(valValue, isDeep, callback, stackA, stackB); + (isArr ? baseEach : baseForOwn)(value, function(objValue, key) { + result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); }); return result; @@ -1207,7 +1165,7 @@ * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns the new function. + * @returns {Function} Returns a callback function. */ function baseCreateCallback(func, thisArg, argCount) { if (typeof func != 'function') { @@ -1243,8 +1201,8 @@ case 1: return function(value) { return func.call(thisArg, value); }; - case 2: return function(value, other) { - return func.call(thisArg, value, other); + case 2: return function(a, b) { + return func.call(thisArg, a, b); }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); @@ -1258,7 +1216,7 @@ /** * The base implementation of `createWrapper` that creates the wrapper and - * sets its metadata. + * sets its meta data. * * @private * @param {Array} data The metadata array. @@ -1294,19 +1252,14 @@ if (partialRightArgs) { args = composeArgsRight(partialRightArgs, partialRightHolders, args); } - if (isCurry) { - var newPartialHolders = getHolders(args); - length -= newPartialHolders.length; - - if (length < arity) { - bitmask |= PARTIAL_FLAG; - bitmask &= ~PARTIAL_RIGHT_FLAG - if (!isCurryBound) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); - } - var newArity = nativeMax(arity - length, 0); - return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, newPartialHolders]); + if (isCurry && length < arity) { + bitmask |= PARTIAL_FLAG; + bitmask &= ~PARTIAL_RIGHT_FLAG + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } + var newArity = nativeMax(0, arity - length); + return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, []]); } var thisBinding = isBind ? thisArg : this; if (isBindKey) { @@ -1330,7 +1283,7 @@ * @private * @param {Array} array The array to process. * @param {Array} [values] The array of values to exclude. - * @returns {Array} Returns the new array of filtered values. + * @returns {Array} Returns a new array of filtered values. */ function baseDifference(array, values) { var length = array ? array.length : 0; @@ -1371,7 +1324,7 @@ /** * The base implementation of `_.forEach` without support for callback - * shorthands or `this` binding. + * shorthands or `thisArg` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -1383,7 +1336,7 @@ iterable = collection, length = collection ? collection.length : 0; - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + if (typeof length == 'number') { if (support.unindexedChars && isString(iterable)) { iterable = iterable.split(''); } @@ -1400,7 +1353,7 @@ /** * The base implementation of `_.forEachRight` without support for callback - * shorthands or `this` binding. + * shorthands or `thisArg` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -1411,7 +1364,7 @@ var iterable = collection, length = collection ? collection.length : 0; - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + if (typeof length == 'number') { if (support.unindexedChars && isString(iterable)) { iterable = iterable.split(''); } @@ -1426,41 +1379,16 @@ return collection; } - /** - * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey` - * without support for callback shorthands or `this` binding which iterates - * over `collection` using the provided `eachFunc`. - * - * @private - * @param {Array|Object|string} collection The collection to search. - * @param {Function} predicate The function called per iteration. - * @param {Function} eachFunc The function to iterate over the collection. - * @param {boolean} [retKey=false] A flag to indicate returning the key of - * the found element instead of the element itself. - * @returns {*} Returns the found element or its key, else `undefined`. - */ - function baseFind(collection, predicate, eachFunc, retKey) { - var result; - - eachFunc(collection, function(value, key, collection) { - if (predicate(value, key, collection)) { - result = retKey ? key : value; - return false; - } - }); - return result; - } - /** * The base implementation of `_.flatten` without support for callback - * shorthands or `this` binding. + * shorthands or `thisArg` binding. * * @private * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. - * @returns {Array} Returns the new flattened array. + * @returns {Array} Returns a new flattened array. */ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, @@ -1492,20 +1420,17 @@ } /** - * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing the callback - * for each property. Callbacks may exit iteration early by explicitly - * returning `false`. + * The base implementation of `_.forOwn` without support for callback + * shorthands or `thisArg` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. - * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseFor(object, callback, keysFunc) { + function baseForOwn(object, callback) { var index = -1, - props = keysFunc(object), + props = keys(object), length = props.length; while (++index < length) { @@ -1518,17 +1443,16 @@ } /** - * This function is like `baseFor` except that it iterates over properties - * in the opposite order. + * The base implementation of `_.forOwnRight` without support for callback + * shorthands or `thisArg` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. - * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForRight(object, callback, keysFunc) { - var props = keysFunc(object), + function baseForOwnRight(object, callback) { + var props = keys(object), length = props.length; while (length--) { @@ -1541,190 +1465,137 @@ } /** - * The base implementation of `_.forIn` without support for callback - * shorthands or `this` binding. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Object} Returns `object`. - */ - function baseForIn(object, callback) { - return baseFor(object, callback, keysIn); - } - - /** - * The base implementation of `_.forOwn` without support for callback - * shorthands or `this` binding. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Object} Returns `object`. - */ - function baseForOwn(object, callback) { - return baseFor(object, callback, keys); - } - - /** - * The base implementation of `_.forOwnRight` without support for callback - * shorthands or `this` binding. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Object} Returns `object`. - */ - function baseForOwnRight(object, callback) { - return baseForRight(object, callback, keys); - } - - /** - * The base implementation of `_.isEqual`, without support for `thisArg` - * binding, that allows partial "_.where" style comparisons. + * The base implementation of `_.isEqual`, without support for `thisArg` binding, + * that allows partial "_.where" style comparisons. * * @private - * @param {*} value The value to compare to `other`. - * @param {*} other The value to compare to `value`. + * @param {*} a The value to compare. + * @param {*} b The other value to compare. * @param {Function} [callback] The function to customize comparing values. * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `value` objects. - * @param {Array} [stackB=[]] Tracks traversed `other` objects. + * @param {Array} [stackA=[]] Tracks traversed `a` objects. + * @param {Array} [stackB=[]] Tracks traversed `b` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ - function baseIsEqual(value, other, callback, isWhere, stackA, stackB) { + function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { if (callback) { - var result = callback(value, other); + var result = callback(a, b); if (typeof result != 'undefined') { return !!result; } } // exit early for identical values - if (value === other) { + if (a === b) { // treat `+0` vs. `-0` as not equal - return value !== 0 || (1 / value == 1 / other); + return a !== 0 || (1 / a == 1 / b); } - var valType = typeof value, - othType = typeof other; + var type = typeof a, + otherType = typeof b; // exit early for unlike primitive values - if (value === value && (value == null || other == null || - (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { + if (a === a && (a == null || b == null || + (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { return false; } - var valClass = toString.call(value), - othClass = toString.call(other), - valIsArg = valClass == argsClass, - othIsArg = othClass == argsClass; + // compare [[Class]] names + var className = toString.call(a), + otherClass = toString.call(b); - if (valIsArg) { - valClass = objectClass; + if (className == argsClass) { + className = objectClass; } - if (othIsArg) { - othClass = objectClass; + if (otherClass == argsClass) { + otherClass = objectClass; } - if (valClass != othClass) { + if (className != otherClass) { return false; } - switch (valClass) { + switch (className) { case boolClass: case dateClass: // coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +value == +other; + return +a == +b; case numberClass: // treat `NaN` vs. `NaN` as equal - return (value != +value) - ? other != +other + return (a != +a) + ? b != +b // but treat `-0` vs. `+0` as not equal - : (value == 0 ? (1 / value == 1 / other) : value == +other); + : (a == 0 ? (1 / a == 1 / b) : a == +b); case regexpClass: case stringClass: // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) // treat string primitives and their corresponding object instances as equal - return value == String(other); + return a == String(b); } - var isArr = valClass == arrayClass; + var isArr = className == arrayClass; if (!isArr) { - // exit for functions and DOM nodes - if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) { - return false; - } // unwrap any `lodash` wrapped values - var valWrapped = hasOwnProperty.call(value, '__wrapped__'), - othWrapped = hasOwnProperty.call(other, '__wrapped__'); + var aWrapped = hasOwnProperty.call(a, '__wrapped__'), + bWrapped = hasOwnProperty.call(b, '__wrapped__'); - if (valWrapped || othWrapped) { - return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, callback, isWhere, stackA, stackB); + if (aWrapped || bWrapped) { + return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); } - if (!support.argsObject) { - valIsArg = isArguments(value); - othIsArg = isArguments(other); - } - var hasValCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), - hasOthCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); - - if (hasValCtor != hasOthCtor) { + // exit for functions and DOM nodes + if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) { return false; } - if (!hasValCtor) { - // in older versions of Opera, `arguments` objects have `Array` constructors - var valCtor = valIsArg ? Object : value.constructor, - othCtor = othIsArg ? Object : other.constructor; - - // non `Object` object instances with different constructors are not equal - if (valCtor != othCtor && - !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && - ('constructor' in value && 'constructor' in other) - ) { - return false; - } + // in older versions of Opera, `arguments` objects have `Array` constructors + var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor, + ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor; + + // non `Object` object instances with different constructors are not equal + if (ctorA != ctorB && + !(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) && + !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && + ('constructor' in a && 'constructor' in b) + ) { + return false; } } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) + var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { - if (stackA[length] == value) { - return stackB[length] == other; + if (stackA[length] == a) { + return stackB[length] == b; } } var size = 0; result = true; - // add `value` and `other` to the stack of traversed objects - stackA.push(value); - stackB.push(other); + // add `a` and `b` to the stack of traversed objects + stackA.push(a); + stackB.push(b); // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { // compare lengths to determine if a deep comparison is necessary - length = value.length; - size = other.length; + length = a.length; + size = b.length; result = size == length; if (result || isWhere) { // deep compare the contents, ignoring non-numeric properties while (size--) { var index = length, - othValue = other[size]; + value = b[size]; if (isWhere) { while (index--) { - if ((result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB))) { + if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { break; } } - if (!result) { - break; - } - } else if (!(result = baseIsEqual(value[size], othValue, callback, isWhere, stackA, stackB))) { + } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { break; } } @@ -1733,20 +1604,20 @@ else { // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` // which, in this case, is more costly - baseForIn(other, function(othValue, key, other) { - if (hasOwnProperty.call(other, key)) { + baseForIn(b, function(value, key, b) { + if (hasOwnProperty.call(b, key)) { // count the number of properties. size++; // deep compare each property value. - return (result = hasOwnProperty.call(value, key) && baseIsEqual(value[key], othValue, callback, isWhere, stackA, stackB)); + return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); } }); if (result && !isWhere) { // ensure both objects have the same number of properties - baseForIn(value, function(valValue, key, value) { - if (hasOwnProperty.call(value, key)) { - // `size` will be `-1` if `value` has more properties than `other` + baseForIn(a, function(value, key, a) { + if (hasOwnProperty.call(a, key)) { + // `size` will be `-1` if `a` has more properties than `b` return (result = --size > -1); } }); @@ -1760,7 +1631,7 @@ /** * The base implementation of `_.merge` without argument juggling or support - * for `this` binding. + * for `thisArg` binding. * * @private * @param {Object} object The destination object. @@ -1770,7 +1641,7 @@ * @param {Array} [stackB=[]] Associates values with source counterparts. */ function baseMerge(object, source, callback, stackA, stackB) { - (isArray(source) ? arrayEach : baseForOwn)(source, function(source, key) { + (isArray(source) ? baseEach : baseForOwn)(source, function(source, key) { var found, isArr, result = source, @@ -1830,7 +1701,7 @@ * @private * @param {number} min The minimum possible value. * @param {number} max The maximum possible value. - * @returns {number} Returns the random number. + * @returns {number} Returns a random number. */ function baseRandom(min, max) { return min + floor(nativeRandom() * (max - min + 1)); @@ -1838,13 +1709,13 @@ /** * The base implementation of `_.uniq` without support for callback shorthands - * or `this` binding. + * or `thisArg` binding. * * @private * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. - * @returns {Array} Returns the new duplicate-value-free array. + * @returns {Array} Returns a duplicate-value-free array. */ function baseUniq(array, isSorted, callback) { var length = array ? array.length : 0; @@ -1897,37 +1768,15 @@ return result; } - /** - * The base implementation of `_.values` and `_.valuesIn` which creates an - * array of `object` property values corresponding to the property names - * returned by `keysFunc`. - * - * @private - * @param {Object} object The object to inspect. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Object} Returns the array of property values. - */ - function baseValues(object, keysFunc) { - var index = -1, - props = keysFunc(object), - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; - } - return result; - } - /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private - * @param {Array} partialArgs An array of arguments to prepend to those provided. + * @param {Array} partialArg An array of arguments to prepend to those provided. * @param {Array} partialHolders An array of `partialArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. - * @returns {Array} Returns the new array of composed arguments. + * @returns {Array} Returns a new array of composed arguments. */ function composeArgs(partialArgs, partialHolders, args) { var holdersLength = partialHolders.length, @@ -1954,10 +1803,10 @@ * is tailored for `_.partialRight`. * * @private - * @param {Array} partialRightArgs An array of arguments to append to those provided. + * @param {Array} partialRightArg An array of arguments to append to those provided. * @param {Array} partialHolders An array of `partialRightArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. - * @returns {Array} Returns the new array of composed arguments. + * @returns {Array} Returns a new array of composed arguments. */ function composeArgsRight(partialRightArgs, partialRightHolders, args) { var holdersIndex = -1, @@ -1982,22 +1831,22 @@ } /** - * Creates a function that aggregates a collection, creating an accumulator - * object composed from the results of running each element in the collection - * through a callback. The given setter function sets the keys and values of - * the accumulator object. If `initializer` is provided will be used to - * initialize the accumulator object. + * Creates a function that aggregates a collection, creating an object or + * array composed from the results of running each element of the collection + * through a callback. The given `setter` function sets the keys and values + * of the composed object or array. * * @private - * @param {Function} setter The function to set keys and values of the accumulator object. - * @param {Function} [initializer] The function to initialize the accumulator object. + * @param {Function} setter The setter function. + * @param {boolean} [retArray=false] A flag to indicate that the aggregator + * function should return an array. * @returns {Function} Returns the new aggregator function. */ - function createAggregator(setter, initializer) { + function createAggregator(setter, retArray) { return function(collection, callback, thisArg) { - var result = initializer ? initializer() : {}; - callback = lodash.createCallback(callback, thisArg, 3); + var result = retArray ? [[], []] : {}; + callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; @@ -2020,7 +1869,7 @@ * * @private * @param {Array} [array=[]] The array to search. - * @returns {Object} Returns the new cache object. + * @returns {Object} Returns the cache object. */ var createCache = Set && function(array) { var cache = new Set, @@ -2034,31 +1883,8 @@ }; /** - * Creates the pad required for `string` based on the given padding length. - * The `chars` string may be truncated if the number of padding characters - * exceeds the padding length. - * - * @private - * @param {string} string The string to create padding for. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the pad for `string`. - */ - function createPad(string, length, chars) { - var strLength = string.length; - length = +length; - - if (strLength >= length || !nativeIsFinite(length)) { - return ''; - } - var padLength = length - strLength; - chars = chars == null ? ' ' : String(chars); - return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); - } - - /** - * Creates a function that either curries or invokes `func` with an optional - * `this` binding and partially applied arguments. + * Creates a function that, when called, either curries or invokes `func` + * with an optional `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to reference. @@ -2076,16 +1902,18 @@ * provided to the new function. * @param {Array} [partialRightArgs] An array of arguments to append to those * provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ - function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) { + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isPartial = bitmask & PARTIAL_FLAG, isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (!isBindKey && !isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } if (isPartial && !partialArgs.length) { bitmask &= ~PARTIAL_FLAG; @@ -2141,17 +1969,17 @@ data[1] |= bitmask; return createWrapper.apply(null, data); } + if (arity == null) { + arity = isBindKey ? 0 : func.length; + } else if (arity < 0) { + arity = 0; + } if (isPartial) { - var partialHolders = getHolders(partialArgs); + partialHolders = getHolders(partialArgs); } if (isPartialRight) { - var partialRightHolders = getHolders(partialRightArgs); - } - if (arity == null) { - arity = isBindKey ? 0 : func.length; + partialRightHolders = getHolders(partialRightArgs); } - arity = nativeMax(arity, 0); - // fast path for `_.bind` data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders]; return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) @@ -2160,11 +1988,40 @@ } /** - * Finds the indexes of all placeholder elements in `array`. + * Creates compiled iteration functions. + * + * @private + * @param {Object} [options] The compile options object. + * @param {string} [options.args] A comma separated string of iteration function arguments. + * @param {string} [options.init] The string representation of the initial `result` value. + * @param {string} [options.loop] Code to execute in the object loop. + * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop. + * @returns {Function} Returns the compiled function. + */ + function createIterator(options) { + options.shadowedProps = shadowedProps; + options.support = support; + + // create the function factory + var factory = Function( + 'errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, ' + + 'nonEnumProps, stringClass, stringProto, toString', + 'return function(' + options.args + ') {\n' + iteratorTemplate(options) + '\n}' + ); + + // return the compiled function + return factory( + errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, + nonEnumProps, stringClass, stringProto, toString + ); + } + + /** + * Finds the indexes of all placeholder elements in a given array. * * @private * @param {Array} array The array to inspect. - * @returns {Array} Returns the new array of placeholder indexes. + * @returns {Array} Returns a new array of placeholder indexes. */ function getHolders(array) { var index = -1, @@ -2181,15 +2038,15 @@ /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized this function returns the custom method, otherwise it returns + * customized this method returns the custom method, otherwise it returns * the `baseIndexOf` function. * * @private * @returns {Function} Returns the "indexOf" function. */ function getIndexOf() { - var result = lodash.indexOf || indexOf; - return result === indexOf ? baseIndexOf : result; + var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result; + return result; } /** @@ -2197,7 +2054,7 @@ * * @private * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. */ function isNative(value) { return typeof value == 'function' && reNative.test(fnToString.call(value)); @@ -2216,9 +2073,10 @@ }; /** - * A fallback implementation of `_.isPlainObject` which checks if `value` - * is an object created by the `Object` constructor or has a `[[Prototype]]` - * of `null`. + * A fallback implementation of `isPlainObject` which checks if a given value + * is an object created by the `Object` constructor, assuming objects created + * by the `Object` constructor have no inherited enumerable properties and that + * there are no `Object.prototype` extensions. * * @private * @param {*} value The value to check. @@ -2228,7 +2086,7 @@ var ctor, result; - // avoid non `Object` objects, `arguments` objects, and DOM elements + // avoid non Object objects, `arguments` objects, and DOM elements if (!(value && toString.call(value) == objectClass) || (!hasOwnProperty.call(value, 'constructor') && (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) || @@ -2255,242 +2113,126 @@ return typeof result == 'undefined' || hasOwnProperty.call(value, result); } - /** - * A fallback implementation of `Object.keys` which creates an array of the - * own enumerable property names of `object`. - * - * @private - * @param {Object} object The object to inspect. - * @returns {Array} Returns the array of property names. - */ - function shimKeys(object) { - var keyIndex, - index = -1, - props = keysIn(object), - length = props.length, - objLength = length && object.length, - maxIndex = objLength - 1, - result = []; - - var allowIndexes = typeof objLength == 'number' && objLength > 0 && - (isArray(object) || (support.nonEnumArgs && isArguments(object)) || - (support.nonEnumStrings && isString(object))); - - while (++index < length) { - var key = props[index]; - if ((allowIndexes && (keyIndex = +key, keyIndex > -1 && keyIndex <= maxIndex && keyIndex % 1 == 0)) || - hasOwnProperty.call(object, key)) { - result.push(key); - } - } - return result; - } - /*--------------------------------------------------------------------------*/ /** - * Creates an array with all falsey values removed. The values `false`, `null`, - * `0`, `""`, `undefined`, and `NaN` are all falsey. + * Checks if `value` is an `arguments` object. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to compact. - * @returns {Array} Returns the new array of filtered values. + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`. * @example * - * _.compact([0, 1, false, 2, '', 3]); - * // => [1, 2, 3] + * (function() { return _.isArguments(arguments); })(1, 2, 3); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false */ - function compact(array) { - var index = -1, - length = array ? array.length : 0, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index]; - if (value) { - result[resIndex++] = value; - } - } - return result; - } + function isArguments(value) { + return value && typeof value == 'object' && typeof value.length == 'number' && + toString.call(value) == argsClass || false; + } + // fallback for environments that can't detect `arguments` objects by [[Class]] + if (!support.argsClass) { + isArguments = function(value) { + return value && typeof value == 'object' && typeof value.length == 'number' && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false; + }; + } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. - * - * @static - * @memberOf _ - * @category Arrays - * @param {Array} array The array to process. - * @param {...Array} [values] The arrays of values to exclude. - * @returns {Array} Returns the new array of filtered values. - * @example + * The base implementation of `_.forIn` without support for callback + * shorthands or `thisArg` binding. * - * _.difference([1, 2, 3], [5, 2, 10]); - * // => [1, 3] + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Object} Returns `object`. */ - function difference() { - var index = -1, - length = arguments.length; - - while (++index < length) { - var value = arguments[index]; - if (isArray(value) || isArguments(value)) { - break; - } - } - return baseDifference(arguments[index], baseFlatten(arguments, true, true, ++index)); - } + var baseForIn = createIterator({ + 'args': 'object, callback', + 'init': 'object', + 'loop': 'if (callback(object[key], key, object) === false) {\n return result;\n }', + 'useHas': false + }); /** - * Creates a slice of `array` with `n` elements dropped from the beginning. + * A fallback implementation of `Object.keys` which produces an array of the + * given object's own enumerable property names. * - * @static - * @memberOf _ + * @private * @type Function - * @category Arrays - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to drop. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.drop([1, 2, 3], 1); - * // => [2, 3] - * - * _.drop([1, 2, 3], 2); - * // => [3] - * - * _.drop([1, 2, 3], 5); - * // => [] - * - * _.drop([1, 2, 3], 0); - * // => [1, 2, 3] + * @param {Object} object The object to inspect. + * @returns {Array} Returns an array of property names. */ - var drop = rest; + var shimKeys = createIterator({ + 'args': 'object', + 'init': '[]', + 'loop': 'result.push(key)', + 'useHas': true + }); + + /*--------------------------------------------------------------------------*/ /** - * Creates a slice of `array` with `n` elements dropped from the end. + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are all falsey. * * @static * @memberOf _ - * @type Function * @category Arrays - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to drop. - * @returns {Array} Returns the slice of `array`. + * @param {Array} array The array to compact. + * @returns {Array} Returns a new array of filtered values. * @example * - * _.dropRight([1, 2, 3], 1); - * // => [1, 2] - * - * _.dropRight([1, 2, 3], 2); - * // => [1] - * - * _.dropRight([1, 2, 3], 5); - * // => [] - * - * _.dropRight([1, 2, 3], 0); + * _.compact([0, 1, false, 2, '', 3]); * // => [1, 2, 3] */ - var dropRight = initial; + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; - /** - * Creates a slice of `array` excluding elements dropped from the end. - * Elements will be dropped until the predicate returns falsey. The predicate - * is bound to `thisArg` and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called - * per element. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.dropRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [1] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate' }, - * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.dropRightWhile(characters, 'blocked'), 'name'); - * // => ['barney'] - * - * // using "_.where" callback shorthand - * _.pluck(_.dropRightWhile(characters, { 'employer': 'na' }), 'name'); - * // => ['barney', 'fred'] - */ - var dropRightWhile = initial; + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } /** - * Creates a slice of `array` excluding elements dropped from the beginning. - * Elements will be dropped until the predicate returns falsey. The predicate - * is bound to `thisArg` and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates an array excluding all values of the provided arrays using strict + * equality for comparisons, i.e. `===`. * * @static * @memberOf _ - * @type Function * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called - * per element. - * @returns {Array} Returns the slice of `array`. + * @param {Array} array The array to process. + * @param {...Array} [values] The arrays of values to exclude. + * @returns {Array} Returns a new array of filtered values. * @example * - * _.dropWhile([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [3] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, - * { 'name': 'fred', 'employer': 'slate' }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.dropWhile(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.pluck(_.dropWhile(characters, { 'employer': 'slate' }), 'name'); - * // => ['pebbles'] + * _.difference([1, 2, 3], [5, 2, 10]); + * // => [1, 3] */ - var dropWhile = rest; + function difference(array) { + return baseDifference(array, baseFlatten(arguments, true, true, 1)); + } /** * This method is like `_.find` except that it returns the index of the first - * element the predicate returns truthy for, instead of the element itself. + * element that passes the callback check, instead of the element itself. * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -2498,10 +2240,10 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index of the found element, else `-1`. * @example * @@ -2524,13 +2266,13 @@ * _.findIndex(characters, 'blocked'); * // => 1 */ - function findIndex(array, predicate, thisArg) { + function findIndex(array, callback, thisArg) { var index = -1, length = array ? array.length : 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); while (++index < length) { - if (predicate(array[index], index, array)) { + if (callback(array[index], index, array)) { return index; } } @@ -2539,12 +2281,12 @@ /** * This method is like `_.findIndex` except that it iterates over elements - * of a collection from right to left. + * of a `collection` from right to left. * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -2552,10 +2294,10 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index of the found element, else `-1`. * @example * @@ -2578,12 +2320,12 @@ * _.findLastIndex(characters, 'blocked'); * // => 2 */ - function findLastIndex(array, predicate, thisArg) { + function findLastIndex(array, callback, thisArg) { var length = array ? array.length : 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); while (length--) { - if (predicate(array[length], length, array)) { + if (callback(array[length], length, array)) { return length; } } @@ -2591,47 +2333,80 @@ } /** - * Gets the first element of `array`. + * Gets the first element or first `n` elements of an array. If a callback + * is provided elements at the beginning of the array are returned as long + * as the callback returns truey. The callback is bound to `thisArg` and + * invoked with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.take` and `_.takeWhile` respectively. + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @alias head + * @alias head, take * @category Arrays * @param {Array} array The array to query. - * @returns {*} Returns the first element of `array`. + * @param {Function|Object|number|string} [callback] The function called + * per element or the number of elements to return. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the first element(s) of `array`. * @example * * _.first([1, 2, 3]); * // => 1 * - * _.first([]); - * // => undefined + * // returns the first two elements + * _.first([1, 2, 3], 2); + * // => [1, 2] + * + * // returns elements from the beginning until the callback result is falsey + * _.first([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [1, 2] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, + * { 'name': 'fred', 'employer': 'slate' }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.first(characters, 'blocked'); + * // => [{ 'name': 'barney', 'employer': 'slate', 'blocked': true }] + * + * // using "_.where" callback shorthand + * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); + * // => ['barney', 'fred'] */ - function first(array, predicate, thisArg) { - if (typeof predicate != 'number' && predicate != null) { + function first(array, callback, thisArg) { + if (typeof callback != 'number' && callback != null) { var index = -1, length = array ? array.length : 0, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { + callback = lodash.createCallback(callback, thisArg, 3); + while (++index < length && callback(array[index], index, array)) { n++; } } else { - n = predicate; + n = callback; if (n == null || thisArg) { return array ? array[0] : undefined; } } - return slice(array, 0, n < 0 ? 0 : n); + return slice(array, 0, n > 0 ? n : 0); } /** * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truthy, the array will only be flattened a single level. If a callback + * is truey, the array will only be flattened a single level. If a callback * is provided each element of the array is passed through the callback before * flattening. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). @@ -2648,11 +2423,11 @@ * @category Arrays * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" - * or "_.where" style callback respectively. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns the new flattened array. + * @returns {Array} Returns a new flattened array. * @example * * _.flatten([1, [2], [3, [[4]]]]); @@ -2706,7 +2481,7 @@ * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=0] The index to search from or `true` * to perform a binary search on a sorted array. - * @returns {number} Returns the index of the matched value, else `-1`. + * @returns {number} Returns the index of the matched value or `-1`. * @example * * _.indexOf([1, 2, 3, 1, 2, 3], 2); @@ -2723,7 +2498,7 @@ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (typeof fromIndex == 'number') { - fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); + fromIndex = fromIndex < 0 ? nativeMax(0, length + fromIndex) : (fromIndex || 0); } else if (fromIndex) { var index = sortedIndex(array, value); return (length && array[index] === value) ? index : -1; @@ -2732,37 +2507,73 @@ } /** - * Gets all but the last element of `array`. + * Gets all but the last element or last `n` elements of an array. If a + * callback is provided elements at the end of the array are excluded from + * the result as long as the callback returns truey. The callback is bound + * to `thisArg` and invoked with three arguments; (value, index, array). * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.dropRight` and `_.dropRightWhile` respectively. + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to query. - * @returns {Array} Returns the slice of `array`. + * @param {Function|Object|number|string} [callback=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. * @example * * _.initial([1, 2, 3]); * // => [1, 2] + * + * // excludes the last two elements + * _.initial([1, 2, 3], 2); + * // => [1] + * + * // excludes elements from the end until the callback fails + * _.initial([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [1] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate' }, + * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.initial(characters, 'blocked'); + * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }] + * + * // using "_.where" callback shorthand + * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); + * // => ['barney', 'fred'] */ - function initial(array, predicate, thisArg) { + function initial(array, callback, thisArg) { var length = array ? array.length : 0; - if (typeof predicate != 'number' && predicate != null) { + if (typeof callback != 'number' && callback != null) { var index = length, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { + callback = lodash.createCallback(callback, thisArg, 3); + while (index-- && callback(array[index], index, array)) { n++; } } else { - n = (predicate == null || thisArg) ? 1 : predicate; + n = (callback == null || thisArg) ? 1 : callback; } - n = length - (n || 0); - return slice(array, 0, n < 0 ? 0 : n); + n = length - n; + return slice(array, 0, n > 0 ? n : 0); } /** @@ -2772,8 +2583,8 @@ * @static * @memberOf _ * @category Arrays - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of shared values. + * @param {...Array} [array] The arrays to inspect. + * @returns {Array} Returns an array of shared values. * @example * * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); @@ -2785,37 +2596,36 @@ argsLength = arguments.length, caches = [], indexOf = getIndexOf(), - prereq = createCache && indexOf === baseIndexOf; + prereq = createCache && indexOf === baseIndexOf, + seen = []; while (++argsIndex < argsLength) { var value = arguments[argsIndex]; if (isArray(value) || isArguments(value)) { args.push(value); caches.push(prereq && value.length >= 120 && - createCache(argsIndex && value)); + createCache(argsIndex ? args[argsIndex] : seen)); } } - argsLength = args.length; var array = args[0], index = -1, length = array ? array.length : 0, - result = [], - seen = caches[0]; + result = []; outer: while (++index < length) { + var cache = caches[0]; value = array[index]; - if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) { + + if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { argsIndex = argsLength; + (cache || seen).push(value); while (--argsIndex) { - var cache = caches[argsIndex]; + cache = caches[argsIndex]; if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { continue outer; } } - if (seen) { - seen.push(value); - } result.push(value); } } @@ -2823,46 +2633,89 @@ } /** - * Gets the last element of `array`. + * Gets the last element or last `n` elements of an array. If a callback is + * provided elements at the end of the array are returned as long as the + * callback returns truey. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.takeRight` and `_.takeRightWhile` respectively. + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to query. - * @returns {*} Returns the last element of `array`. + * @param {Function|Object|number|string} [callback] The function called + * per element or the number of elements to return. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the last element(s) of `array`. * @example * * _.last([1, 2, 3]); * // => 3 + * + * // returns the last two elements + * _.last([1, 2, 3], 2); + * // => [2, 3] + * + * // returns elements from the end until the callback fails + * _.last([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [2, 3] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate' }, + * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.last(characters, 'blocked'), 'name'); + * // => ['fred', 'pebbles'] + * + * // using "_.where" callback shorthand + * _.last(characters, { 'employer': 'na' }); + * // => [{ 'name': 'pebbles', 'employer': 'na', 'blocked': true }] */ - function last(array, predicate, thisArg) { + function last(array, callback, thisArg) { var length = array ? array.length : 0; - if (typeof predicate != 'number' && predicate != null) { + if (typeof callback != 'number' && callback != null) { var index = length, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { + callback = lodash.createCallback(callback, thisArg, 3); + while (index-- && callback(array[index], index, array)) { n++; } } else { - n = predicate; + n = callback; if (n == null || thisArg) { return array ? array[length - 1] : undefined; } } - n = length - (n || 0); - return slice(array, n < 0 ? 0 : n); + n = length - n; + return slice(array, n > 0 ? n : 0); } /** - * Gets the index at which the last occurrence of `value` is found using - * strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, - * it is used as the offset from the end of the collection. + * Gets the index at which the last occurrence of `value` is found using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ @@ -2870,7 +2723,7 @@ * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. + * @returns {number} Returns the index of the matched value or `-1`. * @example * * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); @@ -2883,7 +2736,7 @@ function lastIndexOf(array, value, fromIndex) { var index = array ? array.length : 0; if (typeof fromIndex == 'number') { - index = (fromIndex < 0 ? nativeMax(index + fromIndex, 0) : nativeMin(fromIndex || 0, index - 1)) + 1; + index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; } while (index--) { if (array[index] === value) { @@ -2897,13 +2750,11 @@ * Removes all provided values from `array` using strict equality for * comparisons, i.e. `===`. * - * Note: Unlike `_.without`, this method mutates `array`. - * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to modify. - * @param {...*} [values] The values to remove. + * @param {...*} [value] The values to remove. * @returns {Array} Returns `array`. * @example * @@ -2932,48 +2783,99 @@ } /** - * Removes all elements from `array` that the predicate returns truthy for - * and returns an array of removed elements. The predicate is bound to `thisArg` - * and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * Note: Unlike `_.filter`, this method mutates `array`. + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `end`. If `start` is less than `stop` a + * zero-length range is created unless a negative `step` is specified. * * @static * @memberOf _ * @category Arrays - * @param {Array} array The array to modify. - * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the array of removed elements. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns a new range array. * @example * - * var array = [1, 2, 3, 4, 5, 6]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); - * - * console.log(array); - * // => [1, 3, 5] + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + start = +start || 0; + step = typeof step == 'number' ? step : (+step || 1); + + if (end == null) { + end = start; + start = 0; + } + // use `Array(length)` so engines like Chakra and V8 avoid slower modes + // http://youtu.be/XAqIpGU8ZZk#t=17m25s + var index = -1, + length = nativeMax(0, ceil((end - start) / (step || 1))), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + + /** + * Removes all elements from an array that the callback returns truey for + * and returns an array of removed elements. The callback is bound to `thisArg` + * and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to modify. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4, 5, 6]; + * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * + * console.log(array); + * // => [1, 3, 5] * * console.log(evens); * // => [2, 4, 6] */ - function remove(array, predicate, thisArg) { + function remove(array, callback, thisArg) { var index = -1, length = array ? array.length : 0, result = []; - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); while (++index < length) { var value = array[index]; - if (predicate(value, index, array)) { + if (callback(value, index, array)) { result.push(value); splice.call(array, index--, 1); length--; @@ -2983,36 +2885,124 @@ } /** - * Gets all but the first element of `array`. + * Removes elements located at the given indexes and returns an array of + * removed elements. A hybrid of "_.remove" and "_.at". Indexes may be + * specified as an array of indexes or as individual arguments. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to modify. + * @param {...(number|number[])} [index] The indexes of `array` to remove + * @returns {Array} Returns a new array of removed elements. + * @example + * + * var array = [5, 10, 15, 20, 25, 30]; + * var evens = _.removeAt(array, [1, 3, 5]); + * + * console.log(array); + * // => [5, 15, 25] + * + * console.log(evens); + * // => [10, 20, 30] + * + * var greeting = ('good morning').split(''); + * var vowels = _.removeAt(greeting, 1, 2, 6, 9); + * + * console.log(greeting.join('')); + * // => 'gd mrnng' + * + * console.log(vowels.join('')); + * // => 'oooi' + */ + function removeAt(array, guard) { + var args = arguments, + index = -1, + removals = baseFlatten(args, true, false, 1), + length = removals.length; + + // enables use as a callback for functions like `_.map` + if (typeof guard == 'number' && args[2] && args[2][guard] === array) { + length = 1; + } else { + removals.sort(baseCompareAscending); + } + var result = Array(length); + while(++index < length) { + result[index] = splice.call(array, removals[index] - index, 1)[0]; + } + return result; + } + + + /** + * The opposite of `_.initial`; this method gets all but the first element or + * first `n` elements of an array. If a callback function is provided elements + * at the beginning of the array are excluded from the result as long as the + * callback returns truey. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). + * + * If a property name is provided for `callback` the created "_.pluck" style + * callback will return the property value of the given element. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.drop` and `_.dropWhile` respectively. + * If an object is provided for `callback` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ - * @alias tail + * @alias drop, tail * @category Arrays * @param {Array} array The array to query. - * @returns {Array} Returns the slice of `array`. + * @param {Function|Object|number|string} [callback=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is provided it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. * @example * * _.rest([1, 2, 3]); * // => [2, 3] + * + * // excludes the first two elements + * _.rest([1, 2, 3], 2); + * // => [3] + * + * // excludes elements from the beginning until the callback fails + * _.rest([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [3] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, + * { 'name': 'fred', 'employer': 'slate' }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.rest(characters, 'blocked'), 'name'); + * // => ['fred', 'pebbles'] + * + * // using "_.where" callback shorthand + * _.rest(characters, { 'employer': 'slate' }); + * // => [{ 'name': 'pebbles', 'employer': 'na', 'blocked': true }] */ - function rest(array, predicate, thisArg) { - if (typeof predicate != 'number' && predicate != null) { + function rest(array, callback, thisArg) { + if (typeof callback != 'number' && callback != null) { var index = -1, length = array ? array.length : 0, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { + callback = lodash.createCallback(callback, thisArg, 3); + while (++index < length && callback(array[index], index, array)) { n++; } - } else if (predicate == null || thisArg) { + } else if (callback == null || thisArg) { n = 1; } else { - n = predicate < 0 ? 0 : predicate; + n = callback > 0 ? callback : 0; } return slice(array, n); } @@ -3029,25 +3019,27 @@ * @param {Array} array The array to slice. * @param {number} [start=0] The start index. * @param {number} [end=array.length] The end index. - * @returns {Array} Returns the slice of `array`. + * @returns {Array} Returns the new array. */ function slice(array, start, end) { var index = -1, length = array ? array.length : 0; - start = typeof start == 'undefined' ? 0 : (+start || 0); - if (start < 0) { + if (typeof start == 'undefined') { + start = 0; + } else if (start < 0) { start = nativeMax(length + start, 0); } else if (start > length) { start = length; } - end = typeof end == 'undefined' ? length : (+end || 0); - if (end < 0) { + if (typeof end == 'undefined') { + end = length; + } else if (end < 0) { end = nativeMax(length + end, 0); } else if (end > length) { end = length; } - length = start > end ? 0 : (end - start); + length = end - start || 0; var result = Array(length); while (++index < length) { @@ -3077,7 +3069,7 @@ * @param {*} value The value to evaluate. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. @@ -3087,17 +3079,17 @@ * // => 2 * * var dict = { - * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'forty': 40, 'fifty': 50 } + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } * }; * * // using `callback` - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'forty', function(word) { + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { * return dict.wordToNumber[word]; * }); * // => 2 * * // using `callback` with `thisArg` - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'forty', function(word) { + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { * return this.wordToNumber[word]; * }, dict); * // => 2 @@ -3123,144 +3115,6 @@ return low; } - /** - * Creates a slice of `array` with `n` elements taken from the beginning. - * - * @static - * @memberOf _ - * @type Function - * @category Arrays - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to take. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.take([1, 2, 3], 1); - * // => [1] - * - * _.take([1, 2, 3], 2); - * // => [1, 2] - * - * _.take([1, 2, 3], 5); - * // => [1, 2, 3] - * - * _.take([1, 2, 3], 0); - * // => [] - */ - var take = first; - - /** - * Creates a slice of `array` with `n` elements taken from the end. - * - * @static - * @memberOf _ - * @type Function - * @category Arrays - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to take. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.takeRight([1, 2, 3], 1); - * // => [3] - * - * _.takeRight([1, 2, 3], 2); - * // => [2, 3] - * - * _.takeRight([1, 2, 3], 5); - * // => [1, 2, 3] - * - * _.takeRight([1, 2, 3], 0); - * // => [] - */ - var takeRight = last; - - /** - * Creates a slice of `array` with elements taken from the end. Elements will - * be taken until the predicate returns falsey. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called - * per element. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.takeRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [2, 3] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate' }, - * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.takeRightWhile(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.pluck(_.takeRightWhile(characters, { 'employer': 'na' }), 'name'); - * // => ['pebbles'] - */ - var takeRightWhile = last; - - /** - * Creates a slice of `array` with elements taken from the beginning. Elements - * will be taken until the predicate returns falsey. The predicate is bound - * to `thisArg` and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called - * per element. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.takeWhile([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [1, 2] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, - * { 'name': 'fred', 'employer': 'slate' }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.takeWhile(characters, 'blocked'), 'name'); - * // => ['barney'] - * - * // using "_.where" callback shorthand - * _.pluck(_.takeWhile(characters, { 'employer': 'slate' }), 'name'); - * // => ['barney', 'fred'] - */ - var takeWhile = first; - /** * Creates an array of unique values, in order, of the provided arrays using * strict equality for comparisons, i.e. `===`. @@ -3268,8 +3122,8 @@ * @static * @memberOf _ * @category Arrays - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of combined values. + * @param {...Array} [array] The arrays to inspect. + * @returns {Array} Returns an array of combined values. * @example * * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); @@ -3281,11 +3135,11 @@ /** * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing `true` for - * `isSorted` will use a faster algorithm. If a callback is provided it will - * be executed for each value in the array to generate the criterion by which - * uniqueness is computed. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index, array). + * for comparisons, i.e. `===`. If the array is sorted, providing + * `true` for `isSorted` will use a faster algorithm. If a callback is provided + * each element of `array` is passed through the callback before uniqueness + * is computed. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. @@ -3300,11 +3154,11 @@ * @category Arrays * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" - * or "_.where" style callback respectively. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns the new duplicate-value-free array. + * @returns {Array} Returns a duplicate-value-free array. * @example * * _.uniq([1, 2, 1, 3, 1]); @@ -3357,27 +3211,26 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to filter. - * @param {...*} [values] The values to exclude. - * @returns {Array} Returns the new array of filtered values. + * @param {...*} [value] The values to exclude. + * @returns {Array} Returns a new array of filtered values. * @example * * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ - function without() { - return baseDifference(arguments[0], slice(arguments, 1)); + function without(array) { + return baseDifference(array, slice(arguments, 1)); } /** * Creates an array that is the symmetric difference of the provided arrays. - * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for - * more details. + * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. * * @static * @memberOf _ * @category Arrays - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of values. + * @param {...Array} [array] The arrays to inspect. + * @returns {Array} Returns an array of values. * @example * * _.xor([1, 2, 3], [5, 2, 1, 4]); @@ -3411,8 +3264,8 @@ * @memberOf _ * @alias unzip * @category Arrays - * @param {...Array} [arrays] The arrays to process. - * @returns {Array} Returns the array of grouped elements. + * @param {...Array} [array] The arrays to process. + * @returns {Array} Returns a new array of grouped elements. * @example * * _.zip(['fred', 'barney'], [30, 40], [true, false]); @@ -3444,7 +3297,8 @@ * @category Arrays * @param {Array} keys The array of keys. * @param {Array} [values=[]] The array of values. - * @returns {Object} Returns the new object. + * @returns {Object} Returns an object composed of the given keys and + * corresponding values. * @example * * _.zipObject(['fred', 'barney'], [30, 40]); @@ -3479,7 +3333,7 @@ * @memberOf _ * @category Chaining * @param {*} value The value to wrap. - * @returns {Object} Returns the new wrapper object. + * @returns {Object} Returns the wrapper object. * @example * * var characters = [ @@ -3496,7 +3350,9 @@ * // => 'pebbles is 1' */ function chain(value) { - return new lodashWrapper(value, true); + value = new lodashWrapper(value); + value.__chain__ = true; + return value; } /** @@ -3556,12 +3412,12 @@ } /** - * Produces the result of coercing the wrapped value to a string. + * Produces the `toString` result of the wrapped value. * * @name toString * @memberOf _ * @category Chaining - * @returns {string} Returns the coerced string value. + * @returns {string} Returns the string result. * @example * * _([1, 2, 3]).toString(); @@ -3576,7 +3432,7 @@ * * @name valueOf * @memberOf _ - * @alias toJSON, value + * @alias value * @category Chaining * @returns {*} Returns the wrapped value. * @example @@ -3590,6 +3446,7 @@ /*--------------------------------------------------------------------------*/ + /** * Creates an array of elements from the specified indexes, or keys, of the * `collection`. Indexes may be specified as individual arguments or as arrays @@ -3599,9 +3456,10 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [keys] The keys of elements - * to pick, specified as individual keys or arrays of keys. - * @returns {Array} Returns the array of picked elements. + * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` + * to retrieve, specified as individual indexes or arrays of indexes. + * @returns {Array} Returns a new array of elements corresponding to the + * provided indexes. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); @@ -3610,11 +3468,17 @@ * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ - function at(collection) { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = props.length; + function at(collection, guard) { + var args = arguments, + index = -1, + props = baseFlatten(args, true, false, 1), + length = props.length, + type = typeof guard; + // enables use as a callback for functions like `_.map` + if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) { + length = 1; + } if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } @@ -3634,10 +3498,10 @@ * @memberOf _ * @alias include * @category Collections - * @param {Array|Object|string} collection The collection to search. + * @param {Array|Object|string} collection The collection to iterate over. * @param {*} target The value to check for. * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if a matching element is found, else `false`. + * @returns {boolean} Returns `true` if the `target` element is found, else `false`. * @example * * _.contains([1, 2, 3], 1); @@ -3654,25 +3518,31 @@ */ function contains(collection, target, fromIndex) { var length = collection ? collection.length : 0; - if (!(typeof length == 'number' && length > -1 && length <= maxSafeInteger)) { - collection = values(collection); - length = collection.length; - } - if (typeof fromIndex == 'number') { - fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); - } else { - fromIndex = 0; - } - if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { + fromIndex = typeof fromIndex == 'number' ? fromIndex : 0; + + if (typeof length == 'number') { if (fromIndex >= length) { return false; } - return nativeContains - ? nativeContains.call(collection, target, fromIndex) - : collection.indexOf(target, fromIndex) > -1; + if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { + return nativeContains + ? nativeContains.call(collection, target, fromIndex) + : collection.indexOf(target, fromIndex) > -1; + } + var indexOf = getIndexOf(); + fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; + return indexOf(collection, target, fromIndex) > -1; } - var indexOf = getIndexOf(); - return indexOf(collection, target, fromIndex) > -1; + var index = -1, + result = false; + + baseEach(collection, function(value) { + if (++index >= fromIndex) { + return !(result = value === target); + } + }); + + return result; } /** @@ -3695,7 +3565,7 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -3714,14 +3584,14 @@ }); /** - * Checks if the predicate returns truthy for **all** elements of a collection. - * The predicate is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). + * Checks if the callback returns truey value for **all** elements of a + * collection. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -3730,11 +3600,11 @@ * @alias all * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {boolean} Returns `true` if all elements passed the predicate check, + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {boolean} Returns `true` if all elements passed the callback check, * else `false`. * @example * @@ -3754,36 +3624,36 @@ * _.every(characters, { 'age': 36 }); * // => false */ - function every(collection, predicate, thisArg) { + function every(collection, callback, thisArg) { var result = true; - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { - if (!predicate(collection[index], index, collection)) { + if (!callback(collection[index], index, collection)) { return false; } } } else { baseEach(collection, function(value, index, collection) { - return (result = !!predicate(value, index, collection)); + return (result = !!callback(value, index, collection)); }); } return result; } /** - * Iterates over elements of a collection returning an array of all elements - * the predicate returns truthy for. The predicate is bound to `thisArg` and + * Iterates over elements of a collection, returning an array of all elements + * the callback returns truey for. The callback is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -3792,11 +3662,11 @@ * @alias select * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the new filtered array. + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that passed the callback check. * @example * * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); @@ -3815,23 +3685,23 @@ * _.filter(characters, { 'age': 36 }); * // => [{ 'name': 'barney', 'age': 36 }] */ - function filter(collection, predicate, thisArg) { + function filter(collection, callback, thisArg) { var result = []; - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; - if (predicate(value, index, collection)) { + if (callback(value, index, collection)) { result.push(value); } } } else { baseEach(collection, function(value, index, collection) { - if (predicate(value, index, collection)) { + if (callback(value, index, collection)) { result.push(value); } }); @@ -3841,26 +3711,26 @@ /** * Iterates over elements of a collection, returning the first element that - * the predicate returns truthy for. The predicate is bound to `thisArg` and + * the callback returns truey for. The callback is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ - * @alias detect + * @alias detect, findWhere * @category Collections - * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {*} Returns the matched element, else `undefined`. + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the found element, else `undefined`. * @example * * var characters = [ @@ -3882,28 +3752,43 @@ * _.find(characters, 'blocked'); * // => { 'name': 'fred', 'age': 40, 'blocked': true } */ - function find(collection, predicate, thisArg) { + function find(collection, callback, thisArg) { + callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { - var index = findIndex(collection, predicate, thisArg); - return index > -1 ? collection[index] : undefined; + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (callback(value, index, collection)) { + return value; + } + } + } else { + var result; + baseEach(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result = value; + return false; + } + }); + return result; } - predicate = lodash.createCallback(predicate, thisArg, 3); - return baseFind(collection, predicate, baseEach); } /** - * This method is like `_.find` except that it iterates over elements of a - * collection from right to left. + * This method is like `_.find` except that it iterates over elements + * of a `collection` from right to left. * * @static * @memberOf _ * @category Collections - * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {*} Returns the matched element, else `undefined`. + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the found element, else `undefined`. * @example * * _.findLast([1, 2, 3, 4], function(num) { @@ -3911,41 +3796,21 @@ * }); * // => 3 */ - function findLast(collection, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); - return baseFind(collection, predicate, baseEachRight); - } + function findLast(collection, callback, thisArg) { + var result; - /** - * Performs a deep comparison between each element in `collection` and the - * source object, returning the first element that has equivalent property - * values. - * - * @static - * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to search. - * @param {Object} source The object of property values to match. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'employer': 'slate' }, - * { 'name': 'fred', 'age': 40, 'employer': 'slate' } - * ]; - * - * _.findWhere(characters, { 'employer': 'slate' }); - * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } - * - * _.findWhere(characters, { 'age': 40 }); - * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' } - */ - function findWhere(collection, source) { - return find(collection, matches(source)); + callback = lodash.createCallback(callback, thisArg, 3); + baseEachRight(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result = value; + return false; + } + }); + return result; } /** - * Iterates over elements of a collection executing the callback for each + * Iterates over elements of a collection, executing the callback for each * element. The callback is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Callbacks may exit iteration early by * explicitly returning `false`. @@ -3971,14 +3836,24 @@ * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { - return (callback && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, callback) - : baseEach(collection, baseCreateCallback(callback, thisArg, 3)); + if (callback && typeof thisArg == 'undefined' && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (callback(collection[index], index, collection) === false) { + break; + } + } + } else { + baseEach(collection, baseCreateCallback(callback, thisArg, 3)); + } + return collection; } /** - * This method is like `_.forEach` except that it iterates over elements of - * a collection from right to left. + * This method is like `_.forEach` except that it iterates over elements + * of a `collection` from right to left. * * @static * @memberOf _ @@ -3994,9 +3869,17 @@ * // => logs each number from right to left and returns '3,2,1' */ function forEachRight(collection, callback, thisArg) { - return (callback && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEachRight(collection, callback) - : baseEachRight(collection, baseCreateCallback(callback, thisArg, 3)); + if (callback && typeof thisArg == 'undefined' && isArray(collection)) { + var length = collection.length; + while (length--) { + if (callback(collection[length], length, collection) === false) { + break; + } + } + } else { + baseEachRight(collection, baseCreateCallback(callback, thisArg, 3)); + } + return collection; } /** @@ -4019,7 +3902,7 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -4062,23 +3945,23 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * var keyData = [ + * var keys = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * - * _.indexBy(keyData, 'dir'); + * _.indexBy(keys, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } * - * _.indexBy(keyData, function(object) { return String.fromCharCode(object.code); }); + * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * - * _.indexBy(keyData, function(object) { return this.fromCharCode(object.code); }, String); + * _.indexBy(keys, function(key) { return this.fromCharCode(key.code); }, String); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } */ var indexBy = createAggregator(function(result, value, key) { @@ -4086,10 +3969,10 @@ }); /** - * Invokes the method named by `methodName` on each element in the collection + * Invokes the method named by `methodName` on each element in the `collection` * returning an array of the results of each invoked method. Additional arguments * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the collection. + * will be invoked for, and `this` bound to, each element in the `collection`. * * @static * @memberOf _ @@ -4098,7 +3981,7 @@ * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {...*} [args] Arguments to invoke the method with. - * @returns {Array} Returns the array of results. + * @returns {Array} Returns a new array of the results of each invoked method. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); @@ -4108,16 +3991,22 @@ * // => [['1', '2', '3'], ['4', '5', '6']] */ function invoke(collection, methodName) { - var args = slice(arguments, 2), - index = -1, + var index = -1, isFunc = typeof methodName == 'function', - length = collection && collection.length, - result = Array(length < 0 ? 0 : length >>> 0); + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); - baseEach(collection, function(value) { - var func = isFunc ? methodName : (value != null && value[methodName]); - result[++index] = func ? func.apply(value, args) : undefined; - }); + if (arguments.length < 3 && isArray(collection)) { + while (++index < length) { + var value = collection[index]; + result[index] = isFunc ? methodName.call(value) : value[methodName](); + } + } else { + var args = slice(arguments, 2); + baseEach(collection, function(value) { + result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); + }); + } return result; } @@ -4140,9 +4029,9 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns the new mapped array. + * @returns {Array} Returns a new array of the results of each `callback` execution. * @example * * _.map([1, 2, 3], function(num) { return num * 3; }); @@ -4161,17 +4050,20 @@ * // => ['barney', 'fred'] */ function map(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { - return arrayMap(collection, callback, thisArg); + while (++index < length) { + result[index] = callback(collection[index], index, collection); + } + } else { + baseEach(collection, function(value, key, collection) { + result[++index] = callback(value, key, collection); + }); } - var index = -1, - result = []; - - baseEach(collection, function(value, key, collection) { - result[++index] = callback(value, key, collection); - }); return result; } @@ -4193,9 +4085,9 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" - * or "_.where" style callback respectively. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the maximum value. * @example @@ -4203,9 +4095,6 @@ * _.max([4, 2, 8, 6]); * // => 8 * - * _.max([]); - * // => -Infinity - * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } @@ -4244,7 +4133,7 @@ baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); - if (current > computed || (current === -Infinity && current === result)) { + if (current > computed) { computed = current; result = value; } @@ -4271,9 +4160,9 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" - * or "_.where" style callback respectively. + * @param {Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the minimum value. * @example @@ -4281,9 +4170,6 @@ * _.min([4, 2, 8, 6]); * // => 2 * - * _.min([]); - * // => Infinity - * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } @@ -4322,7 +4208,7 @@ baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); - if (current < computed || (current === Infinity && current === result)) { + if (current < computed) { computed = current; result = value; } @@ -4333,14 +4219,14 @@ /** * Creates an array of elements split into two groups, the first of which - * contains elements the predicate returns truthy for, while the second of which - * contains elements the predicate returns falsey for. The predicate is bound + * contains elements the callback returns truey for, while the second of which + * contains elements the callback returns falsey for. The callback is bound * to `thisArg` and invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -4348,11 +4234,11 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the array of grouped elements. + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of grouped elements. * @example * * _.partition([1, 2, 3], function(num) { return num % 2; }); @@ -4377,17 +4263,18 @@ */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); - }, function() { return [[], []]; }); + }, true); /** * Retrieves the value of a specified property from all elements in the collection. * * @static * @memberOf _ + * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {string} key The name of the property to pluck. - * @returns {Array} Returns the property values. + * @returns {Array} Returns a new array of property values. * @example * * var characters = [ @@ -4398,9 +4285,7 @@ * _.pluck(characters, 'name'); * // => ['barney', 'fred'] */ - function pluck(collection, key) { - return map(collection, property(key)); - } + var pluck = map; /** * Reduces a collection to a value which is the accumulated result of running @@ -4434,8 +4319,8 @@ */ function reduce(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); + callback = lodash.createCallback(callback, thisArg, 4); if (isArray(collection)) { var index = -1, length = collection.length; @@ -4457,8 +4342,8 @@ } /** - * This method is like `_.reduce` except that it iterates over elements of a - * collection from right to left. + * This method is like `_.reduce` except that it iterates over elements + * of a `collection` from right to left. * * @static * @memberOf _ @@ -4471,14 +4356,14 @@ * @returns {*} Returns the accumulated value. * @example * - * var array = [[0, 1], [2, 3], [4, 5]]; - * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); + * var list = [[0, 1], [2, 3], [4, 5]]; + * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); * // => [4, 5, 2, 3, 0, 1] */ function reduceRight(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); + callback = lodash.createCallback(callback, thisArg, 4); baseEachRight(collection, function(value, index, collection) { accumulator = noaccum ? (noaccum = false, value) @@ -4488,13 +4373,13 @@ } /** - * The opposite of `_.filter`; this method returns the elements of a collection - * the predicate does **not** return truthy for. + * The opposite of `_.filter`; this method returns the elements of a + * collection that the callback does **not** return truey for. * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -4502,11 +4387,11 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the new filtered array. + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that failed the callback check. * @example * * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); @@ -4525,9 +4410,11 @@ * _.reject(characters, { 'age': 36 }); * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ - function reject(collection, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); - return filter(collection, negate(predicate)); + function reject(collection, callback, thisArg) { + callback = lodash.createCallback(callback, thisArg, 3); + return filter(collection, function(value, index, collection) { + return !callback(value, index, collection); + }); } /** @@ -4539,7 +4426,7 @@ * @param {Array|Object|string} collection The collection to sample. * @param {number} [n] The number of elements to sample. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {*} Returns the random sample(s). + * @returns {*} Returns the random sample(s) of `collection`. * @example * * _.sample([1, 2, 3, 4]); @@ -4555,24 +4442,22 @@ collection = collection.split(''); } if (n == null || guard) { - var length = collection ? collection.length : 0; - return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + return collection ? collection[baseRandom(0, collection.length - 1)] : undefined; } var result = shuffle(collection); - result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length); + result.length = nativeMin(nativeMax(0, n), result.length); return result; } /** * Creates an array of shuffled values, using a version of the Fisher-Yates - * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) - * for more details. + * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) for more details. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to shuffle. - * @returns {Array} Returns the new shuffled array. + * @returns {Array} Returns a new shuffled collection. * @example * * _.shuffle([1, 2, 3, 4]); @@ -4580,19 +4465,20 @@ */ function shuffle(collection) { var index = -1, - length = collection && collection.length, - result = Array(length < 0 ? 0 : length >>> 0); + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); baseEach(collection, function(value) { var rand = baseRandom(0, ++index); result[index] = result[rand]; result[rand] = value; }); + return result; } /** - * Gets the size of the collection by returning `collection.length` for arrays + * Gets the size of the `collection` by returning `collection.length` for arrays * and array-like objects or the number of own enumerable properties for objects. * * @static @@ -4613,21 +4499,19 @@ */ function size(collection) { var length = collection ? collection.length : 0; - return (typeof length == 'number' && length > -1 && length <= maxSafeInteger) - ? length - : keys(collection).length; + return typeof length == 'number' ? length : keys(collection).length; } /** - * Checks if the predicate returns truthy for **any** element of a collection. - * The function returns as soon as it finds a passing value and does not iterate - * over the entire collection. The predicate is bound to `thisArg` and invoked - * with three arguments; (value, index|key, collection). + * Checks if the callback returns a truey value for **any** element of a + * collection. The function returns as soon as it finds a passing value and + * does not iterate over the entire collection. The callback is bound to + * `thisArg` and invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -4636,11 +4520,11 @@ * @alias any * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {boolean} Returns `true` if any element passed the predicate check, + * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {boolean} Returns `true` if any element passed the callback check, * else `false`. * @example * @@ -4660,22 +4544,22 @@ * _.some(characters, { 'age': 1 }); * // => false */ - function some(collection, predicate, thisArg) { + function some(collection, callback, thisArg) { var result; - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { - if (predicate(collection[index], index, collection)) { + if (callback(collection[index], index, collection)) { return true; } } } else { baseEach(collection, function(value, index, collection) { - return !(result = predicate(value, index, collection)); + return !(result = callback(value, index, collection)); }); } return !!result; @@ -4702,11 +4586,11 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it will - * be used to create a "_.pluck" or "_.where" style callback respectively. + * @param {Array|Function|Object|string} [callback=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns the new sorted array. + * @returns {Array} Returns a new array of sorted elements. * @example * * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); @@ -4732,9 +4616,9 @@ */ function sortBy(collection, callback, thisArg) { var index = -1, - length = collection && collection.length, multi = callback && isArray(callback), - result = Array(length < 0 ? 0 : length >>> 0); + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); if (!multi) { callback = lodash.createCallback(callback, thisArg, 3); @@ -4762,7 +4646,7 @@ } /** - * Converts `collection` to an array. + * Converts the `collection` to an array. * * @static * @memberOf _ @@ -4775,8 +4659,7 @@ * // => [2, 3, 4] */ function toArray(collection) { - var length = collection && collection.length; - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + if (collection && typeof collection.length == 'number') { return (support.unindexedChars && isString(collection)) ? collection.split('') : slice(collection); @@ -4786,39 +4669,35 @@ /** * Performs a deep comparison between each element in `collection` and the - * source object, returning an array of all elements that have equivalent + * `source` object, returning an array of all elements that have equivalent * property values. * * @static * @memberOf _ + * @type Function * @category Collections - * @param {Array|Object|string} collection The collection to search. - * @param {Object} source The object of property values to match. - * @returns {Array} Returns the new filtered array. + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Object} source The object of property values to filter by. + * @returns {Array} Returns a new array of elements that have the given properties. * @example * * var characters = [ - * { 'name': 'barney', 'age': 36, 'employer': 'slate', 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'employer': 'slate', 'pets': ['baby puss', 'dino'] } + * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }, + * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } * ]; * - * _.pluck(_.where(characters, { 'age': 36 }), 'name'); - * // => ['barney'] - * - * _.pluck(_.where(characters, { 'pets': ['dino'] }), 'name'); - * // => ['fred'] + * _.where(characters, { 'age': 36 }); + * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }] * - * _.pluck(_.where(characters, { 'employer': 'slate' }), 'name'); - * // => ['barney', 'fred'] + * _.where(characters, { 'pets': ['dino'] }); + * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }] */ - function where(collection, source) { - return filter(collection, matches(source)); - } + var where = filter; /*--------------------------------------------------------------------------*/ /** - * Creates a function that executes `func`, with the `this` binding and + * Creates a function that executes `func`, with the `this` binding and * arguments of the created function, only after being called `n` times. * * @static @@ -4843,9 +4722,8 @@ */ function after(n, func) { if (!isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } - n = nativeIsFinite(n = +n) ? n : 0; return function() { if (--n < 1) { return func.apply(this, arguments); @@ -4854,9 +4732,9 @@ } /** - * Creates a function that invokes `func` with the `this` binding of `thisArg` - * and prepends any additional `bind` arguments to those provided to the bound - * function. + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any additional `bind` arguments to those + * provided to the bound function. * * Note: Unlike native `Function#bind` this method does not set the `length` * property of bound functions. @@ -4903,8 +4781,8 @@ * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodNames] The object method names to bind, specified - * as individual method names or arrays of method names. + * @param {...string} [methodName] The object method names to + * bind, specified as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * @@ -4930,10 +4808,10 @@ } /** - * Creates a function that invokes the method at `object[key]` and prepends - * any additional `bindKey` arguments to those provided to the bound function. - * This method differs from `_.bind` by allowing bound functions to reference - * methods that will be redefined or don't yet exist. + * Creates a function that, when called, invokes the method at `object[key]` + * and prepends any additional `bindKey` arguments to those provided to the bound + * function. This method differs from `_.bind` by allowing bound functions to + * reference methods that will be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * @@ -4979,7 +4857,7 @@ * @static * @memberOf _ * @category Functions - * @param {...Function} [funcs] Functions to compose. + * @param {...Function} [func] Functions to compose. * @returns {Function} Returns the new composed function. * @example * @@ -5007,7 +4885,7 @@ while (length--) { if (!isFunction(funcs[length])) { - throw new TypeError(funcErrorText); + throw new TypeError; } } return function() { @@ -5065,7 +4943,7 @@ * the leading and/or trailing edge of the `wait` timeout. Subsequent calls * to the debounced function will return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` will be called + * Note: If `leading` and `trailing` options are `true` `func` will be called * on the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * @@ -5110,15 +4988,15 @@ trailing = true; if (!isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } - wait = wait < 0 ? 0 : wait; + wait = nativeMax(0, wait) || 0; if (options === true) { var leading = true; trailing = false; } else if (isObject(options)) { leading = options.leading; - maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); + maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0); trailing = 'trailing' in options ? options.trailing : trailing; } var delayed = function() { @@ -5215,7 +5093,7 @@ */ function defer(func) { if (!isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } var args = slice(arguments, 1); return setTimeout(function() { func.apply(undefined, args); }, 1); @@ -5239,7 +5117,7 @@ */ function delay(func, wait) { if (!isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } var args = slice(arguments, 2); return setTimeout(function() { func.apply(undefined, args); }, wait); @@ -5257,7 +5135,7 @@ * @memberOf _ * @category Functions * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] The function to resolve the cache key. + * @param {Function} [resolver] A function used to resolve the cache key. * @returns {Function} Returns the new memoizing function. * @example * @@ -5283,8 +5161,8 @@ * // => { 'name': 'penelope', 'age': 1 } */ function memoize(func, resolver) { - if (!isFunction(func) || (resolver && !isFunction(resolver))) { - throw new TypeError(funcErrorText); + if (!isFunction(func)) { + throw new TypeError; } var memoized = function() { var cache = memoized.cache, @@ -5298,34 +5176,6 @@ return memoized; } - /** - * Creates a function that negates the result of the predicate `func`. The - * `func` function is executed with the `this` binding and arguments of the - * created function. - * - * @static - * @memberOf _ - * @category Functions - * @param {Function} predicate The predicate to negate. - * @returns {Function} Returns the new function. - * @example - * - * function isEven(num) { - * return num % 2 == 0; - * } - * - * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); - * // => [1, 3, 5] - */ - function negate(predicate) { - if (!isFunction(predicate)) { - throw new TypeError(funcErrorText); - } - return function() { - return !predicate.apply(this, arguments); - }; - } - /** * Creates a function that is restricted to execute `func` once. Repeat calls to * the function will return the value of the first call. The `func` is executed @@ -5348,7 +5198,7 @@ result; if (!isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } return function() { if (ran) { @@ -5364,9 +5214,9 @@ } /** - * Creates a function that invokes `func` with any additional `partial` arguments - * prepended to those provided to the new function. This method is similar to - * `_.bind` except it does **not** alter the `this` binding. + * Creates a function that, when called, invokes `func` with any additional + * `partial` arguments prepended to those provided to the new function. This + * method is similar to `_.bind` except it does **not** alter the `this` binding. * * Note: This method does not set the `length` property of partially applied * functions. @@ -5409,15 +5259,20 @@ * @returns {Function} Returns the new partially applied function. * @example * - * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { - * return _.merge(value, other, deep); - * }); + * var defaultsDeep = _.partialRight(_.merge, _.defaults); + * + * var options = { + * 'variable': 'data', + * 'imports': { 'jq': $ } + * }; + * + * defaultsDeep(options, _.templateSettings); * - * var object = { 'a': { 'b': { 'c': 1 } } }, - * source = { 'a': { 'b': { 'c': 2, 'd': 2 } } }; + * options.variable + * // => 'data' * - * defaultsDeep(object, source); - * // => { 'a': { 'b': { 'c': 1, 'd': 2 } } } + * options.imports + * // => { '_': _, 'jq': $ } */ function partialRight(func) { if (func) { @@ -5436,7 +5291,7 @@ * of the `wait` timeout. Subsequent calls to the throttled function will * return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` will be called + * Note: If `leading` and `trailing` options are `true` `func` will be called * on the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * @@ -5465,16 +5320,16 @@ trailing = true; if (!isFunction(func)) { - throw new TypeError(funcErrorText); + throw new TypeError; } if (options === false) { leading = false; } else if (isObject(options)) { - leading = 'leading' in options ? !!options.leading : leading; - trailing = 'trailing' in options ? !!options.trailing : trailing; + leading = 'leading' in options ? options.leading : leading; + trailing = 'trailing' in options ? options.trailing : trailing; } debounceOptions.leading = leading; - debounceOptions.maxWait = +wait; + debounceOptions.maxWait = wait; debounceOptions.trailing = trailing; return debounce(func, wait, debounceOptions); @@ -5507,6 +5362,7 @@ /*--------------------------------------------------------------------------*/ + /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources will overwrite property assignments of previous @@ -5519,7 +5375,7 @@ * @alias extend * @category Objects * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. + * @param {...Object} [source] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -5528,19 +5384,16 @@ * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); * // => { 'name': 'fred', 'employer': 'slate' } * - * var defaults = _.partialRight(_.assign, function(value, other) { - * return typeof value == 'undefined' ? other : value; + * var defaults = _.partialRight(_.assign, function(a, b) { + * return typeof a == 'undefined' ? b : a; * }); * * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ function assign(object, source, guard) { - var args = arguments; - if (!object || args.length < 2) { - return object; - } - var argsIndex = 0, + var args = arguments, + argsIndex = 0, argsLength = args.length, type = typeof guard; @@ -5556,13 +5409,15 @@ } while (++argsIndex < argsLength) { source = args[argsIndex]; - var index = -1, - props = keys(source), - length = props.length; + if (isObject(source)) { + var index = -1, + props = keys(source), + length = props.length; - while (++index < length) { - var key = props[index]; - object[key] = callback ? callback(object[key], source[key]) : source[key]; + while (++index < length) { + var key = props[index]; + object[key] = callback ? callback(object[key], source[key]) : source[key]; + } } } return object; @@ -5720,14 +5575,11 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property will be ignored. * - * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) - * for a deep version of this method. - * * @static * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. + * @param {...Object} [source] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example @@ -5735,23 +5587,42 @@ * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ - function defaults(object) { - if (!object) { - return object; + function defaults(object, source, guard) { + var args = arguments, + argsIndex = 0, + argsLength = args.length, + type = typeof guard; + + // enables use as a callback for functions like `_.reduce` + if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { + argsLength = 2; + } + while (++argsIndex < argsLength) { + source = args[argsIndex]; + if (isObject(source)) { + var index = -1, + props = keys(source), + length = props.length; + + while (++index < length) { + var key = props[index]; + if (typeof object[key] == 'undefined') { + object[key] = source[key]; + } + } + } } - var args = slice(arguments); - args.push(assignDefaults); - return assign.apply(null, args); + return object; } /** * This method is like `_.findIndex` except that it returns the key of the - * first element the predicate returns truthy for, instead of the element itself. + * first element that passes the callback check, instead of the element itself. * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -5759,11 +5630,11 @@ * @memberOf _ * @category Objects * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {string|undefined} Returns the key of the matched element, else `undefined`. + * @param {Function|Object|string} [callback=identity] The function called per + * iteration. If a property name or object is provided it will be used to + * create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {string|undefined} Returns the key of the found element, else `undefined`. * @example * * var characters = { @@ -5785,19 +5656,27 @@ * _.findKey(characters, 'blocked'); * // => 'fred' */ - function findKey(object, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); - return baseFind(object, predicate, baseForOwn, true); + function findKey(object, callback, thisArg) { + var result; + + callback = lodash.createCallback(callback, thisArg, 3); + baseForOwn(object, function(value, key, object) { + if (callback(value, key, object)) { + result = key; + return false; + } + }); + return result; } /** - * This method is like `_.findKey` except that it iterates over elements of - * a collection in the opposite order. + * This method is like `_.findKey` except that it iterates over elements + * of a `collection` in the opposite order. * - * If a property name is provided for `predicate` the created "_.pluck" style + * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `predicate` the created "_.where" style callback + * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -5805,11 +5684,11 @@ * @memberOf _ * @category Objects * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {string|undefined} Returns the key of the matched element, else `undefined`. + * @param {Function|Object|string} [callback=identity] The function called per + * iteration. If a property name or object is provided it will be used to + * create a "_.pluck" or "_.where" style callback, respectively. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {string|undefined} Returns the key of the found element, else `undefined`. * @example * * var characters = { @@ -5831,19 +5710,28 @@ * _.findLastKey(characters, 'blocked'); * // => 'pebbles' */ - function findLastKey(object, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); - return baseFind(object, predicate, baseForOwnRight, true); + function findLastKey(object, callback, thisArg) { + var result; + + callback = lodash.createCallback(callback, thisArg, 3); + baseForOwnRight(object, function(value, key, object) { + if (callback(value, key, object)) { + result = key; + return false; + } + }); + return result; } /** - * Iterates over own and inherited enumerable properties of an object executing - * the callback for each property. The callback is bound to `thisArg` and invoked - * with three arguments; (value, key, object). Callbacks may exit iteration - * early by explicitly returning `false`. + * Iterates over own and inherited enumerable properties of an object, + * executing the callback for each property. The callback is bound to `thisArg` + * and invoked with three arguments; (value, key, object). Callbacks may exit + * iteration early by explicitly returning `false`. * * @static * @memberOf _ + * @type Function * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. @@ -5856,21 +5744,24 @@ * this.y = 0; * } * - * Shape.prototype.z = 0; + * Shape.prototype.move = function(x, y) { + * this.x += x; + * this.y += y; + * }; * * _.forIn(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments) + * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) */ function forIn(object, callback, thisArg) { callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - return baseFor(object, callback, keysIn); + return baseForIn(object, callback); } /** - * This method is like `_.forIn` except that it iterates over elements of a - * collection in the opposite order. + * This method is like `_.forIn` except that it iterates over elements + * of a `collection` in the opposite order. * * @static * @memberOf _ @@ -5886,20 +5777,34 @@ * this.y = 0; * } * - * Shape.prototype.z = 0; + * Shape.prototype.move = function(x, y) { + * this.x += x; + * this.y += y; + * }; * * _.forInRight(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' + * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' */ function forInRight(object, callback, thisArg) { + var pairs = []; + baseForIn(object, function(value, key) { + pairs.push(key, value); + }); + + var length = pairs.length; callback = baseCreateCallback(callback, thisArg, 3); - return baseForRight(object, callback, keysIn); + while (length--) { + if (callback(pairs[length--], pairs[length], object) === false) { + break; + } + } + return object; } /** - * Iterates over own enumerable properties of an object executing the callback + * Iterates over own enumerable properties of an object, executing the callback * for each property. The callback is bound to `thisArg` and invoked with three * arguments; (value, key, object). Callbacks may exit iteration early by * explicitly returning `false`. @@ -5924,8 +5829,8 @@ } /** - * This method is like `_.forOwn` except that it iterates over elements of a - * collection in the opposite order. + * This method is like `_.forOwn` except that it iterates over elements + * of a `collection` in the opposite order. * * @static * @memberOf _ @@ -5942,8 +5847,17 @@ * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ function forOwnRight(object, callback, thisArg) { + var props = keys(object), + length = props.length; + callback = baseCreateCallback(callback, thisArg, 3); - return baseForRight(object, callback, keys); + while (length--) { + var key = props[length]; + if (callback(object[key], key, object) === false) { + break; + } + } + return object; } /** @@ -5955,7 +5869,7 @@ * @alias methods * @category Objects * @param {Object} object The object to inspect. - * @returns {Array} Returns the new sorted array of property names. + * @returns {Array} Returns an array of property names that have function values. * @example * * _.functions(_); @@ -5963,7 +5877,6 @@ */ function functions(object) { var result = []; - baseForIn(object, function(value, key) { if (isFunction(value)) { result.push(key); @@ -6002,7 +5915,7 @@ * @category Objects * @param {Object} object The object to invert. * @param {boolean} [multiValue=false] Allow multiple values per key. - * @returns {Object} Returns the new inverted object. + * @returns {Object} Returns the created inverted object. * @example * * _.invert({ 'first': 'fred', 'second': 'barney' }); @@ -6041,52 +5954,25 @@ } /** - * Checks if `value` is an `arguments` object. + * Checks if `value` is an array. * * @static * @memberOf _ + * @type Function * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, else `false`. + * @returns {boolean} Returns `true` if the `value` is an array, else `false`. * @example * - * (function() { return _.isArguments(arguments); })(); - * // => true - * - * _.isArguments([1, 2, 3]); + * (function() { return _.isArray(arguments); })(); * // => false - */ - function isArguments(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == argsClass) || false; - } - // fallback for environments without a `[[Class]]` for `arguments` objects - if (!support.argsClass) { - isArguments = function(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && - hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee')) || false; - }; - } - - /** - * Checks if `value` is an array. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example * * _.isArray([1, 2, 3]); * // => true - * - * (function() { return _.isArray(arguments); })(); - * // => false */ var isArray = nativeIsArray || function(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass) || false; + return value && typeof value == 'object' && typeof value.length == 'number' && + toString.call(value) == arrayClass || false; }; /** @@ -6096,38 +5982,32 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a boolean value, else `false`. + * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. * @example * - * _.isBoolean(false); - * // => true - * * _.isBoolean(null); * // => false */ function isBoolean(value) { - return (value === true || value === false || - value && typeof value == 'object' && toString.call(value) == boolClass) || false; + return value === true || value === false || + value && typeof value == 'object' && toString.call(value) == boolClass || false; } /** - * Checks if `value` is a `Date` object. + * Checks if `value` is a date. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @returns {boolean} Returns `true` if the `value` is a date, else `false`. * @example * * _.isDate(new Date); * // => true - * - * _.isDate('Mon April 23 2012'); - * // => false */ function isDate(value) { - return (value && typeof value == 'object' && toString.call(value) == dateClass) || false; + return value && typeof value == 'object' && toString.call(value) == dateClass || false; } /** @@ -6137,63 +6017,56 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true - * - * _.isElement(''); - * // => false */ function isElement(value) { - return (value && typeof value == 'object' && value.nodeType === 1 && - (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value))) || false; + return value && typeof value == 'object' && value.nodeType === 1 && + (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value)) || false; } // fallback for environments without DOM support if (!support.dom) { isElement = function(value) { - return (value && typeof value == 'object' && value.nodeType === 1 && - !isPlainObject(value)) || false; + return value && typeof value == 'object' && value.nodeType === 1 && + !isPlainObject(value) || false; }; } /** - * Checks if a collection is empty. A value is considered empty unless it is - * an array, array-like object, or string with a length greater than `0` or - * an object with own properties. + * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a + * length of `0` and objects with no own enumerable properties are considered + * "empty". * * @static * @memberOf _ * @category Objects * @param {Array|Object|string} value The value to inspect. - * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @returns {boolean} Returns `true` if the `value` is empty, else `false`. * @example * - * _.isEmpty(null); - * // => true + * _.isEmpty([1, 2, 3]); + * // => false * - * _.isEmpty(true); + * _.isEmpty({}); * // => true * - * _.isEmpty(1); + * _.isEmpty(''); * // => true - * - * _.isEmpty([1, 2, 3]); - * // => false - * - * _.isEmpty({ 'a': 1 }); - * // => false */ function isEmpty(value) { var result = true; if (!value) { return result; } - var length = value.length; - if ((length > -1 && length <= maxSafeInteger) && - (isArray(value) || isString(value) || isArguments(value) || - (typeof value == 'object' && isFunction(value.splice)))) { + var className = toString.call(value), + length = value.length; + + if ((className == arrayClass || className == stringClass || + (support.argsClass ? className == argsClass : isArguments(value))) || + (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { return !length; } baseForOwn(value, function() { @@ -6204,83 +6077,61 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If a callback is provided it will be executed to compare - * values. If the callback returns `undefined` comparisons will be handled - * by the method instead. The callback is bound to `thisArg` and invoked - * with two arguments; (value, other). - * - * Note: This method supports comparing arrays, booleans, `Date` objects, - * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes - * are **not** supported. A callback may be used to extend support for - * comparing other values. + * equivalent to each other. If a callback is provided it will be executed + * to compare values. If the callback returns `undefined` comparisons will + * be handled by the method instead. The callback is bound to `thisArg` and + * invoked with two arguments; (a, b). * * @static * @memberOf _ * @category Objects - * @param {*} value The value to compare to `other`. - * @param {*} other The value to compare to `value`. + * @param {*} a The value to compare. + * @param {*} b The other value to compare. * @param {Function} [callback] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'name': 'fred' }; - * var other = { 'name': 'fred' }; + * var copy = { 'name': 'fred' }; * - * object == other; + * object == copy; * // => false * - * _.isEqual(object, other); + * _.isEqual(object, copy); * // => true * * var words = ['hello', 'goodbye']; * var otherWords = ['hi', 'goodbye']; * - * _.isEqual(words, otherWords, function() { - * return _.every(arguments, _.bind(RegExp.prototype.test, /^h(?:i|ello)$/)) || undefined; + * _.isEqual(words, otherWords, function(a, b) { + * var reGreet = /^(?:hello|hi)$/i, + * aGreet = _.isString(a) && reGreet.test(a), + * bGreet = _.isString(b) && reGreet.test(b); + * + * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; * }); * // => true */ - function isEqual(value, other, callback, thisArg) { + function isEqual(a, b, callback, thisArg) { callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2); if (!callback) { // exit early for identical values - if (value === other) { + if (a === b) { // treat `-0` vs. `+0` as not equal - return value !== 0 || (1 / value == 1 / other); + return a !== 0 || (1 / a == 1 / b); } - var valType = typeof value, - othType = typeof other; + var type = typeof a, + otherType = typeof b; // exit early for unlike primitive values - if (value === value && (value == null || other == null || - (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { + if (a === a && (a == null || b == null || + (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { return false; } } - return baseIsEqual(value, other, callback); - } - - /** - * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, - * `SyntaxError`, `TypeError`, or `URIError` object. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an error object, else `false`. - * @example - * - * _.isError(new Error); - * // => true - * - * _.isError(Error); - * // => false - */ - function isError(value) { - return (value && typeof value == 'object' && toString.call(value) == errorClass) || false; + return baseIsEqual(a, b, callback); } /** @@ -6294,7 +6145,7 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is finite, else `false`. + * @returns {boolean} Returns `true` if the `value` is finite, else `false`. * @example * * _.isFinite(-101); @@ -6323,14 +6174,11 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @returns {boolean} Returns `true` if the `value` is a function, else `false`. * @example * * _.isFunction(_); * // => true - * - * _.isFunction(/abc/); - * // => false */ function isFunction(value) { return typeof value == 'function'; @@ -6343,14 +6191,14 @@ } /** - * Checks if `value` is the language type of `Object`. + * Checks if `value` is the language type of Object. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @returns {boolean} Returns `true` if the `value` is an object, else `false`. * @example * * _.isObject({}); @@ -6363,12 +6211,12 @@ * // => false */ function isObject(value) { - // check if the value is the ECMAScript language type of `Object` + // check if the value is the ECMAScript language type of Object // http://es5.github.io/#x8 // and avoid a V8 bug // https://code.google.com/p/v8/issues/detail?id=2291 var type = typeof value; - return type == 'function' || (value && type == 'object') || false; + return value && (type == 'function' || type == 'object') || false; } /** @@ -6382,7 +6230,7 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. * @example * * _.isNaN(NaN); @@ -6399,7 +6247,7 @@ */ function isNaN(value) { // `NaN` as a primitive is the only value that is not equal to itself - // (perform the `[[Class]]` check first to avoid errors with some host objects in IE) + // (perform the [[Class]] check first to avoid errors with some host objects in IE) return isNumber(value) && value != +value; } @@ -6410,13 +6258,13 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. * @example * * _.isNull(null); * // => true * - * _.isNull(void 0); + * _.isNull(undefined); * // => false */ function isNull(value) { @@ -6424,7 +6272,7 @@ } /** - * Checks if `value` is a `Number` primitive or object. + * Checks if `value` is a number. * * Note: `NaN` is considered a number. See the [ES5 spec](http://es5.github.io/#x8.5) * for more details. @@ -6433,30 +6281,20 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @returns {boolean} Returns `true` if the `value` is a number, else `false`. * @example * - * _.isNumber(8.4); + * _.isNumber(8.4 * 5); * // => true - * - * _.isNumber(NaN); - * // => true - * - * _.isNumber('8.4'); - * // => false */ function isNumber(value) { var type = typeof value; return type == 'number' || - (value && type == 'object' && toString.call(value) == numberClass) || false; + value && type == 'object' && toString.call(value) == numberClass || false; } /** - * Checks if `value` is an object created by the `Object` constructor or has - * a `[[Prototype]]` of `null`. - * - * Note: This method assumes objects created by the `Object` constructor - * have no inherited enumerable properties. + * Checks if `value` is an object created by the `Object` constructor. * * @static * @memberOf _ @@ -6478,9 +6316,6 @@ * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true - * - * _.isPlainObject(Object.create(null)); - * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { @@ -6495,44 +6330,40 @@ }; /** - * Checks if `value` is a `RegExp` object. + * Checks if `value` is a regular expression. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a regexp object, else `false`. + * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. * @example * - * _.isRegExp(/abc/); + * _.isRegExp(/fred/); * // => true - * - * _.isRegExp('/abc/'); - * // => false */ function isRegExp(value) { - return (isObject(value) && toString.call(value) == regexpClass) || false; + var type = typeof value; + return value && (type == 'function' || type == 'object') && + toString.call(value) == regexpClass || false; } /** - * Checks if `value` is a `String` primitive or object. + * Checks if `value` is a string. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @returns {boolean} Returns `true` if the `value` is a string, else `false`. * @example * - * _.isString('abc'); + * _.isString('fred'); * // => true - * - * _.isString(1); - * // => false */ function isString(value) { return typeof value == 'string' || - (value && typeof value == 'object' && toString.call(value) == stringClass) || false; + value && typeof value == 'object' && toString.call(value) == stringClass || false; } /** @@ -6542,121 +6373,39 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true - * - * _.isUndefined(null); - * // => false */ function isUndefined(value) { return typeof value == 'undefined'; } /** - * Creates an array of the own enumerable property names of `object`. + * Creates an array composed of the own enumerable property names of an object. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. - * @returns {Array} Returns the array of property names. + * @returns {Array} Returns an array of property names. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * Shape.prototype.z = 0; - * - * _.keys(new Shape); - * // => ['x', 'y'] (property order is not guaranteed across environments) + * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); + * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { - var ctor = object && object.constructor, - length = object ? object.length : 0; - - if ((typeof length == 'number' && length > 0) || - (ctor && object === ctor.prototype)) { - return shimKeys(object); - } - return isObject(object) ? nativeKeys(object) : []; - }; - - /** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns the array of property names. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * Shape.prototype.z = 0; - * - * _.keysIn(new Shape); - * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) - */ - function keysIn(object) { if (!isObject(object)) { return []; } - var length = object.length; - length = (typeof length == 'number' && length > 0 && - (isArray(object) || (support.nonEnumStrings && isString(object)) || - (support.nonEnumArgs && isArguments(object))) && length) >>> 0; - - var keyIndex, - ctor = object.constructor, - index = -1, - isProto = ctor && object === ctor.prototype, - maxIndex = length - 1, - result = Array(length), - skipIndexes = length > 0, - skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), - skipProto = support.enumPrototypes && typeof object == 'function'; - - while (++index < length) { - result[index] = String(index); - } - for (var key in object) { - if (!(isProto && key == 'constructor') && - !(skipProto && key == 'prototype') && - !(skipErrorProps && (key == 'message' || key == 'name')) && - !(skipIndexes && (keyIndex = +key, keyIndex > -1 && keyIndex <= maxIndex && keyIndex % 1 == 0))) { - result.push(key); - } - } - // Lo-Dash skips the `constructor` property when it infers it's iterating - // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` - // attribute of an existing property and the `constructor` property of a - // prototype defaults to non-enumerable. - if (support.nonEnumShadows && object !== objectProto) { - index = -1; - length = shadowedProps.length; - - if (isProto) { - var className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object), - nonEnum = nonEnumProps[className]; - } - while (++index < length) { - key = shadowedProps[index]; - if (!(nonEnum && nonEnum[key]) && hasOwnProperty.call(object, key)) { - result.push(key); - } - } + if ((support.enumPrototypes && typeof object == 'function') || + (support.nonEnumArgs && object.length && isArguments(object))) { + return shimKeys(object); } - return result; - } + return nativeKeys(object); + }; /** * Creates an object with the same keys as `object` and values generated by @@ -6677,9 +6426,9 @@ * @param {Object} object The object to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the new mapped object. + * @returns {Object} Returns a new object with values of the results of each `callback` execution. * @example * * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); @@ -6696,8 +6445,8 @@ */ function mapValues(object, callback, thisArg) { var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); baseForOwn(object, function(value, key, object) { result[key] = callback(value, key, object); }); @@ -6717,7 +6466,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. + * @param {...Object} [source] The source objects. * @param {Function} [callback] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -6756,13 +6505,13 @@ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } */ function merge(object, source, guard) { + if (!isObject(object)) { + return object; + } var args = arguments, length = args.length, type = typeof guard; - if (!object || length < 2) { - return object; - } // enables use as a callback for functions like `_.reduce` if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { length = 2; @@ -6773,7 +6522,7 @@ } else if (length > 2 && typeof args[length - 1] == 'function') { callback = args[--length]; } - var sources = slice(args, 1, length), + var sources = slice(arguments, 1, length), index = -1, stackA = [], stackB = []; @@ -6787,20 +6536,20 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` omitting the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a callback is provided it will be executed for each + * property of `object` omitting the properties the callback returns truey + * for. The callback is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...string|string[]} [callback] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Object} Returns the new object. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object without the omitted properties. * @example * * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); @@ -6811,533 +6560,242 @@ * }); * // => { 'name': 'fred' } */ - function omit(object, predicate, thisArg) { - if (typeof predicate == 'function') { - predicate = lodash.createCallback(predicate, thisArg, 3); - return pick(object, negate(predicate)); - } - var omitProps = baseFlatten(arguments, true, false, 1), - length = omitProps.length; - - while (length--) { - omitProps[length] = String(omitProps[length]); - } - return pick(object, baseDifference(keysIn(object), omitProps)); - } - - /** - * Creates a two dimensional array of a given object's key-value pairs, - * i.e. `[[key1, value1], [key2, value2]]`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns the new array of key-value pairs. - * @example - * - * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) - */ - function pairs(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); + function omit(object, callback, thisArg) { + var result = {}; - while (++index < length) { - var key = props[index]; - result[index] = [key, object[key]]; - } - return result; - } + if (typeof callback != 'function') { + var omitProps = baseFlatten(arguments, true, false, 1), + length = omitProps.length; - /** - * Creates a shallow clone of `object` composed of the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` picking the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; - * (value, key, object). - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per - * iteration or property names to pick, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Object} Returns the new object. - * @example - * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); - * // => { 'name': 'fred' } - * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { - * return key.charAt(0) != '_'; - * }); - * // => { 'name': 'fred' } - */ - function pick(object, predicate, thisArg) { - var result = {}; + while (length--) { + omitProps[length] = String(omitProps[length]); + } + var props = []; + baseForIn(object, function(value, key) { + props.push(key); + }); - if (typeof predicate != 'function') { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = isObject(object) ? props.length : 0; + var index = -1; + props = baseDifference(props, omitProps); + length = props.length; while (++index < length) { var key = props[index]; - if (key in object) { - result[key] = object[key]; - } + result[key] = object[key]; } } else { - predicate = lodash.createCallback(predicate, thisArg, 3); + callback = lodash.createCallback(callback, thisArg, 3); baseForIn(object, function(value, key, object) { - if (predicate(value, key, object)) { + if (!callback(value, key, object)) { result[key] = value; } - }); - } - return result; - } - - /** - * An alternative to `_.reduce`; this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable properties through a callback, with each callback execution - * potentially mutating the `accumulator` object. The callback is bound to - * `thisArg` and invoked with four arguments; (accumulator, value, key, object). - * Callbacks may exit iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Array|Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. - * @example - * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; - * } - * }); - * // => [1, 9, 25] - * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; - * }); - * // => { 'a': 3, 'b': 6, 'c': 9 } - */ - function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); - if (accumulator == null) { - if (isArr) { - accumulator = []; - } else { - if (isObject(object)) { - var ctor = object.constructor, - proto = ctor && ctor.prototype; - } - accumulator = baseCreate(proto); - } - } - if (callback) { - callback = lodash.createCallback(callback, thisArg, 4); - (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { - return callback(accumulator, value, index, object); - }); - } - return accumulator; - } - - /** - * Creates an array of the own enumerable property values of `object`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns the array of property values. - * @example - * - * function Shape(x, y) { - * this.x = x; - * this.y = y; - * } - * - * Shape.prototype.z = 0; - * - * _.values(new Shape(2, 1)); - * // => [2, 1] (property order is not guaranteed across environments) - */ - function values(object) { - return baseValues(object, keys); - } - - /** - * Creates an array of the own and inherited enumerable property values - * of `object`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns the array of property values. - * @example - * - * function Shape(x, y) { - * this.x = x; - * this.y = y; - * } - * - * Shape.prototype.z = 0; - * - * _.valuesIn(new Shape(2, 1)); - * // => [2, 1, 0] (property order is not guaranteed across environments) - */ - function valuesIn(object) { - return baseValues(object, keysIn); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Converts `string` to camel case. - * See [Wikipedia](http://en.wikipedia.org/wiki/CamelCase) for more details. - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to camel case. - * @returns {string} Returns the camel cased string. - * @example - * - * _.camelCase('Hello world'); - * // => 'helloWorld' - * - * _.camelCase('--hello-world'); - * // => 'helloWorld' - * - * _.camelCase('__hello_world__'); - * // => 'helloWorld' - */ - var camelCase = createCompounder(function(result, word, index) { - if (!index && reAllCaps.test(word)) { - return result + word.toLowerCase(); - } - return result + (word.charAt(0)[index ? 'toUpperCase' : 'toLowerCase']() + word.slice(1)); - }); - - /** - * Capitalizes the first character of `string`. - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to capitalize. - * @returns {string} Returns the capitalized string. - * @example - * - * _.capitalize('fred'); - * // => 'Fred' - */ - function capitalize(string) { - if (string == null) { - return ''; - } - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } - - /** - * Checks if `string` ends with a given target string. - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to search. - * @param {string} [target] The string to search for. - * @param {number} [position=string.length] The position to search from. - * @returns {boolean} Returns `true` if the given string ends with the - * target string, else `false`. - * @example - * - * _.endsWith('abc', 'c'); - * // => true - * - * _.endsWith('abc', 'b'); - * // => false - * - * _.endsWith('abc', 'b', 2); - * // => true - */ - function endsWith(string, target, position) { - string = string == null ? '' : String(string); - target = String(target); - - var length = string.length; - position = (typeof position == 'undefined' ? length : nativeMin(position < 0 ? 0 : (+position || 0), length)) - target.length; - return position >= 0 && string.indexOf(target, position) == position; - } - - /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to - * their corresponding HTML entities. - * - * Note: No other characters are escaped. To escape additional characters - * use a third-party library like [_he_](http://mths.be/he). - * - * When working with HTML you should always quote attribute values to reduce - * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) - * for more details. - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escape('fred, barney, & pebbles'); - * // => 'fred, barney, & pebbles' - */ - function escape(string) { - return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); - } - - /** - * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", - * "+", "(", ")", "[", "]", "{" and "}" in `string`. - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escapeRegExp('[lodash](http://lodash.com)'); - * // => '\[lodash\]\(http://lodash\.com\)' - */ - function escapeRegExp(string) { - return string == null ? '' : String(string).replace(reRegExpChars, '\\$&'); - } - - /** - * Converts `string` to kebab case (a.k.a. spinal case). - * See [Wikipedia](http://en.wikipedia.org/wiki/Letter_case#Computers) for - * more details. - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to kebab case. - * @returns {string} Returns the kebab cased string. - * @example - * - * _.kebabCase('Hello world'); - * // => 'hello-world' - * - * _.kebabCase('helloWorld'); - * // => 'hello-world' - * - * _.kebabCase('__hello_world__'); - * // => 'hello-world' - */ - var kebabCase = createCompounder(function(result, word, index) { - return result + (index ? '-' : '') + word.toLowerCase(); - }); + }); + } + return result; + } /** - * Pads `string` on the left and right sides if it is shorter then the given - * padding length. The `chars` string may be truncated if the number of padding - * characters can't be evenly divided by the padding length. + * Creates a two dimensional array of an object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. * * @static * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to pad. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padded string. + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns new array of key-value pairs. * @example * - * _.pad('abc', 8); - * // => ' abc ' - * - * _.pad('abc', 8, '_-'); - * // => '_-abc_-_' - * - * _.pad('abc', 3); - * // => 'abc' + * _.pairs({ 'barney': 36, 'fred': 40 }); + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) */ - function pad(string, length, chars) { - string = string == null ? '' : String(string); - length = +length; + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); - var strLength = string.length; - if (strLength >= length || !nativeIsFinite(length)) { - return string; + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; } - var mid = (length - strLength) / 2, - leftLength = floor(mid), - rightLength = ceil(mid); - - chars = createPad('', rightLength, chars); - return chars.slice(0, leftLength) + string + chars; + return result; } /** - * Pads `string` on the left side if it is shorter then the given padding - * length. The `chars` string may be truncated if the number of padding - * characters exceeds the padding length. + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a callback is provided it will be executed for each + * property of `object` picking the properties the callback returns truey + * for. The callback is bound to `thisArg` and invoked with three arguments; + * (value, key, object). * * @static * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to pad. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padded string. + * @category Objects + * @param {Object} object The source object. + * @param {Function|...string|string[]} [callback] The function called per + * iteration or property names to pick, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. * @example * - * _.padLeft('abc', 6); - * // => ' abc' - * - * _.padLeft('abc', 6, '_-'); - * // => '_-_abc' + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); + * // => { 'name': 'fred' } * - * _.padLeft('abc', 3); - * // => 'abc' + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'fred' } */ - function padLeft(string, length, chars) { - string = string == null ? '' : String(string); - return createPad(string, length, chars) + string; + function pick(object, callback, thisArg) { + var result = {}; + + if (typeof callback != 'function') { + var index = -1, + props = baseFlatten(arguments, true, false, 1), + length = isObject(object) ? props.length : 0; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = lodash.createCallback(callback, thisArg, 3); + baseForIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; } /** - * Pads `string` on the right side if it is shorter then the given padding - * length. The `chars` string may be truncated if the number of padding - * characters exceeds the padding length. + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable properties through a callback, with each callback execution + * potentially mutating the `accumulator` object. The callback is bound to + * `thisArg` and invoked with four arguments; (accumulator, value, key, object). + * Callbacks may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to pad. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padded string. + * @category Objects + * @param {Array|Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the accumulated value. * @example * - * _.padRight('abc', 6); - * // => 'abc ' - * - * _.padRight('abc', 6, '_-'); - * // => 'abc_-_' + * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { + * num *= num; + * if (num % 2) { + * return result.push(num) < 3; + * } + * }); + * // => [1, 9, 25] * - * _.padRight('abc', 3); - * // => 'abc' + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { + * result[key] = num * 3; + * }); + * // => { 'a': 3, 'b': 6, 'c': 9 } */ - function padRight(string, length, chars) { - string = string == null ? '' : String(string); - return string + createPad(string, length, chars); + function transform(object, callback, accumulator, thisArg) { + var isArr = isArray(object); + if (accumulator == null) { + if (isArr) { + accumulator = []; + } else { + var ctor = object && object.constructor, + proto = ctor && ctor.prototype; + + accumulator = baseCreate(proto); + } + } + if (callback) { + callback = lodash.createCallback(callback, thisArg, 4); + (isArr ? baseEach : baseForOwn)(object, function(value, index, object) { + return callback(accumulator, value, index, object); + }); + } + return accumulator; } /** - * Repeats the given string `n` times. + * Creates an array composed of the own enumerable property values of `object`. * * @static * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to repeat. - * @param {number} [n=0] The number of times to repeat the string. - * @returns {string} Returns the repeated string. + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns an array of property values. * @example * - * _.repeat('*', 3); - * // => '***' - * - * _.repeat('abc', 2); - * // => 'abcabc' - * - * _.repeat('abc', 0); - * // => '' + * _.values({ 'one': 1, 'two': 2, 'three': 3 }); + * // => [1, 2, 3] (property order is not guaranteed across environments) */ - function repeat(string, n) { - var result = ''; - n = +n; + function values(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); - if (n < 1 || string == null || !nativeIsFinite(n)) { - return result; + while (++index < length) { + result[index] = object[props[index]]; } - string = String(string); - do { - if (n % 2) { - result += string; - } - n = floor(n / 2); - string += string; - } while (n); return result; } + /*--------------------------------------------------------------------------*/ + /** - * Converts `string` to snake case. - * See [Wikipedia](http://en.wikipedia.org/wiki/Snake_case) for more details. + * Converts the first character of `string` to upper case. * * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The string to snake case. - * @returns {string} Returns the snake cased string. + * @param {string} string The string to capitalize. + * @returns {string} Returns the capitalized string. * @example * - * _.snakeCase('Hello world'); - * // => 'hello_world' - * - * _.snakeCase('--hello-world'); - * // => 'hello_world' - * - * _.snakeCase('helloWorld'); - * // => 'hello_world' + * _.capitalize('fred'); + * // => 'Fred' */ - var snakeCase = createCompounder(function(result, word, index) { - return result + (index ? '_' : '') + word.toLowerCase(); - }); + function capitalize(string) { + if (string == null) { + return ''; + } + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } /** - * Checks if `string` starts with a given target string. + * Converts the characters "&", "<", ">", '"', and "'" in `string` to + * their corresponding HTML entities. + * + * Note: No other characters are escaped. To escape additional characters + * use a third-party library like [_he_](http://mths.be/he). + * + * When working with HTML you should always quote attribute values to reduce + * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) + * for more details. * * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The string to search. - * @param {string} [target] The string to search for. - * @param {number} [position=0] The position to search from. - * @returns {boolean} Returns `true` if the given string starts with the - * target string, else `false`. + * @param {string} string The string to escape. + * @returns {string} Returns the escaped string. * @example * - * _.startsWith('abc', 'a'); - * // => true - * - * _.startsWith('abc', 'b'); - * // => false - * - * _.startsWith('abc', 'b', 1); - * // => true + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' */ - function startsWith(string, target, position) { - string = string == null ? '' : String(string); - position = typeof position == 'undefined' ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length); - return string.lastIndexOf(target, position) == position; + function escape(string) { + return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); } /** @@ -7349,8 +6807,8 @@ * settings object is provided it will override `_.templateSettings` for the * template. * - * Note: In the development build, `_.template` utilizes `sourceURL`s for easier debugging. - * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * Note: In the development build, `_.template` utilizes sourceURLs for easier + * debugging. See [HTML5 Rocks' article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * * For more information on precompiling templates see @@ -7362,17 +6820,17 @@ * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The template string. - * @param {Object} [data] The data object used to populate the template string. + * @param {string} text The template text. + * @param {Object} [data] The data object used to populate the text. * @param {Object} [options] The options object. * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. * @param {Object} [options.imports] An object to import into the template as local variables. * @param {RegExp} [options.interpolate] The "interpolate" delimiter. - * @param {string} [options.sourceURL] The `sourceURL` of the template's compiled source. + * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. * @param {string} [options.variable] The data object variable name. * @returns {Function|string} Returns the interpolated string if a data object - * is provided, else the compiled template function. + * is provided, else it returns a template function. * @example * * // using the "interpolate" delimiter to create a compiled template @@ -7407,7 +6865,7 @@ * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } }); * // => '
  • fred
  • barney
  • ' * - * // using the `sourceURL` option to specify a custom `sourceURL` for the template + * // using the `sourceURL` option to specify a custom sourceURL for the template * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' }); * compiled(data); * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector @@ -7429,18 +6887,20 @@ * };\ * '); */ - function template(string, data, options) { + function template(text, data, options) { // based on John Resig's `tmpl` implementation // http://ejohn.org/blog/javascript-micro-templating/ // and Laura Doktorova's doT.js // https://github.com/olado/doT var settings = lodash.templateSettings; - options = defaults({}, options, settings); - string = String(string == null ? '' : string); + text = String(text || ''); - var imports = defaults({}, options.imports, settings.imports), - importsKeys = keys(imports), - importsValues = values(imports); + // avoid missing dependencies when `iteratorTemplate` is not defined + options = iteratorTemplate ? defaults({}, options, settings) : settings; + + var imports = iteratorTemplate && defaults({}, options.imports, settings.imports), + importsKeys = iteratorTemplate ? keys(imports) : ['_'], + importsValues = iteratorTemplate ? values(imports) : [lodash]; var isEscaping, isEvaluating, @@ -7456,11 +6916,11 @@ (options.evaluate || reNoMatch).source + '|$' , 'g'); - string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); // escape characters that cannot be included in string literals - source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar); // replace delimiters with snippets if (escapeValue) { @@ -7513,7 +6973,7 @@ source + 'return __p\n}'; - // Use a `sourceURL` for easier debugging. + // Use a sourceURL for easier debugging. // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/'; @@ -7539,7 +6999,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The string to trim. + * @param {string} string The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example @@ -7550,17 +7010,12 @@ * _.trim('-_-fred-_-', '_-'); * // => 'fred' */ - function trim(string, chars) { - string = string == null ? '' : String(string); - if (!string) { - return string; - } - if (chars == null) { - return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + var trim = !nativeTrim ? shimTrim : function(string, chars) { + if (string == null) { + return ''; } - chars = String(chars); - return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); - } + return chars == null ? nativeTrim.call(string) : shimTrim(string, chars); + }; /** * Removes leading whitespace or specified characters from `string`. @@ -7568,7 +7023,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The string to trim. + * @param {string} string The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example @@ -7579,17 +7034,12 @@ * _.trimLeft('-_-fred-_-', '_-'); * // => 'fred-_-' */ - function trimLeft(string, chars) { - string = string == null ? '' : String(string); - if (!string) { - return string; - } - if (chars == null) { - return string.slice(trimmedLeftIndex(string)) + var trimLeft = !nativeTrimLeft ? shimTrimLeft : function(string, chars) { + if (string == null) { + return ''; } - chars = String(chars); - return string.slice(charsLeftIndex(string, chars)); - } + return chars == null ? nativeTrimLeft.call(string) : shimTrimLeft(string, chars); + }; /** * Removes trailing whitespace or specified characters from `string`. @@ -7597,7 +7047,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The string to trim. + * @param {string} string The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example @@ -7608,96 +7058,12 @@ * _.trimRight('-_-fred-_-', '_-'); * // => '-_-fred' */ - function trimRight(string, chars) { - string = string == null ? '' : String(string); - if (!string) { - return string; - } - if (chars == null) { - return string.slice(0, trimmedRightIndex(string) + 1) - } - chars = String(chars); - return string.slice(0, charsRightIndex(string, chars) + 1); - } - - /** - * Truncates `string` if it is longer than the given maximum string length. - * The last characters of the truncated string will be replaced with the - * omission string which defaults to "...". - * - * @static - * @memberOf _ - * @category Strings - * @param {string} [string=''] The string to truncate. - * @param {Object|number} [options] The options object or maximum string length. - * @param {number} [options.length=30] The maximum string length. - * @param {string} [options.omission='...'] The string used to indicate text is omitted. - * @param {RegExp|string} [options.separator] The separator pattern to truncate to. - * @returns {string} Returns the truncated string. - * @example - * - * _.truncate('hi-diddly-ho there, neighborino'); - * // => 'hi-diddly-ho there, neighbo...' - * - * _.truncate('hi-diddly-ho there, neighborino', 24); - * // => 'hi-diddly-ho there, n...' - * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); - * // => 'hi-diddly-ho there,...' - * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); - * //=> 'hi-diddly-ho there...' - * - * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); - * // => 'hi-diddly-ho there, neig [...]' - */ - function truncate(string, options) { - var length = 30, - omission = '...'; - - if (options && isObject(options)) { - var separator = 'separator' in options ? options.separator : separator; - length = 'length' in options ? +options.length || 0 : length; - omission = 'omission' in options ? String(options.omission) : omission; - } - else if (options != null) { - length = +options || 0; - } - string = string == null ? '' : String(string); - if (length >= string.length) { - return string; - } - var end = length - omission.length; - if (end < 1) { - return omission; - } - var result = string.slice(0, end); - if (separator == null) { - return result + omission; - } - if (isRegExp(separator)) { - if (string.slice(end).search(separator)) { - var match, - newEnd, - substring = string.slice(0, end); - - if (!separator.global) { - separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g'); - } - separator.lastIndex = 0; - while ((match = separator.exec(substring))) { - newEnd = match.index; - } - result = result.slice(0, newEnd == null ? end : newEnd); - } - } else if (string.indexOf(separator, end) != end) { - var index = result.lastIndexOf(separator); - if (index > -1) { - result = result.slice(0, index); - } + var trimRight = !nativeTrimRight ? shimTrimRight : function(string, chars) { + if (string == null) { + return ''; } - return result + omission; - } + return chars == null ? nativeTrimRight.call(string) : shimTrimRight(string, chars); + }; /** * The inverse of `_.escape`; this method converts the HTML entities @@ -7710,7 +7076,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} [string=''] The string to unescape. + * @param {string} string The string to unescape. * @returns {string} Returns the unescaped string. * @example * @@ -7749,7 +7115,7 @@ } /** - * Creates a function bound to an optional `thisArg`. If `func` is a property + * Produces a callback bound to an optional `thisArg`. If `func` is a property * name the created callback will return the property value for a given element. * If `func` is an object the created callback will return `true` for elements * that contain the equivalent object properties, otherwise it will return `false`. @@ -7761,7 +7127,7 @@ * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns the new function. + * @returns {Function} Returns a callback function. * @example * * var characters = [ @@ -7783,11 +7149,11 @@ function createCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function' || func == null) { - return (typeof thisArg == 'undefined' || !(func && 'prototype' in func)) && + return (typeof thisArg == 'undefined' || !('prototype' in func)) && func || baseCreateCallback(func, thisArg, argCount); } // handle "_.pluck" and "_.where" style callback shorthands - return type == 'object' ? matches(func) : property(func); + return type != 'object' ? property(func) : matches(func); } /** @@ -7809,9 +7175,9 @@ } /** - * Creates a "_.where" style predicate function which performs a deep comparison - * between a given object and the `source` object, returning `true` if the given - * object has equivalent property values, else `false`. + * Creates a "_.where" style function, which performs a deep comparison + * between a given object and the `source` object, returning `true` if the + * given object has equivalent property values, else `false`. * * @static * @memberOf _ @@ -7834,33 +7200,32 @@ * // => { 'name': 'barney', 'age': 36 } */ function matches(source) { + source || (source = {}); + var props = keys(source), - propsLength = props.length, key = props[0], - value = propsLength && source[key]; + a = source[key]; // fast path the common case of providing an object with a single // property containing a primitive value - if (propsLength == 1 && value === value && !isObject(value)) { + if (props.length == 1 && a === a && !isObject(a)) { return function(object) { - if (!(object && hasOwnProperty.call(object, key))) { + if (!hasOwnProperty.call(object, key)) { return false; } // treat `-0` vs. `+0` as not equal - var other = object[key]; - return value === other && (value !== 0 || (1 / value == 1 / other)); + var b = object[key]; + return a === b && (a !== 0 || (1 / a == 1 / b)); }; } return function(object) { - var length = propsLength; - if (length && !object) { - return false; - } - var result = true; + var length = props.length, + result = false; + while (length--) { var key = props[length]; if (!(result = hasOwnProperty.call(object, key) && - baseIsEqual(object[key], source[key], null, true))) { + baseIsEqual(object[key], source[key], null, true))) { break; } } @@ -7875,12 +7240,10 @@ * @static * @memberOf _ * @category Utilities - * @param {Function|Object} [object=this] object The destination object. + * @param {Function|Object} [object=lodash] object The destination object. * @param {Object} source The object of functions to add. * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added - * are chainable. - * @returns {Function|Object} Returns `object`. + * @param {boolean} [options.chain=true] Specify whether the functions added are chainable. * @example * * function vowels(string) { @@ -7909,7 +7272,7 @@ options = source; } source = object; - object = this; + object = lodash; methodNames = functions(source); } if (options === false) { @@ -7946,11 +7309,10 @@ }(func)); } } - return object; } /** - * Reverts the `_` variable to its previous value and returns a reference to + * Reverts the '_' variable to its previous value and returns a reference to * the `lodash` function. * * @static @@ -8001,8 +7363,8 @@ /** * Converts `value` to an integer of the specified radix. If `radix` is - * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, - * in which case a `radix` of `16` is used. + * `undefined` or `0` a `radix` of `10` is used unless the `value` is a + * hexadecimal, in which case a `radix` of `16` is used. * * Note: This method avoids differences in native ES3 and ES5 `parseInt` * implementations. See the [ES5 spec](http://es5.github.io/#E) @@ -8013,7 +7375,7 @@ * @category Utilities * @param {string} value The value to parse. * @param {number} [radix] The radix used to interpret the value to parse. - * @returns {number} Returns the converted integer. + * @returns {number} Returns the new integer value. * @example * * _.parseInt('08'); @@ -8028,7 +7390,7 @@ }; /** - * Creates a "_.pluck" style function which returns the `key` value of a + * Creates a "_.pluck" style function, which returns the `key` value of a * given object. * * @static @@ -8053,14 +7415,14 @@ */ function property(key) { return function(object) { - return object == null ? undefined : object[key]; + return object[key]; }; } /** * Produces a random number between `min` and `max` (inclusive). If only one * argument is provided a number between `0` and the given number will be - * returned. If `floating` is truthy or either `min` or `max` are floats a + * returned. If `floating` is truey or either `min` or `max` are floats a * floating-point number will be returned instead of an integer. * * @static @@ -8069,7 +7431,7 @@ * @param {number} [min=0] The minimum possible value. * @param {number} [max=1] The maximum possible value. * @param {boolean} [floating=false] Specify returning a floating-point number. - * @returns {number} Returns the random number. + * @returns {number} Returns a random number. * @example * * _.random(0, 5); @@ -8116,61 +7478,6 @@ return baseRandom(min, max); } - /** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to but not including `end`. If `start` is less than `stop` a - * zero-length range is created unless a negative `step` is specified. - * - * @static - * @memberOf _ - * @category Utilities - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns the new array of numbers. - * @example - * - * _.range(4); - * // => [0, 1, 2, 3] - * - * _.range(1, 5); - * // => [1, 2, 3, 4] - * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] - * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] - * - * _.range(1, 4, 0); - * // => [1, 1, 1] - * - * _.range(0); - * // => [] - */ - function range(start, end, step) { - start = +start || 0; - step = step == null ? 1 : (+step || 0); - - if (end == null) { - end = start; - start = 0; - } else { - end = +end || 0; - } - // use `Array(length)` so engines like Chakra and V8 avoid slower modes - // http://youtu.be/XAqIpGU8ZZk#t=17m25s - var index = -1, - length = nativeMax(ceil((end - start) / (step || 1)), 0), - result = Array(length); - - while (++index < length) { - result[index] = start; - start += step; - } - return result; - } - /** * Resolves the value of property `key` on `object`. If `key` is a function * it will be invoked with the `this` binding of `object` and its result @@ -8221,9 +7528,9 @@ * @memberOf _ * @category Utilities * @param {number} n The number of times to execute the callback. - * @param {Function} [callback=identity] The function called per iteration. + * @param {Function} callback The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns the array of results. + * @returns {Array} Returns an array of the results of each `callback` execution. * @example * * var diceRolls = _.times(3, _.partial(_.random, 1, 6)); @@ -8236,12 +7543,11 @@ * // => also calls `mage.castSpell(n)` three times */ function times(n, callback, thisArg) { - n = n < 0 ? 0 : n >>> 0; - callback = baseCreateCallback(callback, thisArg, 1); - + n = (n = +n) > -1 ? n : 0; var index = -1, result = Array(n); + callback = baseCreateCallback(callback, thisArg, 1); while (++index < n) { result[index] = callback(index); } @@ -8291,10 +7597,6 @@ lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; - lodash.drop = drop; - lodash.dropRight = dropRight; - lodash.dropRightWhile = dropRightWhile; - lodash.dropWhile = dropWhile; lodash.filter = filter; lodash.flatten = flatten; lodash.forEach = forEach; @@ -8311,7 +7613,6 @@ lodash.invert = invert; lodash.invoke = invoke; lodash.keys = keys; - lodash.keysIn = keysIn; lodash.map = map; lodash.mapValues = mapValues; lodash.matches = matches; @@ -8319,8 +7620,6 @@ lodash.memoize = memoize; lodash.merge = merge; lodash.min = min; - lodash.mixin = mixin; - lodash.negate = negate; lodash.omit = omit; lodash.once = once; lodash.pairs = pairs; @@ -8334,6 +7633,7 @@ lodash.range = range; lodash.reject = reject; lodash.remove = remove; + lodash.removeAt = removeAt; lodash.rest = rest; lodash.shuffle = shuffle; lodash.slice = slice; @@ -8346,7 +7646,6 @@ lodash.union = union; lodash.uniq = uniq; lodash.values = values; - lodash.valuesIn = valuesIn; lodash.where = where; lodash.without = without; lodash.wrap = wrap; @@ -8357,6 +7656,7 @@ // add aliases lodash.callback = createCallback; lodash.collect = map; + lodash.drop = rest; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; @@ -8368,19 +7668,16 @@ lodash.unzip = zip; // add functions to `lodash.prototype` - mixin(lodash, assign({}, lodash)); + mixin(assign({}, lodash)); /*--------------------------------------------------------------------------*/ // add functions that return unwrapped values when chaining - lodash.camelCase = camelCase; lodash.capitalize = capitalize; lodash.clone = clone; lodash.cloneDeep = cloneDeep; lodash.contains = contains; - lodash.endsWith = endsWith; lodash.escape = escape; - lodash.escapeRegExp = escapeRegExp; lodash.every = every; lodash.find = find; lodash.findIndex = findIndex; @@ -8388,7 +7685,6 @@ lodash.findLast = findLast; lodash.findLastIndex = findLastIndex; lodash.findLastKey = findLastKey; - lodash.findWhere = findWhere; lodash.has = has; lodash.identity = identity; lodash.indexOf = indexOf; @@ -8399,7 +7695,6 @@ lodash.isElement = isElement; lodash.isEmpty = isEmpty; lodash.isEqual = isEqual; - lodash.isError = isError; lodash.isFinite = isFinite; lodash.isFunction = isFunction; lodash.isNaN = isNaN; @@ -8410,31 +7705,24 @@ lodash.isRegExp = isRegExp; lodash.isString = isString; lodash.isUndefined = isUndefined; - lodash.kebabCase = kebabCase; lodash.lastIndexOf = lastIndexOf; + lodash.mixin = mixin; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; - lodash.pad = pad; - lodash.padLeft = padLeft; - lodash.padRight = padRight; lodash.parseInt = parseInt; lodash.random = random; lodash.reduce = reduce; lodash.reduceRight = reduceRight; - lodash.repeat = repeat; lodash.result = result; lodash.runInContext = runInContext; lodash.size = size; lodash.some = some; lodash.sortedIndex = sortedIndex; - lodash.snakeCase = snakeCase; - lodash.startsWith = startsWith; lodash.template = template; lodash.trim = trim; lodash.trimLeft = trimLeft; lodash.trimRight = trimRight; - lodash.truncate = truncate; lodash.unescape = unescape; lodash.uniqueId = uniqueId; @@ -8442,12 +7730,13 @@ lodash.all = every; lodash.any = some; lodash.detect = find; + lodash.findWhere = find; lodash.foldl = reduce; lodash.foldr = reduceRight; lodash.include = contains; lodash.inject = reduce; - mixin(lodash, function() { + mixin(function() { var source = {} baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { @@ -8463,12 +7752,9 @@ lodash.first = first; lodash.last = last; lodash.sample = sample; - lodash.take = take; - lodash.takeRight = takeRight; - lodash.takeRightWhile = takeRightWhile; - lodash.takeWhile = takeWhile; // add aliases + lodash.take = first; lodash.head = first; baseForOwn(lodash, function(func, methodName) { @@ -8498,13 +7784,12 @@ // add "Chaining" functions to the wrapper lodash.prototype.chain = wrapperChain; - lodash.prototype.toJSON = wrapperValueOf; lodash.prototype.toString = wrapperToString; lodash.prototype.value = wrapperValueOf; lodash.prototype.valueOf = wrapperValueOf; // add `Array` functions that return unwrapped values - arrayEach(['join', 'pop', 'shift'], function(methodName) { + baseEach(['join', 'pop', 'shift'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { var chainAll = this.__chain__, @@ -8517,7 +7802,7 @@ }); // add `Array` functions that return the existing wrapped value - arrayEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) { + baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { func.apply(this.__wrapped__, arguments); @@ -8526,7 +7811,7 @@ }); // add `Array` functions that return new wrapped values - arrayEach(['concat', 'splice'], function(methodName) { + baseEach(['concat', 'splice'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__); @@ -8536,7 +7821,7 @@ // avoid array-like object bugs with `Array#shift` and `Array#splice` // in IE < 9, Firefox < 10, Narwhal, and RingoJS if (!support.spliceObjects) { - arrayEach(['pop', 'shift', 'splice'], function(methodName) { + baseEach(['pop', 'shift', 'splice'], function(methodName) { var func = arrayRef[methodName], isSplice = methodName == 'splice'; @@ -8554,6 +7839,12 @@ }; }); } + + // add pseudo private property to be used and removed during the build process + lodash._baseForIn = baseForIn; + lodash._iteratorTemplate = iteratorTemplate; + lodash._shimKeys = shimKeys; + return lodash; } diff --git a/test/test.js b/test/test.js index 68b4f3a26d..1212c67590 100644 --- a/test/test.js +++ b/test/test.js @@ -4,10 +4,7 @@ var undefined; /** Used as the size to cover large array optimizations */ - var largeArraySize = 200; - - /** Used as the maximum length an array-like object */ - var maxSafeInteger = Math.pow(2, 53) - 1; + var LARGE_ARRAY_SIZE = 200; /** Used as a reference to the global object */ var root = typeof global == 'object' && global || this; @@ -28,9 +25,7 @@ push = Array.prototype.push, slice = Array.prototype.slice, system = root.system, - toString = Object.prototype.toString; - - var JSON = root.JSON, + toString = Object.prototype.toString, Worker = document && root.Worker; /** The file path of the Lo-Dash file to test */ @@ -83,8 +78,8 @@ /** Detect if testing `npm` modules */ var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]); - /** Detects if running in PhantomJS */ - var isPhantom = phantom || typeof callPhantom == 'function'; + /** Detects if running in a PhantomJS web page */ + var isPhantomPage = typeof callPhantom == 'function'; /** Detect if running in Rhino */ var isRhino = isJava && typeof global == 'function' && global().Array === root.Array; @@ -185,7 +180,7 @@ return result; }()); - /** Used to check problem JScript properties (a.k.a. the `[[DontEnum]]` bug) */ + /** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */ var shadowedProps = [ 'constructor', 'hasOwnProperty', @@ -267,7 +262,6 @@ "'_array': [1, 2, 3],", "'_boolean': new Boolean(false),", "'_date': new Date,", - "'_errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],", "'_function': function() {},", "'_nan': NaN,", "'_null': null,", @@ -275,7 +269,7 @@ "'_object': { 'a': 1, 'b': 2, 'c': 3 },", "'_regexp': /x/,", "'_string': new String('a'),", - "'_undefined': undefined", + "'_undefined': undefined,", '})' ].join('\n'))); } @@ -294,12 +288,15 @@ } // allow bypassing native checks var _fnToString = Function.prototype.toString; - setProperty(Function.prototype, 'toString', function wrapper() { - setProperty(Function.prototype, 'toString', _fnToString); - var result = this === Set ? this.toString() : _fnToString.call(this); - setProperty(Function.prototype, 'toString', wrapper); - return result; - }); + setProperty(Function.prototype, 'toString', (function() { + function fnToString() { + setProperty(Function.prototype, 'toString', _fnToString); + var result = this === Set ? this.toString() : _fnToString.call(this); + setProperty(Function.prototype, 'toString', fnToString); + return result; + } + return fnToString; + }())); // fake DOM setProperty(global, 'window', {}); @@ -321,7 +318,7 @@ var _now = Date.now; setProperty(Date, 'now', function() {}); - var _create = create; + var _create = Object.create; setProperty(Object, 'create', function() {}); var _defineProperty = Object.defineProperty; @@ -333,17 +330,18 @@ var _keys = Object.keys; setProperty(Object, 'keys', function() {}); - var _hasOwnProperty = Object.prototype.hasOwnProperty; - setProperty(Object.prototype, 'hasOwnProperty', function(key) { - if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0])) { - throw new Error; - } - return _hasOwnProperty.call(this, key); - }); - var _contains = String.prototype.contains; setProperty(String.prototype, 'contains', _contains ? function() {} : Boolean); + var _trim = String.prototype.trim; + setProperty(String.prototype, 'trim', _trim ? function() {} : String); + + var _trimLeft = String.prototype.trimLeft; + setProperty(String.prototype, 'trimLeft', _trimLeft ? function() {} : String); + + var _trimRight = String.prototype.trimRight; + setProperty(String.prototype, 'trimRight', _trimRight ? function() {} : String); + // clear cache so Lo-Dash can be reloaded emptyObject(require.cache); @@ -357,14 +355,22 @@ setProperty(Object, 'defineProperty', _defineProperty); setProperty(Object, 'getPrototypeOf', _getPrototypeOf); setProperty(Object, 'keys', _keys); - setProperty(Object.prototype, 'hasOwnProperty', _hasOwnProperty); setProperty(Function.prototype, 'toString', _fnToString); - if (_contains) { - setProperty(String.prototype, 'contains', _contains); - } else { - delete String.prototype.contains; - } + _.forOwn({ + 'contains': _contains, + 'trim': _trim, + 'trimLeft': _trimLeft, + 'trimRight': _trimRight + }, + function(func, key) { + if (func) { + setProperty(String.prototype, key, func); + } else { + delete String.prototype[key]; + } + }); + delete global.window; delete global.WinRTError; delete Function.prototype._method; @@ -387,7 +393,6 @@ 'parent._._boolean = new Boolean(false);', 'parent._._date = new Date;', "parent._._element = document.createElement('div');", - 'parent._._errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError];', 'parent._._function = function() {};', 'parent._._nan = NaN;', 'parent._._null = null;', @@ -423,7 +428,7 @@ (function() { test('supports loading ' + basename + ' as the "lodash" module', 1, function() { if (amd) { - strictEqual((lodashModule || {}).moduleName, 'lodash'); + equal((lodashModule || {}).moduleName, 'lodash'); } else { skipTest(); @@ -432,7 +437,7 @@ test('supports loading ' + basename + ' with the Require.js "shim" configuration option', 1, function() { if (amd && /requirejs/.test(ui.loaderPath)) { - strictEqual((shimmedModule || {}).moduleName, 'shimmed'); + equal((shimmedModule || {}).moduleName, 'shimmed'); } else { skipTest(); } @@ -440,7 +445,7 @@ test('supports loading ' + basename + ' as the "underscore" module', 1, function() { if (amd && !/dojo/.test(ui.loaderPath)) { - strictEqual((underscoreModule || {}).moduleName, 'underscore'); + equal((underscoreModule || {}).moduleName, 'underscore'); } else { skipTest(); @@ -458,7 +463,7 @@ setTimeout(attempt, 16); return; } - strictEqual(actual, _.VERSION); + equal(actual, _.VERSION); QUnit.start(); }; @@ -472,27 +477,28 @@ test('should not add `Function.prototype` extensions to lodash', 1, function() { if (lodashBizarro) { - ok(!('_method' in lodashBizarro)); + equal('_method' in lodashBizarro, false); } else { skipTest(); } }); - test('should avoid overwritten native methods', 9, function() { + test('should avoid overwritten native methods', 12, function() { function Foo() {} function message(methodName) { return '`_.' + methodName + '` should avoid overwritten native methods'; } + var object = { 'a': true }; - var object = { 'a': 1 }, - otherObject = { 'b': 2 }, - largeArray = _.times(largeArraySize, _.constant(object)); + var largeArray = _.times(LARGE_ARRAY_SIZE, function() { + return object; + }); if (lodashBizarro) { try { - var actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'length': 0 })]; + actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'length': 0 })]; } catch(e) { actual = null; } @@ -514,11 +520,11 @@ deepEqual(actual[1], {}, message('Object.create')); try { - actual = lodashBizarro.bind(function() { return this.a; }, object); + var actual = lodashBizarro.bind(function() { return this.a; }, object); } catch(e) { actual = null; } - ok(!(expando in actual), message('Object.defineProperty')); + equal(expando in actual, false, message('Object.defineProperty')); try { actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; @@ -536,14 +542,14 @@ try { actual = [ - lodashBizarro.difference([object, otherObject], largeArray), + lodashBizarro.difference([object], largeArray), lodashBizarro.intersection(largeArray, [object]), lodashBizarro.uniq(largeArray) ]; } catch(e) { actual = null; } - deepEqual(actual, [[otherObject], [object], [object]], message('Set')); + deepEqual(actual, [[], [object], [object]], message('Set')); try { actual = lodashBizarro.contains('abc', 'c'); @@ -551,9 +557,23 @@ actual = null; } strictEqual(actual, true, message('String#contains')); + + _.forEach(['trim', 'trimLeft', 'trimRight'], function(methodName) { + try { + var actual = [ + lodashBizarro[methodName](whitespace + 'a b c' + whitespace), + lodashBizarro[methodName](''), + lodashBizarro[methodName]('-_-a-b-c-_-', '_-'), + lodashBizarro[methodName]('', '_-') + ]; + } catch(e) { + actual = null; + } + ok(_.every(actual, _.isString), message('String#' + methodName)); + }); } else { - skipTest(9); + skipTest(12); } }); }()); @@ -569,7 +589,7 @@ test('should return provided `lodash` instances', 1,function() { var wrapped = _(false); - strictEqual(_(wrapped), wrapped); + equal(_(wrapped), wrapped); }); }()); @@ -578,23 +598,18 @@ QUnit.module('lodash.after'); (function() { - function after(n, times) { - var count = 0; - _.times(times, _.after(n, function() { count++; })); - return count; - } test('should create a function that executes `func` after `n` calls', 4, function() { + function after(n, times) { + var count = 0; + _.times(times, _.after(n, function() { count++; })); + return count; + } + strictEqual(after(5, 5), 1, 'after(n) should execute `func` after being called `n` times'); strictEqual(after(5, 4), 0, 'after(n) should not execute `func` unless called `n` times'); strictEqual(after(0, 0), 0, 'after(0) should not execute `func` immediately'); strictEqual(after(0, 1), 1, 'after(0) should execute `func` when called once'); }); - - test('should coerce non-finite `n` values to `0`', 3, function() { - _.each([-Infinity, NaN, Infinity], function(n) { - strictEqual(after(n, 1), 1); - }); - }); }()); /*--------------------------------------------------------------------------*/ @@ -611,6 +626,7 @@ this.a = 1; this.c = 3; } + Foo.prototype.b = 2; deepEqual(_.assign({}, new Foo), { 'a': 1, 'c': 3 }); }); @@ -631,6 +647,14 @@ deepEqual(_.assign({ 'a': 1, 'b': 2 }, expected), expected); }); + test('should not error on `null` or `undefined` sources (test in IE < 9)', 1, function() { + try { + deepEqual(_.assign({}, null, undefined, { 'a': 1 }), { 'a': 1 }); + } catch(e) { + ok(false); + } + }); + test('should work with a callback', 1, function() { var actual = _.assign({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) { return typeof a == 'undefined' ? b : a; @@ -693,7 +717,14 @@ deepEqual(actual, [1, 3]); }); - _.each({ + test('should work when used as a callback for `_.map`', 1, function() { + var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], + actual = _.map(array, _.at); + + deepEqual(actual, [[1], [5], [9]]); + }); + + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -726,7 +757,7 @@ var values = _.reject(falsey.slice(1), function(value) { return value == null; }), expected = _.map(values, function(value) { return [value]; }); - var actual = _.map(values, function(value) { + var actual = _.map(values, function(value, index) { try { var bound = _.bind(fn, value); return bound(); @@ -743,14 +774,14 @@ actual = bound('a'); ok(actual[0] === null || actual[0] && actual[0].Array); - strictEqual(actual[1], 'a'); + equal(actual[1], 'a'); _.times(2, function(index) { bound = index ? _.bind(fn, undefined) : _.bind(fn); actual = bound('b'); ok(actual[0] === undefined || actual[0] && actual[0].Array); - strictEqual(actual[1], 'b'); + equal(actual[1], 'b'); }); }); @@ -769,7 +800,7 @@ }); test('should support placeholders', 4, function() { - if (!isModularize) { + if (_._iteratorTemplate) { var object = {}, bound = _.bind(fn, object, _, 'b', _); @@ -784,7 +815,7 @@ }); test('should create a function with a `length` of `0`', 2, function() { - var fn = function(a, b, c) {}, + var func = function(a, b, c) {}, bound = _.bind(fn, {}); strictEqual(bound.length, 0); @@ -797,7 +828,6 @@ function Foo() { return this; } - var bound = _.bind(Foo, { 'a': 1 }), newBound = new bound; @@ -810,7 +840,6 @@ function Foo(value) { return value && object; } - var bound = _.bind(Foo), object = {}; @@ -825,6 +854,10 @@ deepEqual(bound(['b'], 'c'), [object, 'a', ['b'], 'c']); }); + test('should throw a TypeError if `func` is not a function', 1, function() { + raises(function() { _.bind(); }, TypeError); + }); + test('should return a wrapped value when chaining', 2, function() { if (!isNpm) { var object = {}, @@ -868,6 +901,7 @@ this._b = 2; this.a = function() { return this._a; }; } + Foo.prototype.b = function() { return this._b; }; var object = new Foo; @@ -951,122 +985,17 @@ var object = { 'name': 'fred', 'greet': function(greeting) { - return this.name + ' says: ' + greeting; + return greeting + ' ' + this.name; } }; - var bound = _.bindKey(object, 'greet', 'hi'); - strictEqual(bound(), 'fred says: hi'); + var func = _.bindKey(object, 'greet', 'hi'); + equal(func(), 'hi fred'); object.greet = function(greeting) { - return this.name + ' says: ' + greeting + '!'; - }; - strictEqual(bound(), 'fred says: hi!'); - }); - - test('should support placeholders', 4, function() { - var object = { - 'fn': function fn(a, b, c, d) { - return slice.call(arguments); - } + return greeting + ' ' + this.name + '!'; }; - - if (!isModularize) { - var bound = _.bindKey(object, 'fn', _, 'b', _); - deepEqual(bound('a', 'c'), ['a', 'b', 'c']); - deepEqual(bound('a'), ['a', 'b', undefined]); - deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']); - deepEqual(bound(), [undefined, 'b', undefined]); - } - else { - skipTest(4); - } - }); - }()); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('case methods'); - - _.each(['camel', 'kebab', 'snake'], function(caseName) { - var methodName = caseName + 'Case', - func = _[methodName]; - - var expected = (function() { - switch (caseName) { - case 'camel': return 'helloWorld'; - case 'kebab': return 'hello-world'; - case 'snake': return 'hello_world'; - } - }()); - - var burredLetters = [ - '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', - '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', - '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF' - ]; - - var deburredLetters = [ - 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', - 'D', 'N', 'O', 'O', 'O', 'O', 'O', '', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th', 'ss', - 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', - 'd', 'n', 'o', 'o', 'o', 'o', 'o', '', 'o', 'u', 'u', 'u', 'u', 'y', 'th', 'y' - ]; - - test('`_.' + methodName + '` should convert `string` to ' + caseName + ' case', 4, function() { - _.each(['Hello world', 'helloWorld', '--hello-world', '__hello_world__'], function(string) { - strictEqual(func(string), expected); - }); - }); - - test('`_.' + methodName + '` should handle double-converting strings', 4, function() { - _.each(['Hello world', 'helloWorld', '--hello-world', '__hello_world__'], function(string) { - strictEqual(func(func(string)), expected); - }); - }); - - test('`_.' + methodName + '` should deburr letters', 1, function() { - var actual = _.map(burredLetters, function(burred, index) { - var isCamel = caseName == 'camel', - deburrLetter = deburredLetters[index]; - - var string = isCamel - ? func('z' + burred) - : func(burred); - - var deburredString = isCamel - ? 'z' + deburrLetter - : deburrLetter.toLowerCase(); - - return string == deburredString; - }); - - ok(_.every(actual, _.identity)); - }); - - test('`_.' + methodName + '` should coerce `string` to a string', 2, function() { - var string = 'Hello world'; - strictEqual(func(Object(string)), expected); - strictEqual(func({ 'toString': _.constant(string) }), expected); - }); - }); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.camelCase'); - - (function() { - test('should work with numbers', 3, function() { - strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit'); - strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles'); - strictEqual(_.camelCase('xhr2 request'), 'xhr2Request'); - }); - - test('should handle acronyms', 3, function() { - strictEqual(_.camelCase('safe HTML'), 'safeHTML'); - strictEqual(_.camelCase('escape HTML entities'), 'escapeHTMLEntities'); - strictEqual(_.camelCase('XMLHttpRequest'), 'xmlHttpRequest'); + equal(func(), 'hi fred!'); }); }()); @@ -1076,9 +1005,15 @@ (function() { test('should capitalize the first character of a string', 3, function() { - strictEqual(_.capitalize('fred'), 'Fred'); - strictEqual(_.capitalize('Fred'), 'Fred'); - strictEqual(_.capitalize(' fred'), ' fred'); + equal(_.capitalize('fred'), 'Fred'); + equal(_.capitalize('Fred'), 'Fred'); + equal(_.capitalize(' fred'), ' fred'); + }); + + test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() { + strictEqual(_.capitalize(null), ''); + strictEqual(_.capitalize(undefined), ''); + strictEqual(_.capitalize(''), ''); }); }()); @@ -1100,7 +1035,7 @@ test('should return the existing wrapper when chaining', 1, function() { if (!isNpm) { var wrapper = _({ 'a': 0 }); - strictEqual(wrapper.chain(), wrapper); + equal(wrapper.chain(), wrapper); } else { skipTest(); @@ -1184,7 +1119,7 @@ Klass.prototype = { 'b': 1 }; var nonCloneable = { - 'a DOM element': body, + 'an element': body, 'a function': Klass }; @@ -1214,14 +1149,14 @@ actual = _.clone(expected); deepEqual(actual, expected); - ok(actual !== expected && actual[0] === expected[0]); + ok(actual != expected && actual[0] === expected[0]); }); test('`_.clone` should perform a shallow clone when used as a callback for `_.map`', 1, function() { var expected = [{ 'a': [0] }, { 'b': [1] }], actual = _.map(expected, _.clone); - ok(actual[0] !== expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b); + ok(actual[0] != expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b); }); test('`_.cloneDeep` should deep clone objects with circular references', 1, function() { @@ -1237,7 +1172,7 @@ ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object); }); - _.each([ + _.forEach([ 'clone', 'cloneDeep' ], @@ -1284,7 +1219,7 @@ return this[value]; }, { 'a': 'A' }); - strictEqual(actual, 'A'); + equal(actual, 'A'); }); test('`_.' + methodName + '` should handle cloning if `callback` returns `undefined`', 1, function() { @@ -1297,7 +1232,7 @@ actual = func(array); strictEqual(actual.index, 2); - strictEqual(actual.input, 'vwxyz'); + equal(actual.input, 'vwxyz'); }); test('`_.' + methodName + '` should deep clone `lastIndex` regexp property', 1, function() { @@ -1306,21 +1241,7 @@ regexp.exec('vwxyz'); var actual = func(regexp); - strictEqual(actual.lastIndex, 3); - }); - - test('`_.' + methodName + '` should not error on DOM elements', 1, function() { - if (document) { - var element = document.createElement('div'); - try { - strictEqual(func(element), element); - } catch(e) { - ok(false); - } - } - else { - skipTest(); - } + equal(actual.lastIndex, 3); }); }); }(1, 2, 3)); @@ -1356,7 +1277,7 @@ }; var welcome = _.compose(greet, format); - strictEqual(welcome('pebbles'), 'Hiya Penelope!'); + equal(welcome('pebbles'), 'Hiya Penelope!'); }); test('should return a new function', 1, function() { @@ -1406,59 +1327,40 @@ QUnit.module('lodash.contains'); (function() { - _.each({ + _.forEach({ 'an `arguments` object': arguments, - 'an array': [1, 2, 3, 4], - 'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, - 'a string': '1234' + 'an array': [1, 2, 3, 1, 2, 3], + 'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3 }, + 'a string': '123123' }, function(collection, key) { - var values = _.toArray(collection); - test('should work with ' + key + ' and return `true` for matched values', 1, function() { strictEqual(_.contains(collection, 3), true); }); test('should work with ' + key + ' and return `false` for unmatched values', 1, function() { - strictEqual(_.contains(collection, 5), false); + strictEqual(_.contains(collection, 4), false); }); - test('should work with ' + key + ' and a positive `fromIndex`', 2, function() { - strictEqual(_.contains(collection, values[2], 2), true); - strictEqual(_.contains(collection, values[1], 2), false); + test('should work with ' + key + ' and a positive `fromIndex`', 1, function() { + strictEqual(_.contains(collection, 1, 2), true); }); - test('should work with ' + key + ' and a `fromIndex` >= `collection.length`', 12, function() { - _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { + test('should work with ' + key + ' and a `fromIndex` >= `collection.length`', 6, function() { + _.forEach([6, 8], function(fromIndex) { strictEqual(_.contains(collection, 1, fromIndex), false); strictEqual(_.contains(collection, undefined, fromIndex), false); strictEqual(_.contains(collection, '', fromIndex), false); }); }); - test('should work with ' + key + ' and treat falsey `fromIndex` values as `0`', 1, function() { - var expected = _.map(falsey, _.constant(true)); - - var actual = _.map(falsey, function(fromIndex) { - return _.contains(collection, values[0], fromIndex); - }); - - deepEqual(actual, expected); - }); - - test('should work with ' + key + ' and treat non-number `fromIndex` values as `0`', 1, function() { - strictEqual(_.contains(collection, values[0], '1'), true); - }); - - test('should work with ' + key + ' and a negative `fromIndex`', 2, function() { - strictEqual(_.contains(collection, values[2], -2), true); - strictEqual(_.contains(collection, values[1], -2), false); + test('should work with ' + key + ' and a negative `fromIndex`', 1, function() { + strictEqual(_.contains(collection, 2, -3), true); }); - test('should work with ' + key + ' and a negative `fromIndex` <= negative `collection.length`', 3, function() { - _.each([-4, -6, -Infinity], function(fromIndex) { - strictEqual(_.contains(collection, values[0], fromIndex), true); - }); + test('should work with ' + key + ' and a negative `fromIndex` <= negative `collection.length`', 2, function() { + strictEqual(_.contains(collection, 1, -6), true); + strictEqual(_.contains(collection, 2, -8), true); }); test('should work with ' + key + ' and return an unwrapped value when chaining', 1, function() { @@ -1471,7 +1373,7 @@ }); }); - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -1489,7 +1391,7 @@ test('should be aliased', 1, function() { strictEqual(_.include, _.contains); }); - }(1, 2, 3, 4)); + }(1, 2, 3, 1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -1620,7 +1522,7 @@ test('should ignore primitive `prototype` arguments and use an empty object instead', 1, function() { var primitives = [true, null, 1, 'a', undefined], - expected = _.map(primitives, _.constant(true)); + expected = _.map(primitives, function() { return true; }); var actual = _.map(primitives, function(value, index) { return _.isPlainObject(index ? _.create(value) : _.create()); @@ -1635,60 +1537,28 @@ QUnit.module('lodash.callback'); (function() { - test('should create a callback with a falsey `thisArg`', 1, function() { - var values = _.map(falsey, function(value) { - return Object(value == null ? root : value); - }); - - var actual = _.map(values, function(value) { - var callback = _.callback(function() { return this; }, value); - return callback(); - }); - - deepEqual(actual, values); - }); - - test('should return `_.identity` when `func` is nullish', 2, function() { - var object = {}; - _.each([null, undefined], function(value) { - var callback = _.callback(value); - strictEqual(callback(object), object); - }); - }); - - test('should not error when `func` is nullish and a `thisArg` is provided', 2, function() { - var object = {}; - _.each([null, undefined], function(value) { - try { - var callback = _.callback(value, {}); - strictEqual(callback(object), object); - } catch(e) { - ok(false); - } - }); - }); - - test('should return a callback created by `_.matches` when `func` is an object', 2, function() { - var callback = _.callback({ 'a': 1 }); - strictEqual(callback({ 'a': 1, 'b': 2 }), true); - strictEqual(callback({}), false); - }); + test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() { + var fn = function() { + var result = [this.a]; + push.apply(result, arguments); + return result; + }; - test('should return a callback created by `_.property` when `func` is a number or string', 2, function() { - var array = ['a'], - callback = _.callback(0); + var expected = [1, 2, 3], + object = { 'a': 1 }, + callback = _.createCallback(_.partial(fn, 2), object); - strictEqual(callback(array), 'a'); + deepEqual(callback(3), expected); - callback = _.callback('0'); - strictEqual(callback(array), 'a'); + callback = _.createCallback(_.partialRight(fn, 3), object); + deepEqual(callback(2), expected); }); test('should work without an `argCount`', 1, function() { var args, expected = ['a', 'b', 'c', 'd', 'e']; - var callback = _.callback(function() { + var callback = _.createCallback(function() { args = slice.call(arguments); }); @@ -1696,23 +1566,6 @@ deepEqual(args, expected); }); - test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() { - function fn() { - var result = [this.a]; - push.apply(result, arguments); - return result; - } - - var expected = [1, 2, 3], - object = { 'a': 1 }, - callback = _.callback(_.partial(fn, 2), object); - - deepEqual(callback(3), expected); - - callback = _.callback(_.partialRight(fn, 3), object); - deepEqual(callback(2), expected); - }); - test('should return the function provided if already bound with `Function#bind`', 1, function() { function a() {} @@ -1721,7 +1574,7 @@ if (bound && !('prototype' in bound)) { var bound = a.bind(object); - strictEqual(_.callback(bound, object), bound); + strictEqual(_.createCallback(bound, object), bound); } else { skipTest(); @@ -1735,8 +1588,8 @@ var object = {}; if (_.support.funcDecomp) { - strictEqual(_.callback(a, object), a); - notStrictEqual(_.callback(b, object), b); + strictEqual(_.createCallback(a, object), a); + notStrictEqual(_.createCallback(b, object), b); } else { skipTest(2); @@ -1745,21 +1598,21 @@ test('should only write metadata to named functions', 3, function() { function a() {}; - var b = function() {}; function c() {}; - var object = {}; + var b = function() {}, + object = {}; if (defineProperty && _.support.funcDecomp) { - _.callback(a, object); + _.createCallback(a, object); ok(expando in a); - _.callback(b, object); - ok(!(expando in b)); + _.createCallback(b, object); + equal(expando in b, false); if (_.support.funcNames) { _.support.funcNames = false; - _.callback(c, object); + _.createCallback(c, object); ok(expando in c); _.support.funcNames = true; @@ -1777,8 +1630,8 @@ function a() {}; if (defineProperty && lodashBizarro) { - lodashBizarro.callback(a, {}); - ok(!(expando in a)); + lodashBizarro.createCallback(a, {}); + equal(expando in a, false); } else { skipTest(); @@ -1792,42 +1645,25 @@ (function() { function fn(a, b, c, d) { - return slice.call(arguments); + return a + b + c + d; } test('should curry based on the number of arguments provided', 3, function() { - var curried = _.curry(fn), - expected = [1, 2, 3, 4]; - - deepEqual(curried(1)(2)(3)(4), expected); - deepEqual(curried(1, 2)(3, 4), expected); - deepEqual(curried(1, 2, 3, 4), expected); + var curried = _.curry(fn); + equal(curried(1)(2)(3)(4), 10); + equal(curried(1, 2)(3, 4), 10); + equal(curried(1, 2, 3, 4), 10); }); test('should work with partialed methods', 2, function() { var curried = _.curry(fn), - expected = [1, 2, 3, 4]; - - var a = _.partial(curried, 1), + a = _.partial(curried, 1), b = _.bind(a, null, 2), c = _.partialRight(b, 4), d = _.partialRight(b(3), 4); - deepEqual(c(3), expected); - deepEqual(d(), expected); - }); - - test('should support placeholders', 4, function() { - if (!isModularize) { - var curried = _.curry(fn); - deepEqual(curried(1)(_, 3)(_, 4)(2), [1, 2, 3, 4]); - deepEqual(curried(_, 2)(1)(_, 4)(3), [1, 2, 3, 4]); - deepEqual(curried(_, _, 3)(_, 2)(_, 4)(1), [1, 2, 3, 4]); - deepEqual(curried(_, _, _, 4)(_, _, 3)(_, 2)(1), [1, 2, 3, 4]); - } - else { - skipTest(4); - } + equal(c(3), 10); + equal(d(), 10); }); test('should return a function with a `length` of `0`', 6, function() { @@ -1843,7 +1679,6 @@ function Foo(value) { return value && object; } - var curried = _.curry(Foo), object = {}; @@ -1852,26 +1687,24 @@ }); test('should not alter the `this` binding', 9, function() { - function fn(a, b, c) { + var fn = function(a, b, c) { var value = this || {}; - return [value[a], value[b], value[c]]; - } - - var object = { 'a': 1, 'b': 2, 'c': 3 }, - expected = [1, 2, 3]; + return value[a] + value[b] + value[c]; + }; - deepEqual(_.curry(_.bind(fn, object), 3)('a')('b')('c'), expected); - deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), expected); - deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), expected); + var object = { 'a': 1, 'b': 2, 'c': 3 }; + equal(_.curry(_.bind(fn, object), 3)('a')('b')('c'), 6); + equal(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), 6); + equal(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), 6); - deepEqual(_.bind(_.curry(fn), object)('a')('b')('c'), Array(3)); - deepEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), Array(3)); - deepEqual(_.bind(_.curry(fn), object)('a', 'b', 'c'), expected); + ok(_.isEqual(_.bind(_.curry(fn), object)('a')('b')('c'), NaN)); + ok(_.isEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), NaN)); + equal(_.bind(_.curry(fn), object)('a', 'b', 'c'), 6); object.curried = _.curry(fn); - deepEqual(object.curried('a')('b')('c'), Array(3)); - deepEqual(object.curried('a', 'b')('c'), Array(3)); - deepEqual(object.curried('a', 'b', 'c'), expected); + ok(_.isEqual(object.curried('a')('b')('c'), NaN)); + ok(_.isEqual(object.curried('a', 'b')('c'), NaN)); + equal(object.curried('a', 'b', 'c'), 6); }); }()); @@ -1889,10 +1722,10 @@ debounced(); debounced(); - strictEqual(count, 0); + equal(count, 0); setTimeout(function() { - strictEqual(count, 1); + equal(count, 1); QUnit.start(); }, 96); } @@ -1963,12 +1796,12 @@ } }); - asyncTest('should support a `leading` option', 7, function() { + asyncTest('should work with `leading` option', 7, function() { if (!(isRhino && isModularize)) { var withLeading, counts = [0, 0, 0]; - _.each([true, { 'leading': true }], function(options, index) { + _.forEach([true, { 'leading': true }], function(options, index) { var debounced = _.debounce(function(value) { counts[index]++; return value; @@ -1977,10 +1810,10 @@ if (index == 1) { withLeading = debounced; } - strictEqual(debounced('x'), 'x'); + equal(debounced('x'), 'x'); }); - _.each([false, { 'leading': false }], function(options) { + _.forEach([false, { 'leading': false }], function(options) { var withoutLeading = _.debounce(_.identity, 32, options); strictEqual(withoutLeading('x'), undefined); }); @@ -1998,7 +1831,7 @@ deepEqual(counts, [1, 1, 2]); withLeading('x'); - strictEqual(counts[1], 2); + equal(counts[1], 2); QUnit.start(); }, 64); @@ -2009,7 +1842,7 @@ } }); - asyncTest('should support a `trailing` option', 4, function() { + asyncTest('should work with `trailing` option', 4, function() { if (!(isRhino && isModularize)) { var withCount = 0, withoutCount = 0; @@ -2039,9 +1872,9 @@ } }); - test('should support a `maxWait` option', 2, function() { + test('should work with `maxWait` option', 2, function() { if (!(isRhino && isModularize)) { - var limit = (argv || isPhantom) ? 1000 : 256, + var limit = (argv || isPhantomPage) ? 1000 : 256, withCount = 0, withoutCount = 0; @@ -2105,7 +1938,7 @@ } } setTimeout(function() { - strictEqual(count, 2); + equal(count, 2); deepEqual(args, [object, 'a']); QUnit.start(); }, 64); @@ -2131,6 +1964,7 @@ this.a = 1; this.c = 3; } + Foo.prototype.b = 2; deepEqual(_.defaults({ 'c': 2 }, new Foo), { 'a': 1, 'c': 2 }); }); @@ -2150,6 +1984,14 @@ var actual = _.defaults({ 'a': undefined }, { 'a': 1 }); strictEqual(actual.a, 1); }); + + test('should not error on `null` or `undefined` sources (test in IE < 9)', 1, function() { + try { + deepEqual(_.defaults({ 'a': 1 }, null, undefined, { 'a': 2, 'b': 2 }), { 'a': 1, 'b': 2 }); + } catch(e) { + ok(false); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -2285,8 +2127,6 @@ QUnit.module('lodash.difference'); (function() { - var args = arguments; - test('should return the difference of the given arrays', 2, function() { var actual = _.difference([1, 2, 3, 4, 5], [5, 2, 10]); deepEqual(actual, [1, 3, 4]); @@ -2296,8 +2136,8 @@ }); test('should work with large arrays', 1, function() { - var array1 = _.range(largeArraySize + 1), - array2 = _.range(largeArraySize), + var array1 = _.range(LARGE_ARRAY_SIZE), + array2 = array1.slice(), a = {}, b = {}, c = {}; @@ -2305,73 +2145,22 @@ array1.push(a, b, c); array2.push(b, c, a); - deepEqual(_.difference(array1, array2), [largeArraySize]); + deepEqual(_.difference(array1, array2), []); }); test('should work with large arrays of objects', 1, function() { - var object1 = {}, - object2 = {}, - largeArray = _.times(largeArraySize, _.constant(object1)); - - deepEqual(_.difference([object1, object2], largeArray), [object2]); - }); - - test('should ignore values that are not arrays or `arguments` objects', 3, function() { - var array = [0, 1, null, 3]; - deepEqual(_.difference(array, 3, null, { '0': 1 }), array); - deepEqual(_.difference(null, array, null, [2, 1]), [0, null, 3]); - deepEqual(_.difference(null, array, null, args), [0, null]); - }); - }(1, 2, 3)); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.endsWith'); - - (function() { - var string = 'abc'; - - test('should return `true` if a string ends with `target`', 1, function() { - strictEqual(_.endsWith(string, 'c'), true); - }); - - test('should return `false` if a string does not end with `target`', 1, function() { - strictEqual(_.endsWith(string, 'b'), false); - }); - - test('should work with a `position` argument', 1, function() { - strictEqual(_.endsWith(string, 'b', 2), true); - }); - - test('should work with `position` >= `string.length`', 4, function() { - _.each([3, 5, maxSafeInteger, Infinity], function(position) { - strictEqual(_.endsWith(string, 'c', position), true); - }); - }); - - test('should treat falsey `position` values, except `undefined`, as `0`', 1, function() { - var expected = _.map(falsey, _.constant(true)); + var object = {}; - var actual = _.map(falsey, function(position) { - return _.endsWith(string, position === undefined ? 'c' : '', position); + var largeArray = _.times(LARGE_ARRAY_SIZE, function() { + return object; }); - deepEqual(actual, expected); - }); - - test('should treat a negative `position` as `0`', 6, function() { - _.each([-1, -3, -Infinity], function(position) { - ok(_.every(string, function(chr) { - return _.endsWith(string, chr, position) === false; - })); - strictEqual(_.endsWith(string, '', position), true); - }); + deepEqual(_.difference(largeArray, [object]), []); }); - test('should always return `true` when `target` is an empty string regardless of `position`', 1, function() { - ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, maxSafeInteger, Infinity], function(position) { - return _.endsWith(string, '', position, true); - })); + test('should ignore individual secondary values', 1, function() { + var array = [1, null, 3]; + deepEqual(_.difference(array, null, 3), array); }); }()); @@ -2384,36 +2173,21 @@ unescaped = '&<>"\'\/'; test('should escape values', 1, function() { - strictEqual(_.escape(unescaped), escaped); + equal(_.escape(unescaped), escaped); }); test('should not escape the "/" character', 1, function() { - strictEqual(_.escape('/'), '/'); + equal(_.escape('/'), '/'); }); test('should handle strings with nothing to escape', 1, function() { - strictEqual(_.escape('abc'), 'abc'); - }); - - test('should escape the same characters unescaped by `_.unescape`', 1, function() { - strictEqual(_.escape(_.unescape(escaped)), escaped); - }); - }()); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.escapeRegExp'); - - (function() { - test('should escape values', 1, function() { - var escaped = '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\/\\\\', - unescaped = '.*+?^${}()|[\]\/\\'; - - strictEqual(_.escapeRegExp(unescaped), escaped); + equal(_.escape('abc'), 'abc'); }); - test('should handle strings with nothing to escape', 1, function() { - strictEqual(_.escapeRegExp('abc'), 'abc'); + test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() { + strictEqual(_.escape(null), ''); + strictEqual(_.escape(undefined), ''); + strictEqual(_.escape(''), ''); }); }()); @@ -2423,7 +2197,7 @@ (function() { test('should return `true` for empty or falsey collections', 1, function() { - var expected = _.map(empties, _.constant(true)); + var expected = _.map(empties, function() { return true; }); var actual = _.map(empties, function(value) { try { @@ -2434,7 +2208,7 @@ deepEqual(actual, expected); }); - test('should return `true` if the callback returns truthy for all elements in the collection', 1, function() { + test('should return `true` if the callback returns truey for all elements in the collection', 1, function() { strictEqual(_.every([true, 1, 'x'], _.identity), true); }); @@ -2460,13 +2234,12 @@ QUnit.module('source property checks'); - _.each(['assign', 'defaults', 'merge'], function(methodName) { + _.forEach(['assign', 'defaults', 'merge'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should not assign inherited `source` properties', 1, function() { function Foo() {} Foo.prototype = { 'a': 1 }; - deepEqual(func({}, new Foo), {}); }); @@ -2488,7 +2261,7 @@ expected[1] = undefined; - ok('1' in actual); + ok(1 in actual); deepEqual(actual, expected); }); } @@ -2498,7 +2271,7 @@ QUnit.module('strict mode checks'); - _.each(['assign', 'bindAll', 'defaults'], function(methodName) { + _.forEach(['assign', 'bindAll', 'defaults'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should not throw strict mode errors', 1, function() { @@ -2529,7 +2302,7 @@ QUnit.module('lodash.filter'); (function() { - test('should return elements the `callback` returns truthy for', 1, function() { + test('should return elements the `callback` returns truey for', 1, function() { var actual = _.filter([1, 2, 3], function(num) { return num % 2; }); @@ -2565,26 +2338,25 @@ /*--------------------------------------------------------------------------*/ - _.each(['find', 'findLast', 'findIndex', 'findLastIndex', 'findKey', 'findLastKey'], function(methodName) { - QUnit.module('lodash.' + methodName); - - var func = _[methodName]; + (function() { + var objects = [ + { 'a': 0, 'b': 0 }, + { 'a': 1, 'b': 1 }, + { 'a': 2, 'b': 2 } + ]; - (function() { - var objects = [ - { 'a': 0, 'b': 0 }, - { 'a': 1, 'b': 1 }, - { 'a': 2, 'b': 2 } - ]; + _.forEach({ + 'find': [objects[1], undefined, objects[2], objects[1]], + 'findLast': [objects[2], undefined, objects[2], objects[2]], + 'findIndex': [1, -1, 2, 1], + 'findLastIndex': [2, -1, 2, 2], + 'findKey': ['1', undefined, '2', '1'], + 'findLastKey': ['2', undefined, '2', '2'] + }, + function(expected, methodName) { + QUnit.module('lodash.' + methodName); - var expected = ({ - 'find': [objects[1], undefined, objects[2], objects[1]], - 'findLast': [objects[2], undefined, objects[2], objects[2]], - 'findIndex': [1, -1, 2, 1], - 'findLastIndex': [2, -1, 2, 2], - 'findKey': ['1', undefined, '2', '1'], - 'findLastKey': ['2', undefined, '2', '2'] - })[methodName]; + var func = _[methodName]; test('should return the correct value', 1, function() { strictEqual(func(objects, function(object) { return object.a; }), expected[0]); @@ -2595,11 +2367,19 @@ }); test('should return `' + expected[1] + '` if value is not found', 1, function() { - strictEqual(func(objects, function(object) { return object.a === 3; }), expected[1]); - }); - - test('should work with an object for `callback`', 1, function() { - strictEqual(func(objects, { 'b': 2 }), expected[2]); + strictEqual(func(objects, function(object) { return object.a == 3; }), expected[1]); + }); + + test('should work with an object for `collection`', 1, function() { + var actual = _.find({ 'a': 1, 'b': 2, 'c': 3 }, function(num) { + return num > 2; + }); + + equal(actual, 3); + }); + + test('should work with an object for `callback`', 1, function() { + strictEqual(func(objects, { 'b': 2 }), expected[2]); }); test('should work with a string for `callback`', 1, function() { @@ -2611,7 +2391,7 @@ emptyValues = /Index/.test(methodName) ? _.reject(empties, _.isPlainObject) : empties, expecting = _.map(emptyValues, function() { return expected[1]; }); - _.each(emptyValues, function(value) { + _.forEach(emptyValues, function(value) { try { actual.push(func(value, { 'a': 3 })); } catch(e) { } @@ -2619,89 +2399,13 @@ deepEqual(actual, expecting); }); - }()); - - (function() { - var expected = ({ - 'find': 1, - 'findLast': 2, - 'findKey': 'a', - 'findLastKey': 'b' - })[methodName]; - - if (expected != null) { - test('should work with an object for `collection`', 1, function() { - var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(num) { - return num < 3; - }); - - strictEqual(actual, expected); - }); - } - }()); - - (function() { - var expected = ({ - 'find': 'a', - 'findLast': 'b', - 'findIndex': 0, - 'findLastIndex': 1 - })[methodName]; - if (expected != null) { - test('should work with a string for `collection`', 1, function() { - var actual = func('abc', function(chr, index) { - return index < 2; - }); - - strictEqual(actual, expected); - }); - } if (methodName == 'find') { - test('should be aliased', 1, function() { + test('should be aliased', 2, function() { strictEqual(_.detect, func); + strictEqual(_.findWhere, func); }); } - }()); - }); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.findWhere'); - - (function() { - var objects = [ - { 'a': 1 }, - { 'a': 1 }, - { 'a': 1, 'b': 2 }, - { 'a': 2, 'b': 2 }, - { 'a': 3 } - ]; - - test('should filter by `source` properties', 6, function() { - strictEqual(_.findWhere(objects, { 'a': 1 }), objects[0]); - strictEqual(_.findWhere(objects, { 'a': 2 }), objects[3]); - strictEqual(_.findWhere(objects, { 'a': 3 }), objects[4]); - strictEqual(_.findWhere(objects, { 'b': 1 }), undefined); - strictEqual(_.findWhere(objects, { 'b': 2 }), objects[2]); - strictEqual(_.findWhere(objects, { 'a': 1, 'b': 2 }), objects[2]); - }); - - test('should work with a function for `source`', 1, function() { - function source() {} - source.a = 2; - - strictEqual(_.findWhere(objects, source), objects[3]); - }); - - test('should match all elements when provided an empty `source`', 1, function() { - var expected = _.map(empties, _.constant(true)); - - var actual = _.map(empties, function(value) { - return _.findWhere(objects, value) === objects[0]; - }); - - deepEqual(actual, expected); }); }()); @@ -2726,26 +2430,14 @@ deepEqual(_.first(array, 2), [1, 2]); }); - test('should treat falsey `n` values, except nullish, as `0`', 1, function() { - var expected = _.map(falsey, function(value) { - return value == null ? 1 : []; - }); - - var actual = _.map(falsey, function(n) { - return _.first(array, n); - }); - - deepEqual(actual, expected); - }); - test('should return an empty array when `n` < `1`', 3, function() { - _.each([0, -1, -Infinity], function(n) { + _.forEach([0, -1, -2], function(n) { deepEqual(_.first(array, n), []); }); }); - test('should return all elements when `n` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { + test('should return all elements when `n` >= `array.length`', 2, function() { + _.forEach([3, 4], function(n) { deepEqual(_.first(array, n), array); }); }); @@ -2901,22 +2593,26 @@ expected.push(undefined, undefined, undefined); deepEqual(actual1, expected); - ok('4' in actual1); + ok(4 in actual1); deepEqual(actual2, expected); - ok('4' in actual2); + ok(4 in actual2); }); test('should work with extremely large arrays', 1, function() { - // test in modern browsers + var expected = Array(5e5), + pass = true; + if (freeze) { try { - var expected = Array(5e5), - actual = _.flatten([expected]); - - deepEqual(actual, expected) + var actual = _.flatten([expected]); } catch(e) { - ok(false); + pass = false; + } + if (pass) { + deepEqual(actual, expected); + } else { + ok(pass); } } else { skipTest(); @@ -2959,11 +2655,10 @@ QUnit.module('forEach methods'); - _.each(['forEach', 'forEachRight'], function(methodName) { - var func = _[methodName], - isForEach = methodName == 'forEach'; + _.forEach(['forEach', 'forEachRight'], function(methodName) { + var func = _[methodName]; - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -2977,7 +2672,7 @@ values.push(value); }); - if (isForEach) { + if (methodName == 'forEach') { deepEqual(args, ['a', 0, collection]); deepEqual(values, ['a', 'b', 'c']); } else { @@ -2988,7 +2683,7 @@ }); test('`_.' + methodName + '` should be aliased', 1, function() { - if (isForEach) { + if (methodName == 'forEach') { strictEqual(_.each, _.forEach); } else { strictEqual(_.eachRight, _.forEachRight); @@ -3000,7 +2695,7 @@ QUnit.module('forIn methods'); - _.each(['forIn', 'forInRight'], function(methodName) { + _.forEach(['forIn', 'forInRight'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` iterates over inherited properties', 1, function() { @@ -3017,7 +2712,7 @@ QUnit.module('forOwn methods'); - _.each(['forOwn', 'forOwnRight'], function(methodName) { + _.forEach(['forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; test('iterates over the `length` property', 1, function() { @@ -3035,20 +2730,15 @@ (function() { var methods = [ - 'countBy', 'every', 'filter', + 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', - 'groupBy', - 'indexBy', 'map', - 'max', - 'min', - 'partition', 'reject', 'some' ]; @@ -3058,26 +2748,6 @@ 'some' ]; - var collectionMethods = [ - 'countBy', - 'every', - 'filter', - 'find', - 'findLast', - 'forEach', - 'forEachRight', - 'groupBy', - 'indexBy', - 'map', - 'max', - 'min', - 'partition', - 'reduce', - 'reduceRight', - 'reject', - 'some' - ]; - var forInMethods = [ 'forIn', 'forInRight' @@ -3105,7 +2775,7 @@ 'forOwnRight' ]; - _.each(methods, function(methodName) { + _.forEach(methods, function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -3133,21 +2803,22 @@ function callback(num, index) { actual = this[index]; } + func([1], callback, [2]); - strictEqual(actual, 2); + equal(actual, 2); func({ 'a': 1 }, callback, { 'a': 2 }); - strictEqual(actual, 2); + equal(actual, 2); }); }); - _.each(_.difference(methods, boolMethods), function(methodName) { + _.forEach(_.difference(methods, boolMethods), function(methodName) { var array = [1, 2, 3], func = _[methodName]; test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() { if (!isNpm) { - var actual = _(array)[methodName](_.noop); + var actual = _(array)[methodName](noop); ok(actual instanceof _); } else { @@ -3156,7 +2827,7 @@ }); }); - _.each(_.difference(methods, forInMethods), function(methodName) { + _.forEach(_.difference(methods, forInMethods), function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -3170,56 +2841,34 @@ }); }); - _.each(iterationMethods, function(methodName) { + _.forEach(iterationMethods, function(methodName) { var array = [1, 2, 3], func = _[methodName]; test('`_.' + methodName + '` should return the collection', 1, function() { - strictEqual(func(array, Boolean), array); + equal(func(array, Boolean), array); }); test('`_.' + methodName + '` should return the existing wrapper when chaining', 1, function() { if (!isNpm) { var wrapper = _(array); - strictEqual(wrapper[methodName](_.noop), wrapper); + equal(wrapper[methodName](noop), wrapper); } else { skipTest(); } }); }); - - _.each(collectionMethods, function(methodName) { - var func = _[methodName]; - - test('`_.' + methodName + '` should treat objects with lengths of `0` as array-like', 1, function() { - var pass = true; - func({ 'length': 0 }, function() { pass = false; }, 0); - ok(pass); - }); - - test('`_.' + methodName + '` should not treat objects with negative lengths as array-like', 1, function() { - var pass = false; - func({ 'length': -1 }, function() { pass = true; }, 0); - ok(pass); - }); - - test('`_.' + methodName + '` should not treat objects with non-number lengths as array-like', 1, function() { - var pass = false; - func({ 'length': '0' }, function() { pass = true; }, 0); - ok(pass); - }); - }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('collection iteration bugs'); - _.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { + _.forEach(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; - test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + test('`_.' + methodName + '` fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { var props = []; func(shadowedObject, function(value, prop) { props.push(prop); }); deepEqual(props.sort(), shadowedProps); @@ -3276,17 +2925,13 @@ QUnit.module('object assignments'); - _.each(['assign', 'defaults', 'merge'], function(methodName) { + _.forEach(['assign', 'defaults', 'merge'], function(methodName) { var func = _[methodName]; - test('`_.' + methodName + '` should return `undefined` when no destination object is provided', 1, function() { - strictEqual(func(), undefined); - }); - test('`_.' + methodName + '` should return the existing wrapper when chaining', 1, function() { if (!isNpm) { var wrapper = _({ 'a': 1 }); - strictEqual(wrapper[methodName]({ 'b': 2 }), wrapper); + equal(wrapper[methodName]({ 'b': 2 }), wrapper); } else { skipTest(); @@ -3316,9 +2961,10 @@ test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { function Foo() {} + Foo.prototype.c = 3; + Foo.a = 1; Foo.b = 2; - Foo.prototype.c = 3; var expected = { 'a': 1, 'b': 2 }; deepEqual(func({}, Foo), expected); @@ -3331,31 +2977,9 @@ var array = [{ 'b': 2 }, { 'c': 3 }]; deepEqual(_.reduce(array, func, { 'a': 1}), { 'a': 1, 'b': 2, 'c': 3 }); }); - - test('`_.' + methodName + '` should not error on nullish sources (test in IE < 9)', 1, function() { - try { - deepEqual(func({ 'a': 1 }, undefined, { 'b': 2 }, null), { 'a': 1, 'b': 2 }); - } catch(e) { - ok(false); - } - }); - - test('`_.' + methodName + '` should not error when `object` is nullish and source objects are provided', 1, function() { - var expected = _.times(2, _.constant(true)); - - var actual = _.map([null, undefined], function(value) { - try { - return _.isEqual(func(value, { 'a': 1 }), value); - } catch(e) { - return false; - } - }); - - deepEqual(actual, expected); - }); }); - _.each(['assign', 'merge'], function(methodName) { + _.forEach(['assign', 'merge'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should pass the correct `callback` arguments', 2, function() { @@ -3402,7 +3026,7 @@ QUnit.module('exit early'); - _.each(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { + _.forEach(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; if (!func) { return; @@ -3420,7 +3044,7 @@ values = []; func(object, function(value) { values.push(value); return false; }); - strictEqual(values.length, 1); + equal(values.length, 1); }); }); @@ -3434,7 +3058,7 @@ stringObject = Object(stringLiteral), expected = [stringLiteral, stringObject]; - var largeArray = _.times(largeArraySize, function(count) { + var largeArray = _.times(LARGE_ARRAY_SIZE, function(count) { return count % 2 ? stringObject : stringLiteral; }); @@ -3444,7 +3068,7 @@ deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []); }); - test('lodash.memoize should support values that resolve to the `__proto__` key', 1, function() { + test('lodash.memoize should memoize values resolved to the `__proto__` key', 1, function() { var count = 0, memoized = _.memoize(function() { return ++count; }); @@ -3460,7 +3084,7 @@ (function() { test('should return the function names of an object', 1, function() { - var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.each }; + var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.forEach }; deepEqual(_.functions(object), ['b', 'd']); }); @@ -3469,7 +3093,8 @@ this.a = _.identity; this.b = 'b' } - Foo.prototype.c = _.noop; + + Foo.prototype.c = noop; deepEqual(_.functions(new Foo), ['a', 'c']); }); @@ -3571,7 +3196,7 @@ test('should return `false` for primitives', 1, function() { var values = falsey.concat(1, 'a'), - expected = _.map(values, _.constant(false)); + expected = _.map(values, function() { return false; }); var actual = _.map(values, function(value) { return _.has(value, 'valueOf'); @@ -3647,52 +3272,41 @@ var array = [1, 2, 3, 1, 2, 3]; test('should return the index of the first matched value', 1, function() { - strictEqual(_.indexOf(array, 3), 2); + equal(_.indexOf(array, 3), 2); }); test('should return `-1` for an unmatched value', 4, function() { - strictEqual(_.indexOf(array, 4), -1); - strictEqual(_.indexOf(array, 4, true), -1); + equal(_.indexOf(array, 4), -1); + equal(_.indexOf(array, 4, true), -1); var empty = []; - strictEqual(_.indexOf(empty, undefined), -1); - strictEqual(_.indexOf(empty, undefined, true), -1); + equal(_.indexOf(empty, undefined), -1); + equal(_.indexOf(empty, undefined, true), -1); }); test('should work with a positive `fromIndex`', 1, function() { - strictEqual(_.indexOf(array, 1, 2), 3); - }); - - test('should work with `fromIndex` >= `array.length`', 12, function() { - _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { - strictEqual(_.indexOf(array, 1, fromIndex), -1); - strictEqual(_.indexOf(array, undefined, fromIndex), -1); - strictEqual(_.indexOf(array, '', fromIndex), -1); - }); + equal(_.indexOf(array, 1, 2), 3); }); - test('should treat falsey `fromIndex` values as `0`', 1, function() { - var expected = _.map(falsey, _.constant(0)); - - var actual = _.map(falsey, function(fromIndex) { - return _.indexOf(array, 1, fromIndex); + test('should work with `fromIndex` >= `array.length`', 6, function() { + _.forEach([6, 8], function(fromIndex) { + equal(_.indexOf(array, 1, fromIndex), -1); + equal(_.indexOf(array, undefined, fromIndex), -1); + equal(_.indexOf(array, '', fromIndex), -1); }); - - deepEqual(actual, expected); }); - test('should treat non-number `fromIndex` values as `0`', 1, function() { - strictEqual(_.indexOf([1, 2, 3], 1, '1'), 0); + test('should work with a negative `fromIndex`', 1, function() { + equal(_.indexOf(array, 2, -3), 4); }); - test('should work with a negative `fromIndex`', 1, function() { - strictEqual(_.indexOf(array, 2, -3), 4); + test('should work with a negative `fromIndex` <= `-array.length`', 2, function() { + strictEqual(_.indexOf(array, 1, -6), 0); + strictEqual(_.indexOf(array, 2, -8), 1); }); - test('should work with a negative `fromIndex` <= `-array.length`', 3, function() { - _.each([-6, -8, -Infinity], function(fromIndex) { - strictEqual(_.indexOf(array, 1, fromIndex), 0); - }); + test('should ignore non-number `fromIndex` values', 1, function() { + strictEqual(_.indexOf([1, 2, 3], 1, '1'), 0); }); test('should work with `isSorted`', 1, function() { @@ -3705,8 +3319,6 @@ QUnit.module('custom `_.indexOf` methods'); (function() { - function Foo() {} - function custom(array, value, fromIndex) { var index = (fromIndex || 0) - 1, length = array.length; @@ -3720,22 +3332,23 @@ return -1; } + function Foo() {} + var array = [1, new Foo, 3, new Foo], indexOf = _.indexOf; - var largeArray = _.times(largeArraySize, function() { + var largeArray = _.times(LARGE_ARRAY_SIZE, function() { return new Foo; }); - test('`_.contains` should work with a custom `_.indexOf` method', 2, function() { + test('`_.contains` should work with a custom `_.indexOf` method', 1, function() { if (!isModularize) { _.indexOf = custom; ok(_.contains(array, new Foo)); - ok(_.contains({ 'a': 1, 'b': new Foo, 'c': 3 }, new Foo)); _.indexOf = indexOf; } else { - skipTest(2); + skipTest(); } }); @@ -3790,7 +3403,7 @@ ]; test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, _.constant([])); + var expected = _.map(falsey, function() { return []; }); var actual = _.map(falsey, function(value, index) { try { @@ -3813,26 +3426,14 @@ deepEqual(_.initial([]), []); }); - test('should treat falsey `n` values, except nullish, as `0`', 1, function() { - var expected = _.map(falsey, function(value) { - return value == null ? [1, 2] : array; - }); - - var actual = _.map(falsey, function(n) { - return _.initial(array, n); - }); - - deepEqual(actual, expected); - }); - test('should return all elements when `n` < `1`', 3, function() { - _.each([0, -1, -Infinity], function(n) { + _.forEach([0, -1, -2], function(n) { deepEqual(_.initial(array, n), array); }); }); - test('should return an empty array when `n` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { + test('should return an empty array when `n` >= `array.length`', 2, function() { + _.forEach([3, 4], function(n) { deepEqual(_.initial(array, n), []); }); }); @@ -3884,32 +3485,25 @@ QUnit.module('lodash.intersection'); (function() { - var args = arguments; - test('should return the intersection of the given arrays', 1, function() { var actual = _.intersection([1, 3, 2], [5, 2, 1, 4], [2, 1]); deepEqual(actual, [1, 2]); }); - test('should return an array of unique values', 2, function() { - var array = [1, 1, 3, 2, 2]; - deepEqual(_.intersection(array, [5, 2, 2, 1, 4], [2, 1, 1]), [1, 2]); - deepEqual(_.intersection(array), [1, 3, 2]); + test('should return an array of unique values', 1, function() { + var actual = _.intersection([1, 1, 3, 2, 2], [5, 2, 2, 1, 4], [2, 1, 1]); + deepEqual(actual, [1, 2]); }); test('should work with large arrays of objects', 1, function() { var object = {}, - largeArray = _.times(largeArraySize, _.constant(object)); - - deepEqual(_.intersection([object], largeArray), [object]); - }); + expected = [object]; - test('should work with large arrays of objects', 2, function() { - var object = {}, - largeArray = _.times(largeArraySize, _.constant(object)); + var largeArray = _.times(LARGE_ARRAY_SIZE, function() { + return object; + }); - deepEqual(_.intersection([object], largeArray), [object]); - deepEqual(_.intersection(_.range(largeArraySize), null, [1]), [1]); + deepEqual(_.intersection(expected, largeArray), expected); }); test('should return a wrapped value when chaining', 2, function() { @@ -3923,13 +3517,10 @@ } }); - test('should ignore values that are not arrays or `arguments` objects', 3, function() { - var array = [0, 1, null, 3]; - deepEqual(_.intersection(array, 3, null, { '0': 1 }), array); - deepEqual(_.intersection(null, array, null, [2, 1]), [1]); - deepEqual(_.intersection(null, array, null, args), [1, 3]); + test('should ignore individual secondary values', 1, function() { + deepEqual(_.intersection([1, null, 3], 3, null), []); }); - }(1, 2, 3)); + }()); /*--------------------------------------------------------------------------*/ @@ -3967,8 +3558,8 @@ (function() { test('should invoke a methods on each element of a collection', 1, function() { - var array = ['a', 'b', 'c']; - deepEqual( _.invoke(array, 'toUpperCase'), ['A', 'B', 'C']); + var actual = _.invoke(['a', 'b', 'c'], 'toUpperCase'); + deepEqual(actual, ['A', 'B', 'C']); }); test('should work with a function `methodName` argument', 1, function() { @@ -3983,15 +3574,6 @@ var object = { 'a': 1, 'b': 2, 'c': 3 }; deepEqual(_.invoke(object, 'toFixed', 1), ['1.0', '2.0', '3.0']); }); - - test('should treat number values for `collection` as empty', 1, function() { - deepEqual(_.invoke(1), []); - }); - - test('should work with nullish elements', 1, function() { - var array = ['a', null, undefined, 'd']; - deepEqual(_.invoke(array, 'toUpperCase'), ['A', undefined, undefined, 'D']); - }); }()); /*--------------------------------------------------------------------------*/ @@ -4005,8 +3587,8 @@ strictEqual(_.isArguments(args), true); }); - test('should return `false` for non `arguments` objects', 10, function() { - var expected = _.map(falsey, _.constant(false)); + test('should return `false` for non `arguments` objects', 9, function() { + var expected = _.map(falsey, function() { return false; }); var actual = _.map(falsey, function(value, index) { return index ? _.isArguments(value) : _.isArguments(); @@ -4015,10 +3597,9 @@ strictEqual(_.isArguments([1, 2, 3]), false); strictEqual(_.isArguments(true), false); strictEqual(_.isArguments(new Date), false); - strictEqual(_.isArguments(new Error), false); strictEqual(_.isArguments(_), false); - strictEqual(_.isArguments({ '0': 1, 'callee': _.noop, 'length': 1 }), false); - strictEqual(_.isArguments(1), false); + strictEqual(_.isArguments({ '0': 1, 'callee': noop, 'length': 1 }), false); + strictEqual(_.isArguments(0), false); strictEqual(_.isArguments(/x/), false); strictEqual(_.isArguments('a'), false); @@ -4046,8 +3627,8 @@ strictEqual(_.isArray([1, 2, 3]), true); }); - test('should return `false` for non arrays', 10, function() { - var expected = _.map(falsey, _.constant(false)); + test('should return `false` for non arrays', 9, function() { + var expected = _.map(falsey, function() { return false; }); var actual = _.map(falsey, function(value, index) { return index ? _.isArray(value) : _.isArray(); @@ -4056,10 +3637,9 @@ strictEqual(_.isArray(args), false); strictEqual(_.isArray(true), false); strictEqual(_.isArray(new Date), false); - strictEqual(_.isArray(new Error), false); strictEqual(_.isArray(_), false); strictEqual(_.isArray({ '0': 1, 'length': 1 }), false); - strictEqual(_.isArray(1), false); + strictEqual(_.isArray(0), false); strictEqual(_.isArray(/x/), false); strictEqual(_.isArray('a'), false); @@ -4090,7 +3670,7 @@ strictEqual(_.isBoolean(new Boolean(false)), true); }); - test('should return `false` for non booleans', 10, function() { + test('should return `false` for non booleans', 9, function() { var expected = _.map(falsey, function(value) { return value === false; }); var actual = _.map(falsey, function(value, index) { @@ -4100,10 +3680,9 @@ strictEqual(_.isBoolean(args), false); strictEqual(_.isBoolean([1, 2, 3]), false); strictEqual(_.isBoolean(new Date), false); - strictEqual(_.isBoolean(new Error), false); strictEqual(_.isBoolean(_), false); strictEqual(_.isBoolean({ 'a': 1 }), false); - strictEqual(_.isBoolean(1), false); + strictEqual(_.isBoolean(0), false); strictEqual(_.isBoolean(/x/), false); strictEqual(_.isBoolean('a'), false); @@ -4131,8 +3710,8 @@ strictEqual(_.isDate(new Date), true); }); - test('should return `false` for non dates', 10, function() { - var expected = _.map(falsey, _.constant(false)); + test('should return `false` for non dates', 9, function() { + var expected = _.map(falsey, function() { return false; }); var actual = _.map(falsey, function(value, index) { return index ? _.isDate(value) : _.isDate(); @@ -4141,10 +3720,9 @@ strictEqual(_.isDate(args), false); strictEqual(_.isDate([1, 2, 3]), false); strictEqual(_.isDate(true), false); - strictEqual(_.isDate(new Error), false); strictEqual(_.isDate(_), false); strictEqual(_.isDate({ 'a': 1 }), false); - strictEqual(_.isDate(1), false); + strictEqual(_.isDate(0), false); strictEqual(_.isDate(/x/), false); strictEqual(_.isDate('a'), false); @@ -4166,8 +3744,6 @@ QUnit.module('lodash.isElement'); (function() { - var args = arguments; - function Element() { this.nodeType = 1; } @@ -4196,28 +3772,7 @@ } }); - test('should return `false` for non DOM elements', 11, function() { - var expected = _.map(falsey, _.constant(false)); - - var actual = _.map(falsey, function(value, index) { - return index ? _.isElement(value) : _.isElement(); - }); - - strictEqual(_.isElement(args), false); - strictEqual(_.isElement([1, 2, 3]), false); - strictEqual(_.isElement(true), false); - strictEqual(_.isElement(new Date), false); - strictEqual(_.isElement(new Error), false); - strictEqual(_.isElement(_), false); - strictEqual(_.isElement({ 'a': 1 }), false); - strictEqual(_.isElement(1), false); - strictEqual(_.isElement(/x/), false); - strictEqual(_.isElement('a'), false); - - deepEqual(actual, expected); - }); - - test('should work with DOM elements from another realm', 1, function() { + test('should work with elements from another realm', 1, function() { if (_._element) { strictEqual(_.isElement(_._element), true); } @@ -4225,7 +3780,7 @@ skipTest(); } }); - }(1, 2, 3)); + }()); /*--------------------------------------------------------------------------*/ @@ -4235,7 +3790,7 @@ var args = arguments; test('should return `true` for empty or falsey values', 3, function() { - var expected = _.map(empties, _.constant(true)); + var expected = _.map(empties, function() { return true; }); var actual = _.map(empties, function(value) { return _.isEmpty(value); @@ -4252,51 +3807,36 @@ strictEqual(_.isEmpty('a'), false); }); - test('should work with an object that has a `length` property', 1, function() { - strictEqual(_.isEmpty({ 'length': 0 }), false); - }); - - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - strictEqual(_.isEmpty(args), false); - }); - - test('should work with jQuery/MooTools DOM query collections', 1, function() { - function Foo(elements) { push.apply(this, elements); } - Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; - - strictEqual(_.isEmpty(new Foo([])), true); + test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { + equal(_.isEmpty(shadowedObject), false); }); - test('should not treat objects with negative lengths as array-like', 1, function() { + test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { function Foo() {} - Foo.prototype.length = -1; + Foo.prototype.a = 1; + strictEqual(_.isEmpty(Foo), true); - strictEqual(_.isEmpty(new Foo), true); + Foo.prototype = { 'a': 1 }; + strictEqual(_.isEmpty(Foo), true); }); - test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() { - function Foo() {} - Foo.prototype.length = maxSafeInteger + 1; - - strictEqual(_.isEmpty(new Foo), true); + test('should work with an object that has a `length` property', 1, function() { + strictEqual(_.isEmpty({ 'length': 0 }), false); }); - test('should not treat objects with non-number lengths as array-like', 1, function() { - strictEqual(_.isEmpty({ 'length': '0' }), false); - }); + test('should work with jQuery/MooTools DOM query collections', 1, function() { + function Foo(elements) { push.apply(this, elements); } + Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { - strictEqual(_.isEmpty(shadowedObject), false); + strictEqual(_.isEmpty(new Foo([])), true); }); - test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { - function Foo() {} - Foo.prototype.a = 1; - - strictEqual(_.isEmpty(Foo), true); - - Foo.prototype = { 'a': 1 }; - strictEqual(_.isEmpty(Foo), true); + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + if (!isPhantomPage) { + strictEqual(_.isEmpty(args), false); + } else { + skipTest(); + } }); test('should return an unwrapped value when intuitively chaining', 1, function() { @@ -4350,14 +3890,14 @@ var primitive, object = { 'toString': function() { return primitive; } }, values = [true, null, 1, 'a', undefined], - expected = _.map(values, _.constant(false)); + expected = _.map(values, function() { return false; }); var actual = _.map(values, function(value) { primitive = value; return _.isEqual(object, value); }); - deepEqual(actual, expected); + ok(actual, expected); }); test('should perform comparisons between arrays', 6, function() { @@ -4471,7 +4011,7 @@ 'f': ['a', new String('b'), 'c'], 'g': new Boolean(false), 'h': new Date(2012, 4, 23), - 'i': _.noop, + 'i': noop, 'j': 'a' } }; @@ -4485,7 +4025,7 @@ 'f': ['a', 'b', 'c'], 'g': false, 'h': new Date(2012, 4, 23), - 'i': _.noop, + 'i': noop, 'j': 'a' } }; @@ -4494,7 +4034,9 @@ }); test('should perform comparisons between object instances', 4, function() { - function Foo() { this.value = 1; } + function Foo() { + this.value = 1; + } Foo.prototype.value = 1; function Bar() { @@ -4540,7 +4082,7 @@ strictEqual(_.isEqual(args1, args2), true); - if (!isPhantom) { + if (!isPhantomPage) { strictEqual(_.isEqual(args1, args3), false); } else { @@ -4548,24 +4090,7 @@ } }); - test('should treat `arguments` objects like `Object` objects', 2, function() { - var args = (function() { return arguments; }(1, 2, 3)), - object = { '0': 1, '1': 2, '2': 3, 'length': 3 }; - - function Foo() {} - Foo.prototype = object; - - strictEqual(_.isEqual(args, object), true); - - if (!isPhantom) { - strictEqual(_.isEqual(args, new Foo), false); - } - else { - skipTest(); - } - }); - - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { strictEqual(_.isEqual(shadowedObject, {}), false); }); @@ -4711,11 +4236,11 @@ var actual = _.isEqual('a', 'a', function() { return 'a'; }); strictEqual(actual, true); - var expected = _.map(falsey, _.constant(false)); + var expected = _.map(falsey, function() { return false; }); actual = []; - _.each(falsey, function(value) { - actual.push(_.isEqual('a', 'b', _.constant(value))); + _.forEach(falsey, function(value) { + actual.push(_.isEqual('a', 'b', function() { return value; })); }); deepEqual(actual, expected); @@ -4738,13 +4263,13 @@ function Foo() { this.a = 1; } Foo.prototype.constructor = null; - var otherObject = { 'a': 1 }; - strictEqual(_.isEqual(new Foo, otherObject), false); + var other = { 'a': 1 }; + strictEqual(_.isEqual(new Foo, other), false); if (create) { - var object = create(null); + var object = Object.create(null); object.a = 1; - strictEqual(_.isEqual(object, otherObject), true); + strictEqual(_.isEqual(object, other), true); } else { skipTest(); @@ -4819,113 +4344,42 @@ skipTest(); } }); - - test('should not error on DOM elements', 1, function() { - if (document) { - var element1 = document.createElement('div'), - element2 = element1.cloneNode(true); - - try { - strictEqual(_.isEqual(element1, element2), false); - } catch(e) { - ok(false); - } - } - else { - skipTest(); - } - }); }()); /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.isError'); + QUnit.module('lodash.isFinite'); (function() { - var args = arguments; + test('should return `true` for finite values', 5, function() { + strictEqual(_.isFinite(0), true); + strictEqual(_.isFinite(1), true); + strictEqual(_.isFinite(3.14), true); + strictEqual(_.isFinite(-1), true); + strictEqual(_.isFinite(new Number(0)), true); + }); - test('should return `true` for error objects', 1, function() { - var errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError], - expected = _.map(errors, _.constant(true)); + test('should return `false` for non-finite values', 3, function() { + strictEqual(_.isFinite(NaN), false); + strictEqual(_.isFinite(Infinity), false); + strictEqual(_.isFinite(-Infinity), false); + }); - var actual = _.map(errors, function(error) { - return _.isError(error) === true; - }); + test('should return `false` for non-numeric values', 8, function() { + strictEqual(_.isFinite(null), false); + strictEqual(_.isFinite(undefined), false); + strictEqual(_.isFinite([]), false); + strictEqual(_.isFinite(true), false); + strictEqual(_.isFinite(new Date), false); + strictEqual(_.isFinite(''), false); + strictEqual(_.isFinite(' '), false); + strictEqual(_.isFinite('2px'), false); + }); - deepEqual(actual, expected); - }); - - test('should return `false` for non-error objects', 10, function() { - var expected = _.map(falsey, _.constant(false)); - - var actual = _.map(falsey, function(value, index) { - return index ? _.isError(value) : _.isError(); - }); - - strictEqual(_.isError(args), false); - strictEqual(_.isError([1, 2, 3]), false); - strictEqual(_.isError(true), false); - strictEqual(_.isError(new Date), false); - strictEqual(_.isError(_), false); - strictEqual(_.isError({ 'a': 1 }), false); - strictEqual(_.isError(1), false); - strictEqual(_.isError(/x/), false); - strictEqual(_.isError('a'), false); - - deepEqual(actual, expected); - }); - - test('should work with an error object from another realm', 1, function() { - if (_._object) { - var expected = _.map(_._errors, _.constant(true)); - - var actual = _.map(_._errors, function(error) { - return _.isError(error) === true; - }); - - deepEqual(actual, expected); - } - else { - skipTest(); - } - }); - }(1, 2, 3)); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.isFinite'); - - (function() { - test('should return `true` for finite values', 5, function() { - strictEqual(_.isFinite(0), true); - strictEqual(_.isFinite(1), true); - strictEqual(_.isFinite(3.14), true); - strictEqual(_.isFinite(-1), true); - strictEqual(_.isFinite(new Number(0)), true); - }); - - test('should return `false` for non-finite values', 3, function() { - strictEqual(_.isFinite(NaN), false); - strictEqual(_.isFinite(Infinity), false); - strictEqual(_.isFinite(-Infinity), false); - }); - - test('should return `false` for non-numeric values', 9, function() { - strictEqual(_.isFinite(null), false); - strictEqual(_.isFinite(undefined), false); - strictEqual(_.isFinite([]), false); - strictEqual(_.isFinite(true), false); - strictEqual(_.isFinite(new Date), false); - strictEqual(_.isFinite(new Error), false); - strictEqual(_.isFinite(''), false); - strictEqual(_.isFinite(' '), false); - strictEqual(_.isFinite('2px'), false); - }); - - test('should return `true` for numeric string values', 3, function() { - strictEqual(_.isFinite('2'), true); - strictEqual(_.isFinite('0'), true); - strictEqual(_.isFinite('08'), true); + test('should return `true` for numeric string values', 3, function() { + strictEqual(_.isFinite('2'), true); + strictEqual(_.isFinite('0'), true); + strictEqual(_.isFinite('08'), true); }); test('should work with numbers from another realm', 1, function() { @@ -4949,8 +4403,8 @@ strictEqual(_.isFunction(_), true); }); - test('should return `false` for non functions', 10, function() { - var expected = _.map(falsey, _.constant(false)); + test('should return `false` for non functions', 9, function() { + var expected = _.map(falsey, function() { return false; }); var actual = _.map(falsey, function(value, index) { return index ? _.isFunction(value) : _.isFunction(); @@ -4960,9 +4414,8 @@ strictEqual(_.isFunction([1, 2, 3]), false); strictEqual(_.isFunction(true), false); strictEqual(_.isFunction(new Date), false); - strictEqual(_.isFunction(new Error), false); strictEqual(_.isFunction({ 'a': 1 }), false); - strictEqual(_.isFunction(1), false); + strictEqual(_.isFunction(0), false); strictEqual(_.isFunction(/x/), false); strictEqual(_.isFunction('a'), false); @@ -4991,7 +4444,7 @@ strictEqual(_.isNaN(new Number(NaN)), true); }); - test('should return `false` for non NaNs', 11, function() { + test('should return `false` for non NaNs', 10, function() { var expected = _.map(falsey, function(value) { return value !== value; }); var actual = _.map(falsey, function(value, index) { @@ -5002,10 +4455,9 @@ strictEqual(_.isNaN([1, 2, 3]), false); strictEqual(_.isNaN(true), false); strictEqual(_.isNaN(new Date), false); - strictEqual(_.isNaN(new Error), false); strictEqual(_.isNaN(_), false); strictEqual(_.isNaN({ 'a': 1 }), false); - strictEqual(_.isNaN(1), false); + strictEqual(_.isNaN(0), false); strictEqual(_.isNaN(/x/), false); strictEqual(_.isNaN('a'), false); @@ -5033,7 +4485,7 @@ strictEqual(_.isNull(null), true); }); - test('should return `false` for non nulls', 11, function() { + test('should return `false` for non nulls', 10, function() { var expected = _.map(falsey, function(value) { return value === null; }); var actual = _.map(falsey, function(value, index) { @@ -5044,10 +4496,9 @@ strictEqual(_.isNull([1, 2, 3]), false); strictEqual(_.isNull(true), false); strictEqual(_.isNull(new Date), false); - strictEqual(_.isNull(new Error), false); strictEqual(_.isNull(_), false); strictEqual(_.isNull({ 'a': 1 }), false); - strictEqual(_.isNull(1), false); + strictEqual(_.isNull(0), false); strictEqual(_.isNull(/x/), false); strictEqual(_.isNull('a'), false); @@ -5076,7 +4527,7 @@ strictEqual(_.isNumber(new Number(0)), true); }); - test('should return `false` for non numbers', 10, function() { + test('should return `false` for non numbers', 9, function() { var expected = _.map(falsey, function(value) { return typeof value == 'number'; }); var actual = _.map(falsey, function(value, index) { @@ -5087,7 +4538,6 @@ strictEqual(_.isNumber([1, 2, 3]), false); strictEqual(_.isNumber(true), false); strictEqual(_.isNumber(new Date), false); - strictEqual(_.isNumber(new Error), false); strictEqual(_.isNumber(_), false); strictEqual(_.isNumber({ 'a': 1 }), false); strictEqual(_.isNumber(/x/), false); @@ -5117,12 +4567,11 @@ (function() { var args = arguments; - test('should return `true` for objects', 11, function() { + test('should return `true` for objects', 10, function() { strictEqual(_.isObject(args), true); strictEqual(_.isObject([1, 2, 3]), true); strictEqual(_.isObject(new Boolean(false)), true); strictEqual(_.isObject(new Date), true); - strictEqual(_.isObject(new Error), true); strictEqual(_.isObject(_), true); strictEqual(_.isObject({ 'a': 1 }), true); strictEqual(_.isObject(new Number(0)), true); @@ -5138,7 +4587,7 @@ test('should return `false` for non objects', 1, function() { var values = falsey.concat('a', true), - expected = _.map(values, _.constant(false)); + expected = _.map(values, function() { return false; }); var actual = _.map(values, function(value, index) { return index ? _.isObject(value) : _.isObject(); @@ -5179,7 +4628,7 @@ // 2: Initial check with object, this is the other half of the trigger _.isObject(obj); - strictEqual(_.isObject(str), false); + equal(_.isObject(str), false); }); }(1, 2, 3)); @@ -5202,7 +4651,7 @@ strictEqual(_.isPlainObject(new Foo(1)), false); }); - test('should return `true` for objects with a `[[Prototype]]` of `null`', 1, function() { + test('should return `true` for objects a [[Prototype]] of `null`', 1, function() { if (create) { strictEqual(_.isPlainObject(create(null)), true); } else { @@ -5232,14 +4681,14 @@ } }); - test('should return `false` for Object objects without a `[[Class]]` of "Object"', 3, function() { + test('should return `false` for Object objects without a [[Class]] of "Object"', 3, function() { strictEqual(_.isPlainObject(arguments), false); strictEqual(_.isPlainObject(Error), false); strictEqual(_.isPlainObject(Math), false); }); test('should return `false` for non objects', 3, function() { - var expected = _.map(falsey, _.constant(false)); + var expected = _.map(falsey, function() { return false; }); var actual = _.map(falsey, function(value, index) { return index ? _.isPlainObject(value) : _.isPlainObject(); @@ -5272,8 +4721,8 @@ strictEqual(_.isRegExp(RegExp('x')), true); }); - test('should return `false` for non regexes', 10, function() { - var expected = _.map(falsey, _.constant(false)); + test('should return `false` for non regexes', 9, function() { + var expected = _.map(falsey, function(value) { return false; }); var actual = _.map(falsey, function(value, index) { return index ? _.isRegExp(value) : _.isRegExp(); @@ -5283,10 +4732,9 @@ strictEqual(_.isRegExp([1, 2, 3]), false); strictEqual(_.isRegExp(true), false); strictEqual(_.isRegExp(new Date), false); - strictEqual(_.isRegExp(new Error), false); strictEqual(_.isRegExp(_), false); strictEqual(_.isRegExp({ 'a': 1 }), false); - strictEqual(_.isRegExp(1), false); + strictEqual(_.isRegExp(0), false); strictEqual(_.isRegExp('a'), false); deepEqual(actual, expected); @@ -5314,7 +4762,7 @@ strictEqual(_.isString(new String('a')), true); }); - test('should return `false` for non strings', 10, function() { + test('should return `false` for non strings', 9, function() { var expected = _.map(falsey, function(value) { return value === ''; }); var actual = _.map(falsey, function(value, index) { @@ -5325,10 +4773,9 @@ strictEqual(_.isString([1, 2, 3]), false); strictEqual(_.isString(true), false); strictEqual(_.isString(new Date), false); - strictEqual(_.isString(new Error), false); strictEqual(_.isString(_), false); strictEqual(_.isString({ '0': 1, 'length': 1 }), false); - strictEqual(_.isString(1), false); + strictEqual(_.isString(0), false); strictEqual(_.isString(/x/), false); deepEqual(actual, expected); @@ -5356,21 +4803,20 @@ strictEqual(_.isUndefined(undefined), true); }); - test('should return `false` for non `undefined` values', 11, function() { + test('should return `false` for non `undefined` values', 10, function() { var expected = _.map(falsey, function(value) { return value === undefined; }); var actual = _.map(falsey, function(value, index) { - return index ? _.isUndefined(value) : _.isUndefined(); + return _.isUndefined(value); }); strictEqual(_.isUndefined(args), false); strictEqual(_.isUndefined([1, 2, 3]), false); strictEqual(_.isUndefined(true), false); strictEqual(_.isUndefined(new Date), false); - strictEqual(_.isUndefined(new Error), false); strictEqual(_.isUndefined(_), false); strictEqual(_.isUndefined({ 'a': 1 }), false); - strictEqual(_.isUndefined(1), false); + strictEqual(_.isUndefined(0), false); strictEqual(_.isUndefined(/x/), false); strictEqual(_.isUndefined('a'), false); @@ -5392,13 +4838,13 @@ QUnit.module('isType checks'); (function() { - test('should return `false` for subclassed values', 8, function() { + test('should return `false` for subclassed values', 7, function() { var funcs = [ - 'isArray', 'isBoolean', 'isDate', 'isError', - 'isFunction', 'isNumber', 'isRegExp', 'isString' + 'isArray', 'isBoolean', 'isDate', 'isFunction', + 'isNumber', 'isRegExp', 'isString' ]; - _.each(funcs, function(methodName) { + _.forEach(funcs, function(methodName) { function Foo() {} Foo.prototype = root[methodName.slice(2)].prototype; @@ -5422,7 +4868,7 @@ 'isObject', 'isNull', 'isNumber', 'isRegExp', 'isString', 'isUndefined' ]; - _.each(funcs, function(methodName) { + _.forEach(funcs, function(methodName) { var pass = true; try { _[methodName](xml); @@ -5440,146 +4886,52 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('keys methods'); - - _.each(['keys', 'keysIn'], function(methodName) { - var args = arguments, - func = _[methodName], - isKeys = methodName == 'keys'; + QUnit.module('lodash.keys'); - test('`_.' + methodName + '` should return the keys of an object', 1, function() { - var object = { 'a': 1, 'b': 1 }, - actual = func(object); + (function() { + var args = arguments; - deepEqual(actual.sort(), ['a', 'b']); + test('should return the keys of an object', 1, function() { + var object = { 'a': 1, 'b': 1 }; + deepEqual(_.keys(object), ['a', 'b']); }); - test('`_.' + methodName + '` should treat sparse arrays as dense', 1, function() { + test('should work with sparse arrays', 1, function() { var array = [1]; array[2] = 3; - - var actual = func(array); - deepEqual(actual.sort(), ['0', '1', '2']); - }); - - test('`_.' + methodName + '` should custom properties on arrays', 1, function() { - var array = [1]; - array.a = 1; - - var actual = func(array); - deepEqual(actual.sort(), ['0', 'a']); - }); - - test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of arrays', 1, function() { - Array.prototype.a = 1; - var expected = isKeys ? ['0'] : ['0', 'a'], - actual = func([1]); - - deepEqual(actual.sort(), expected); - delete Array.prototype.a; + deepEqual(_.keys(array), ['0', '2']); }); - test('`_.' + methodName + '` should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantom) { - var actual = func(args); - deepEqual(actual.sort(), ['0', '1', '2']); - } else { - skipTest(); - } - }); - - test('`_.' + methodName + '` should custom properties on `arguments` objects', 1, function() { - if (!isPhantom) { - args.a = 1; - var actual = func(args); - - deepEqual(actual.sort(), ['0', '1', '2', 'a']); - delete args.a; - } else { - skipTest(); - } - }); - - test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of `arguments` objects', 1, function() { - if (!isPhantom) { - Object.prototype.a = 1; - var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a'], - actual = func(args); - - deepEqual(actual.sort(), expected); - delete Object.prototype.a; + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + if (!isPhantomPage) { + deepEqual(_.keys(args), ['0', '1', '2']); } else { skipTest(); } }); - test('`_.' + methodName + '` should work with string objects (test in IE < 9)', 1, function() { - var actual = func(Object('abc')); - deepEqual(actual.sort(), ['0', '1', '2']); - }); - - test('`_.' + methodName + '` should custom properties on string objects', 1, function() { - var object = Object('a'); - object.a = 1; - - var actual = func(object); - deepEqual(actual.sort(), ['0', 'a']); - }); - - test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of string objects', 1, function() { - String.prototype.a = 1; - var expected = isKeys ? ['0'] : ['0', 'a'], - actual = func(Object('a')); - - deepEqual(actual.sort(), expected); - delete String.prototype.a; - }); + test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 2, function() { + function Foo() {} + Foo.prototype.a = 1; - test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { - var actual = func(shadowedObject); - deepEqual(actual.sort(), shadowedProps); + deepEqual(_.keys(Foo.prototype), ['a']); + deepEqual(_.keys(shadowedObject).sort(), shadowedProps); }); - test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { + test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { function Foo() {} - Foo.a = 1; - Foo.b = 2; Foo.prototype.c = 3; - var expected = ['a', 'b'], - actual = func(Foo); + Foo.a = 1; + Foo.b = 2; - deepEqual(actual.sort(), expected); + var expected = ['a', 'b']; + deepEqual(_.keys(Foo), expected); Foo.prototype = { 'c': 3 }; - actual = func(Foo); - deepEqual(actual.sort(), expected); + deepEqual(_.keys(Foo), expected); }); - - test('`_.' + methodName + '` skips the `constructor` property on prototype objects', 2, function() { - function Foo() {} - Foo.prototype.a = 1; - - var expected = ['a']; - deepEqual(func(Foo.prototype), ['a']); - - Foo.prototype = { 'constructor': Foo, 'a': 1 }; - deepEqual(func(Foo.prototype), ['a']); - }); - - test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties', 1, function() { - function Foo() { - this.a = 1; - this.b = 2; - } - Foo.prototype.c = 3; - - var expected = isKeys ? ['a', 'b'] : ['a', 'b', 'c'], - actual = func(new Foo); - - deepEqual(actual.sort(), expected); - }); - }); + }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -5595,33 +4947,21 @@ ]; test('should return the last element', 1, function() { - strictEqual(_.last(array), 3); + equal(_.last(array), 3); }); test('should return the last two elements', 1, function() { deepEqual(_.last(array, 2), [2, 3]); }); - test('should treat falsey `n` values, except nullish, as `0`', 1, function() { - var expected = _.map(falsey, function(value) { - return value == null ? 3 : []; - }); - - var actual = _.map(falsey, function(n) { - return _.last(array, n); - }); - - deepEqual(actual, expected); - }); - test('should return an empty array when `n` < `1`', 3, function() { - _.each([0, -1, -Infinity], function(n) { + _.forEach([0, -1, -2], function(n) { deepEqual(_.last(array, n), []); }); }); - test('should return all elements when `n` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { + test('should return all elements when `n` >= `array.length`', 2, function() { + _.forEach([3, 4], function(n) { deepEqual(_.last(array, n), array); }); }); @@ -5689,7 +5029,7 @@ test('should not chain when arguments are not provided', 1, function() { if (!isNpm) { var actual = _(array).last(); - strictEqual(actual, 3); + equal(actual, 3); } else { skipTest(); @@ -5713,50 +5053,37 @@ var array = [1, 2, 3, 1, 2, 3]; test('should return the index of the last matched value', 1, function() { - strictEqual(_.lastIndexOf(array, 3), 5); + equal(_.lastIndexOf(array, 3), 5); }); test('should return `-1` for an unmatched value', 1, function() { - strictEqual(_.lastIndexOf(array, 4), -1); + equal(_.lastIndexOf(array, 4), -1); }); test('should work with a positive `fromIndex`', 1, function() { strictEqual(_.lastIndexOf(array, 1, 2), 0); }); - test('should work with `fromIndex` >= `array.length`', 12, function() { - _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { - strictEqual(_.lastIndexOf(array, undefined, fromIndex), -1); - strictEqual(_.lastIndexOf(array, 1, fromIndex), 3); - strictEqual(_.lastIndexOf(array, '', fromIndex), -1); + test('should work with `fromIndex` >= `array.length`', 6, function() { + _.forEach([6, 8], function(fromIndex) { + equal(_.lastIndexOf(array, undefined, fromIndex), -1); + equal(_.lastIndexOf(array, 1, fromIndex), 3); + equal(_.lastIndexOf(array, '', fromIndex), -1); }); }); - test('should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`', 1, function() { - var expected = _.map(falsey, function(value) { - return typeof value == 'number' ? -1 : 5; - }); - - var actual = _.map(falsey, function(fromIndex) { - return _.lastIndexOf(array, 3, fromIndex); - }); - - deepEqual(actual, expected); - }); - - test('should treat non-number `fromIndex` values as `array.length`', 2, function() { - strictEqual(_.lastIndexOf(array, 3, '1'), 5); - strictEqual(_.lastIndexOf(array, 3, true), 5); - }); - test('should work with a negative `fromIndex`', 1, function() { strictEqual(_.lastIndexOf(array, 2, -3), 1); }); - test('should work with a negative `fromIndex` <= `-array.length`', 3, function() { - _.each([-6, -8, -Infinity], function(fromIndex) { - strictEqual(_.lastIndexOf(array, 1, fromIndex), 0); - }); + test('should work with a negative `fromIndex` <= `-array.length`', 2, function() { + strictEqual(_.lastIndexOf(array, 1, -6), 0); + equal(_.lastIndexOf(array, 2, -8), -1); + }); + + test('should ignore non-number `fromIndex` values', 2, function() { + equal(_.lastIndexOf([1, 2, 3], 3, '1'), 2); + equal(_.lastIndexOf([1, 2, 3], 3, true), 2); }); }()); @@ -5765,11 +5092,11 @@ QUnit.module('indexOf methods'); (function() { - _.each(['indexOf', 'lastIndexOf'], function(methodName) { + _.forEach(['indexOf', 'lastIndexOf'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, _.constant(-1)); + var expected = _.map(falsey, function() { return -1; }); var actual = _.map(falsey, function(value, index) { try { @@ -5836,7 +5163,7 @@ test('should return a wrapped value when chaining', 1, function() { if (!isNpm) { - ok(_(array).map(_.noop) instanceof _); + ok(_(array).map(noop) instanceof _); } else { skipTest(); @@ -5856,8 +5183,8 @@ } }); - test('should accept a falsey `collection` argument', 1, function() { - var expected = _.map(falsey, _.constant([])); + test('should accept a falsey `array` argument', 1, function() { + var expected = _.map(falsey, function() { return []; }); var actual = _.map(falsey, function(value, index) { try { @@ -5868,10 +5195,6 @@ deepEqual(actual, expected); }); - test('should treat number values for `collection` as empty', 1, function() { - deepEqual(_.map(1), []); - }); - test('should be aliased', 1, function() { strictEqual(_.collect, _.map); }); @@ -5921,7 +5244,7 @@ test('should return a wrapped value when chaining', 1, function() { if (!isNpm) { - ok(_(object).mapValues(_.noop) instanceof _); + ok(_(object).mapValues(noop) instanceof _); } else { skipTest(); @@ -5929,7 +5252,7 @@ }); test('should accept a falsey `object` argument', 1, function() { - var expected = _.map(falsey, _.constant({})); + var expected = _.map(falsey, function() { return {}; }); var actual = _.map(falsey, function(value, index) { try { @@ -5946,60 +5269,21 @@ QUnit.module('lodash.matches'); (function() { - var object = { 'a': 1, 'b': 2, 'c': 3 }, - sources = [{ 'a': 1 }, { 'a': 1, 'c': 3 }]; - - test('should create a function that performs a deep comparison between a given object and the `source` object', 6, function() { - _.each(sources, function(source, index) { - var matches = _.matches(source); - strictEqual(matches.length, 1); - strictEqual(matches(object), true); - - matches = _.matches(index ? { 'c': 3, 'd': 4 } : { 'b': 1 }); - strictEqual(matches(object), false); - }); - }); + var object = { 'a': 1, 'b': 2 }; - test('should return `true` when comparing an empty `source`', 1, function() { - var expected = _.map(empties, _.constant(true)); + test('should create a function that performs a deep comparison between a given object and the `source` object', 3, function() { + var matches = _.matches({ 'a': 1 }); - var actual = _.map(empties, function(value) { - var matches = _.matches(value); - return matches(object) === true; - }); + equal(matches.length, 1); + strictEqual(matches(object), true); - deepEqual(actual, expected); + matches = _.matches({ 'b': 1 }); + strictEqual(matches(object), false); }); - test('should not error error for falsey `object` values', 2, function() { - var expected = _.map(falsey, _.constant(true)); - - _.each(sources, function(source) { - var matches = _.matches(source); - - var actual = _.map(falsey, function(value, index) { - try { - var result = index ? matches(value) : matches(); - return result === false; - } catch(e) { } - }); - - deepEqual(actual, expected); - }); - }); - - test('should return `true` when comparing an empty `source` to a falsey `object`', 1, function() { - var expected = _.map(falsey, _.constant(true)), - matches = _.matches({}); - - var actual = _.map(falsey, function(value, index) { - try { - var result = index ? matches(value) : matches(); - return result === true; - } catch(e) { } - }); - - deepEqual(actual, expected); + test('should return `false` when comparing an empty `source`', 1, function() { + var matches = _.matches({}); + strictEqual(matches(object), false); }); }()); @@ -6009,7 +5293,7 @@ (function() { test('should return the largest value from a collection', 1, function() { - strictEqual(3, _.max([1, 2, 3])); + equal(3, _.max([1, 2, 3])); }); test('should return `-Infinity` for empty collections', 1, function() { @@ -6048,16 +5332,16 @@ return a + b + c; }); - strictEqual(memoized(1, 2, 3), 6); - strictEqual(memoized(1, 3, 5), 6); + equal(memoized(1, 2, 3), 6); + equal(memoized(1, 3, 5), 6); }); test('should support a `resolver` argument', 2, function() { var fn = function(a, b, c) { return a + b + c; }, memoized = _.memoize(fn, fn); - strictEqual(memoized(1, 2, 3), 6); - strictEqual(memoized(1, 3, 5), 9); + equal(memoized(1, 2, 3), 6); + equal(memoized(1, 3, 5), 9); }); test('should not set a `this` binding', 2, function() { @@ -6066,31 +5350,15 @@ }); var object = { 'b': 2, 'c': 3, 'memoized': memoized }; - strictEqual(object.memoized(1), 6); - strictEqual(object.memoized(2), 7); - }); - - test('should throw a TypeError if `resolve` is truthy and not a function', function() { - raises(function() { _.memoize(_.noop, {}); }, TypeError); - }); - - test('should not throw a TypeError if `resolve` is falsey', function() { - var expected = _.map(falsey, _.constant(true)); - - var actual = _.map(falsey, function(value, index) { - try { - return _.isFunction(index ? _.memoize(_.noop, value) : _.memoize(_.noop)); - } catch(e) { } - }); - - deepEqual(actual, expected); + equal(object.memoized(1), 6); + equal(object.memoized(2), 7); }); test('should check cache for own properties', 1, function() { var actual = [], memoized = _.memoize(_.identity); - _.each(shadowedProps, function(value) { + _.forEach(shadowedProps, function(value) { actual.push(memoized(value)); }); @@ -6098,14 +5366,14 @@ }); test('should expose a `cache` object on the `memoized` function', 4, function() { - _.each(['_a', 'a'], function(key, index) { + _.forEach(['_a', 'a'], function(key, index) { var memoized = _.memoize(_.identity, index && _.identity); memoized('a'); - strictEqual(memoized.cache[key], 'a'); + equal(memoized.cache[key], 'a'); memoized.cache[key] = 'b'; - strictEqual(memoized('a'), 'b'); + equal(memoized('a'), 'b'); }); }); }()); @@ -6177,7 +5445,7 @@ }; var actual = _.merge(object, source); - strictEqual(_.isArguments(actual.args), false); + equal(_.isArguments(actual.args), false); }); test('should work with four arguments', 1, function() { @@ -6226,7 +5494,7 @@ (function() { test('should return the smallest value from a collection', 1, function() { - strictEqual(1, _.min([1, 2, 3])); + equal(1, _.min([1, 2, 3])); }); test('should return `Infinity` for empty collections', 1, function() { @@ -6259,16 +5527,15 @@ QUnit.module('lodash.max and lodash.min'); - _.each(['max', 'min'], function(methodName) { + _.forEach(['max', 'min'], function(methodName) { var array = [1, 2, 3], - func = _[methodName], - isMax = methodName == 'max'; + func = _[methodName]; test('`_.' + methodName + '` should work with Date objects', 1, function() { var now = new Date, past = new Date(0); - strictEqual(func([now, past]), isMax ? now : past); + equal(func([now, past]), methodName == 'max' ? now : past); }); test('`_.' + methodName + '` should work with a callback argument', 1, function() { @@ -6276,7 +5543,7 @@ return -num; }); - strictEqual(actual, isMax ? 1 : 3); + equal(actual, methodName == 'max' ? 1 : 3); }); test('`_.' + methodName + '` should pass the correct `callback` arguments when iterating an array', 1, function() { @@ -6310,39 +5577,29 @@ return -this[index]; }, array); - strictEqual(actual, isMax ? 1 : 3); + equal(actual, methodName == 'max' ? 1 : 3); }); test('`_.' + methodName + '` should work when used as a callback for `_.map`', 1, function() { var array = [[2, 3, 1], [5, 6, 4], [8, 9, 7]], actual = _.map(array, func); - deepEqual(actual, isMax ? [3, 6, 9] : [1, 4, 7]); + deepEqual(actual, methodName == 'max' ? [3, 6, 9] : [1, 4, 7]); }); test('`_.' + methodName + '` should iterate an object', 1, function() { var actual = func({ 'a': 1, 'b': 2, 'c': 3 }); - strictEqual(actual, isMax ? 3 : 1); + equal(actual, methodName == 'max' ? 3 : 1); }); test('`_.' + methodName + '` should iterate a string', 2, function() { - _.each(['abc', Object('abc')], function(value) { + _.forEach(['abc', Object('abc')], function(value) { var actual = func(value); - strictEqual(actual, isMax ? 'c' : 'a'); + equal(actual, methodName == 'max' ? 'c' : 'a'); }); }); - test('`_.' + methodName + '` should work when `callback` returns +/-Infinity', 1, function() { - var object = { 'a': (isMax ? -Infinity : Infinity) }; - - var actual = func([object, { 'a': object.a }], function(object) { - return object.a; - }); - - strictEqual(actual, object); - }); - - test('`_.' + methodName + '` should work when chaining on an array with only one value', 1, function() { + test('`_.' + methodName + '` should resolve the correct value when provided an array containing only one value', 1, function() { if (!isNpm) { var actual = _([40])[methodName]().value(); strictEqual(actual, 40); @@ -6354,7 +5611,7 @@ test('`_.' + methodName + '` should work with extremely large arrays', 1, function() { var array = _.range(0, 5e5); - strictEqual(func(array), isMax ? 499999 : 0); + equal(func(array), methodName == 'max' ? 499999 : 0); }); }); @@ -6371,36 +5628,15 @@ } var value = ['a'], - source = { 'a': function(array) { return array[0]; }, 'b': 'B' }; - - test('should use `this` as the default `object` value', 3, function() { - var object = _.create(_); - object.mixin(source); - - strictEqual(object.a(value), 'a'); - - ok(!('a' in _)); - ok(!('a' in _.prototype)); - - delete wrapper.a; - delete wrapper.prototype.a; - delete wrapper.b; - delete wrapper.prototype.b; - }); + source = { 'a': function(array) { return array[0]; } }; test('should accept an `object` argument', 1, function() { - var object = {}; - _.mixin(object, source); - strictEqual(object.a(value), 'a'); + var lodash = {}; + _.mixin(lodash, source); + strictEqual(lodash.a(value), 'a'); }); - test('should return `object`', 2, function() { - var object = {}; - strictEqual(_.mixin(object, source), object); - strictEqual(_.mixin(), _); - }); - - test('should work with a function for `object`', 2, function() { + test('should accept a function `object` argument', 2, function() { _.mixin(wrapper, source); var wrapped = wrapper(value), @@ -6411,24 +5647,30 @@ delete wrapper.a; delete wrapper.prototype.a; - delete wrapper.b; - delete wrapper.prototype.b; }); test('should mixin `source` methods into lodash', 4, function() { - _.mixin(source); + if (!isNpm) { + _.mixin({ + 'a': 'a', + 'A': function(string) { return string.toUpperCase(); } + }); - strictEqual(_.a(value), 'a'); - strictEqual(_(value).a().__wrapped__, 'a'); + equal('a' in _, false); + equal('a' in _.prototype, false); - delete _.a; - delete _.prototype.a; + delete _.a; + delete _.prototype.a; - ok(!('b' in _)); - ok(!('b' in _.prototype)); + equal(_.A('a'), 'A'); + equal(_('a').A().value(), 'A'); - delete _.b; - delete _.prototype.b; + delete _.A; + delete _.prototype.A; + } + else { + skipTest(4); + } }); test('should accept an `options` argument', 16, function() { @@ -6436,8 +5678,8 @@ return (func === _ ? 'lodash' : 'provided') + ' function should ' + (chain ? '' : 'not ') + 'chain'; } - _.each([_, wrapper], function(func) { - _.each([false, true, { 'chain': false }, { 'chain': true }], function(options) { + _.forEach([_, wrapper], function(func) { + _.forEach([false, true, { 'chain': false }, { 'chain': true }], function(options) { if (func === _) { _.mixin(source, options); } else { @@ -6446,17 +5688,15 @@ var wrapped = func(value), actual = wrapped.a(); - if (options === true || (options && options.chain)) { + if (options && (options === true || options.chain)) { strictEqual(actual.__wrapped__, 'a', message(func, true)); ok(actual instanceof func, message(func, true)); } else { strictEqual(actual, 'a', message(func, false)); - ok(!(actual instanceof func), message(func, false)); + equal(actual instanceof func, false, message(func, false)); } delete func.a; delete func.prototype.a; - delete func.b; - delete func.prototype.b; }); }); }); @@ -6480,36 +5720,9 @@ } delete _.a; delete _.prototype.a; - delete _.b; - delete _.prototype.b; ok(pass); }); - - test('should return the existing wrapper when chaining', 2, function() { - if (!isNpm) { - _.each([_, wrapper], function(func) { - if (func === _) { - var wrapper = _(source), - actual = wrapper.mixin(); - - strictEqual(actual.value(), _); - } - else { - wrapper = _(func); - actual = wrapper.mixin(source); - strictEqual(actual, wrapper); - } - delete func.a; - delete func.prototype.a; - delete func.b; - delete func.prototype.b; - }); - } - else { - skipTest(2); - } - }); }()); /*--------------------------------------------------------------------------*/ @@ -6519,7 +5732,7 @@ (function() { test('should always return `undefined`', 1, function() { var values = falsey.concat([], true, new Date, _, {}, /x/, 'a'), - expected = _.map(values, _.constant()); + expected = _.map(values, function() { return undefined; }); var actual = _.map(values, function(value, index) { return index ? _.noop(value) : _.noop(); @@ -6634,16 +5847,16 @@ (function() { test('should execute `func` once', 1, function() { var count = 0, - once = _.once(function() { count++; }); + func = _.once(function() { count++; }); - once(); - once(); + func(); + func(); strictEqual(count, 1); }); test('should not set a `this` binding', 1, function() { - var once = _.once(function() { this.count++; }), - object = { 'count': 0, 'once': once }; + var func = _.once(function() { this.count++; }), + object = { 'count': 0, 'once': func }; object.once(); object.once(); @@ -6653,26 +5866,26 @@ test('should ignore recursive calls', 1, function() { var count = 0; - var once = _.once(function() { + var func = _.once(function() { count++; - once(); + func(); }); - once(); + func(); strictEqual(count, 1); }); test('should not throw more than once', 2, function() { - var once = _.once(function() { + var pass = true; + + var func = _.once(function() { throw new Error; }); - raises(function() { once(); }, Error); - - var pass = true; + raises(function() { func(); }, Error); try { - once(); + func(); } catch(e) { pass = false; } @@ -6682,104 +5895,6 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.pad'); - - (function() { - test('should pad a string to a given length', 1, function() { - strictEqual(_.pad('abc', 9), ' abc '); - }); - - test('should truncate pad characters to fit the pad length', 2, function() { - strictEqual(_.pad('abc', 8), ' abc '); - strictEqual(_.pad('abc', 8, '_-'), '_-abc_-_'); - }); - - test('should coerce `string` to a string', 2, function() { - strictEqual(_.pad(Object('abc'), 4), 'abc '); - strictEqual(_.pad({ 'toString': _.constant('abc') }, 5), ' abc '); - }); - }()); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.padLeft'); - - (function() { - test('should pad a string to a given length', 1, function() { - strictEqual(_.padLeft('abc', 6), ' abc'); - }); - - test('should truncate pad characters to fit the pad length', 1, function() { - strictEqual(_.padLeft('abc', 6, '_-'), '_-_abc'); - }); - - test('should coerce `string` to a string', 2, function() { - strictEqual(_.padLeft(Object('abc'), 4), ' abc'); - strictEqual(_.padLeft({ 'toString': _.constant('abc') }, 5), ' abc'); - }); - }()); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.padRight'); - - (function() { - test('should pad a string to a given length', 1, function() { - strictEqual(_.padRight('abc', 6), 'abc '); - }); - - test('should truncate pad characters to fit the pad length', 1, function() { - strictEqual(_.padRight('abc', 6, '_-'), 'abc_-_'); - }); - - test('should coerce `string` to a string', 2, function() { - strictEqual(_.padRight(Object('abc'), 4), 'abc '); - strictEqual(_.padRight({ 'toString': _.constant('abc') }, 5), 'abc '); - }); - }()); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('pad methods'); - - _.each(['pad', 'padLeft', 'padRight'], function(methodName, index) { - var func = _[methodName]; - - test('`_.' + methodName + '` should not pad is string is >= `length`', 2, function() { - strictEqual(func('abc', 2), 'abc'); - strictEqual(func('abc', 3), 'abc'); - }); - - test('`_.' + methodName + '` should treat negative `length` as `0`', 2, function() { - _.each([0, -2], function(length) { - strictEqual(func('abc', length), 'abc'); - }); - }); - - test('`_.' + methodName + '` should coerce `length` to a number', 2, function() { - _.each(['', '4'], function(length) { - var actual = length ? (index == 1 ? ' abc' : 'abc ') : 'abc'; - strictEqual(func('abc', length), actual); - }); - }); - - test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string and `chars`', 6, function() { - _.each([null, '_-'], function(chars) { - strictEqual(func(null, 0, chars), ''); - strictEqual(func(undefined, 0, chars), ''); - strictEqual(func('', 0, chars), ''); - }); - }); - - test('`_.' + methodName + '` should work with `null`, `undefined`, or empty string for `chars`', 3, function() { - notStrictEqual(func('abc', 6, null), 'abc'); - notStrictEqual(func('abc', 6, undefined), 'abc'); - strictEqual(func('abc', 6, ''), 'abc'); - }); - }); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.pairs'); (function() { @@ -6817,7 +5932,7 @@ }); test('should use a radix of `16`, for hexadecimals, if `radix` is `undefined` or `0`', 8, function() { - _.each(['0x20', '0X20'], function(string) { + _.forEach(['0x20', '0X20'], function(string) { strictEqual(_.parseInt(string), 32); strictEqual(_.parseInt(string, 0), 32); strictEqual(_.parseInt(string, 16), 32); @@ -6837,7 +5952,7 @@ strictEqual(_.parseInt(whitespace + '08'), 8); strictEqual(_.parseInt(whitespace + '08', 10), 8); - _.each(['0x20', '0X20'], function(string) { + _.forEach(['0x20', '0X20'], function(string) { strictEqual(_.parseInt(whitespace + string), 32); strictEqual(_.parseInt(whitespace + string, 16), 32); }); @@ -6854,13 +5969,15 @@ QUnit.module('partial methods'); - _.each(['partial', 'partialRight'], function(methodName) { + _.forEach(['partial', 'partialRight'], function(methodName) { var func = _[methodName], isPartial = methodName == 'partial'; test('`_.' + methodName + '` partially applies arguments', 1, function() { - var par = func(_.identity, 'a'); - strictEqual(par(), 'a'); + var fn = function(a) { return a; }, + par = func(fn, 'a'); + + equal(par(), 'a'); }); test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() { @@ -6879,29 +5996,10 @@ }); test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked with additional arguments', 1, function() { - var par = func(_.identity); - strictEqual(par('a'), 'a'); - }); - - test('`_.' + methodName + '` should support placeholders', 4, function() { - if (!isModularize) { - var fn = function() { return slice.call(arguments); }, - par = func(fn, _, 'b', _); - - deepEqual(par('a', 'c'), ['a', 'b', 'c']); - deepEqual(par('a'), ['a', 'b', undefined]); - deepEqual(par(), [undefined, 'b', undefined]); + var fn = function(a) { return a; }, + par = func(fn); - if (isPartial) { - deepEqual(par('a', 'c', 'd'), ['a', 'b', 'c', 'd']); - } else { - par = func(fn, _, 'c', _); - deepEqual(par('a', 'b', 'd'), ['a', 'b', 'c', 'd']); - } - } - else { - skipTest(4); - } + equal(par('a'), 'a'); }); test('`_.' + methodName + '` should not alter the `this` binding', 3, function() { @@ -6929,12 +6027,34 @@ function Foo(value) { return value && object; } - - var object = {}, - par = func(Foo); - - ok(new par instanceof Foo); - strictEqual(new par(true), object); + var par = func(Foo), + object = {}; + + ok(new par instanceof Foo); + strictEqual(new par(true), object); + }); + + test('`_.' + methodName + '` should support placeholders', 4, function() { + if (_._iteratorTemplate) { + var fn = function() { + return slice.call(arguments); + }; + + var par = func(fn, _, 'b', _); + deepEqual(par('a', 'c'), ['a', 'b', 'c']); + deepEqual(par('a'), ['a', 'b', undefined]); + deepEqual(par(), [undefined, 'b', undefined]); + + if (isPartial) { + deepEqual(par('a', 'c', 'd'), ['a', 'b', 'c', 'd']); + } else { + par = func(fn, _, 'c', _); + deepEqual(par('a', 'b', 'd'), ['a', 'b', 'c', 'd']); + } + } + else { + skipTest(4); + } }); test('`_.' + methodName + '` should clone metadata for created functions', 3, function() { @@ -6946,17 +6066,17 @@ par2 = func(par1, 'barney'), par3 = func(par1, 'pebbles'); - strictEqual(par1('fred'), isPartial ? 'hi fred' : 'fred hi') - strictEqual(par2(), isPartial ? 'hi barney' : 'barney hi'); - strictEqual(par3(), isPartial ? 'hi pebbles' : 'pebbles hi'); + equal(par1('fred'), isPartial ? 'hi fred' : 'fred hi') + equal(par2(), isPartial ? 'hi barney' : 'barney hi'); + equal(par3(), isPartial ? 'hi pebbles' : 'pebbles hi'); }); test('`_.' + methodName + '` should work with curried methods', 2, function() { var fn = function(a, b, c) { return a + b + c; }, curried = _.curry(func(fn, 1), 2); - strictEqual(curried(2, 3), 6); - strictEqual(curried(2)(3), 6); + equal(curried(2, 3), 6); + equal(curried(2)(3), 6); }); }); @@ -6981,9 +6101,9 @@ (function() { test('combinations of partial functions should work', 1, function() { - function fn() { + var fn = function() { return slice.call(arguments); - } + }; var a = _.partial(fn), b = _.partialRight(a, 3), @@ -6993,11 +6113,11 @@ }); test('combinations of bound and partial functions should work', 3, function() { - function fn() { + var fn = function() { var result = [this.a]; push.apply(result, arguments); return result; - } + }; var expected = [1, 2, 3, 4], object = { 'a': 1, 'fn': fn }; @@ -7022,9 +6142,9 @@ }); test('recursively bound functions should work', 1, function() { - function fn() { + var fn = function() { return this.a; - } + }; var a = _.bind(fn, { 'a': 1 }), b = _.bind(a, { 'a': 2 }), @@ -7042,9 +6162,9 @@ var array = [1, 0, 1]; test('should always return two groups of elements', 3, function() { - deepEqual(_.partition([], _.identity), [[], []]); - deepEqual(_.partition(array, _.constant(true)), [array, []]); - deepEqual(_.partition(array, _.constant(false)), [[], array]); + deepEqual(_.partition([], function(value) { return value; }), [[], []]); + deepEqual(_.partition(array, function(value) { return true; }), [array, []]); + deepEqual(_.partition(array, function(value) { return false; }), [[], array]); }); test('should use `_.identity` when no `callback` is provided', 1, function() { @@ -7187,25 +6307,6 @@ var object = { 'a': [1], 'b': [1, 2], 'c': [1, 2, 3] }; deepEqual(_.pluck(object, 'length'), [1, 2, 3]); }); - - test('should work with nullish elements', 1, function() { - var objects = [{ 'a': 1 }, null, undefined, { 'a': 4 }]; - deepEqual(_.pluck(objects, 'a'), [1, undefined, undefined, 4]); - }); - - test('should coerce `key` to a string', 1, function() { - function fn() {} - fn.toString = _.constant('fn'); - - var objects = [{ 'null': 1 }, { 'undefined': 2 }, { 'fn': 3 }, { '[object Object]': 4 }], - values = [null, undefined, fn, {}] - - var actual = _.map(objects, function(object, index) { - return _.pluck([object], values[index]); - }); - - deepEqual(actual, [[1], [2], [3], [4]]); - }); }()); /*--------------------------------------------------------------------------*/ @@ -7217,10 +6318,10 @@ var object = { 'a': 1, 'b': 2 }, property = _.property('a'); - strictEqual(property.length, 1); + equal(property.length, 1); strictEqual(property(object), 1); - property = _.property('b'); + property = _.property('b'); strictEqual(property(object), 2); }); @@ -7228,7 +6329,7 @@ var array = [1, 2, 3], property = _.property(1); - strictEqual(property(array), 2); + equal(property(array), 2); }); }()); @@ -7251,8 +6352,8 @@ delete array[3]; _.pull(array, 1); - ok(!('0' in array)); - ok(!('2' in array)); + equal(0 in array, false); + equal(2 in array, false); }); test('should treat holes as `undefined`', 1, function() { @@ -7281,7 +6382,7 @@ test('supports not passing a `max` argument', 1, function() { ok(_.some(array, function() { - return _.random(5) !== 5; + return _.random(5) != 5; })); }); @@ -7328,6 +6429,8 @@ QUnit.module('lodash.range'); (function() { + var func = _.range; + test('should work when passing a single `end` argument', 1, function() { deepEqual(_.range(4), [0, 1, 2, 3]); }); @@ -7354,7 +6457,7 @@ }); test('should treat falsey `start` arguments as `0`', 13, function() { - _.each(falsey, function(value, index) { + _.forEach(falsey, function(value, index) { if (index) { deepEqual(_.range(value), []); deepEqual(_.range(value, 1), [0]); @@ -7364,9 +6467,9 @@ }); }); - test('should coerce arguments to finite numbers', 1, function() { - var actual = [_.range('0', 1), _.range('1'), _.range(0, 1, '1'), _.range(NaN), _.range(NaN, NaN)]; - deepEqual(actual, [[0], [0], [0], [], []]); + test('should coerce arguments to numbers', 1, function() { + var actual = [func('0',1), func('1'), func(0, 1, '1')]; + deepEqual(actual, [[0], [0], [0]]); }); }()); @@ -7425,7 +6528,7 @@ deepEqual(args, expected); }); - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -7439,7 +6542,7 @@ }); deepEqual(args, ['a', 'b', 1, collection]); - strictEqual(actual, 'abc'); + equal(actual, 'abc'); }); }); @@ -7457,7 +6560,7 @@ var array = [1, 2, 3]; test('should use the last element of a collection as the default `accumulator`', 1, function() { - strictEqual(_.reduceRight(array), 3); + equal(_.reduceRight(array), 3); }); test('should pass the correct `callback` arguments when iterating an array', 2, function() { @@ -7504,7 +6607,7 @@ deepEqual(args, expected); }); - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -7518,7 +6621,7 @@ }); deepEqual(args, ['c', 'b', 1, collection]); - strictEqual(actual, 'cba'); + equal(actual, 'cba'); }); }); @@ -7531,7 +6634,7 @@ QUnit.module('reduce methods'); - _.each(['reduce', 'reduceRight'], function(methodName) { + _.forEach(['reduce', 'reduceRight'], function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -7540,7 +6643,7 @@ return accumulator + value; }, ''); - strictEqual(actual, methodName == 'reduce' ? 'abc' : 'cba'); + equal(actual, methodName == 'reduce' ? 'abc' : 'cba'); }); test('`_.' + methodName + '` should support the `thisArg` argument', 1, function() { @@ -7557,7 +6660,7 @@ return sum + num; }); - strictEqual(actual, 6); + equal(actual, 6); } else { skipTest(); @@ -7566,11 +6669,11 @@ test('`_.' + methodName + '` should support empty or falsey collections without an initial `accumulator` value', 1, function() { var actual = [], - expected = _.map(empties, _.constant()); + expected = _.map(empties, function() { return undefined; }); - _.each(empties, function(value) { + _.forEach(empties, function(value) { try { - actual.push(func(value, _.noop)); + actual.push(func(value, noop)); } catch(e) { } }); @@ -7578,11 +6681,11 @@ }); test('`_.' + methodName + '` should support empty or falsey collections with an initial `accumulator` value', 1, function() { - var expected = _.map(empties, _.constant('x')); + var expected = _.map(empties, function() { return 'x'; }); var actual = _.map(empties, function(value) { try { - return func(value, _.noop, 'x'); + return func(value, noop, 'x'); } catch(e) { } }); @@ -7590,7 +6693,7 @@ }); test('`_.' + methodName + '` should handle an initial `accumulator` value of `undefined`', 1, function() { - var actual = func([], _.noop, undefined); + var actual = func([], noop, undefined); strictEqual(actual, undefined); }); @@ -7600,12 +6703,12 @@ if ('__proto__' in array) { array.__proto__ = object; - strictEqual(_.reduce(array, _.noop), undefined); + strictEqual(_.reduce(array, noop), undefined); } else { skipTest(); } - strictEqual(_.reduce(object, _.noop), undefined); + strictEqual(_.reduce(object, noop), undefined); }); }); @@ -7627,7 +6730,7 @@ QUnit.module('filter methods'); - _.each(['filter', 'reject'], function(methodNames) { + _.forEach(['filter', 'reject'], function(methodNames) { var func = _[methodNames]; test('`_.' + methodNames + '` should not modify the resulting value from within `callback`', 1, function() { @@ -7683,8 +6786,8 @@ delete array[3]; _.remove(array, function(num) { return num === 1; }); - ok(!('0' in array)); - ok(!('2' in array)); + equal(0 in array, false); + equal(2 in array, false); }); test('should treat holes as `undefined`', 1, function() { @@ -7698,28 +6801,55 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.repeat'); + QUnit.module('lodash.removeAt'); (function() { - test('should repeat a string `n` times', 2, function() { - strictEqual(_.repeat('*', 3), '***'); - strictEqual(_.repeat('abc', 2), 'abcabc'); + test('should modify the array and return removed elements', 2, function() { + var array = [1, 2, 3]; + var actual = _.removeAt(array, [0, 1]); + + deepEqual(array, [3]); + deepEqual(actual, [1, 2]); + }); + + test('should work with unsorted indexes', 2, function() { + var array = [1, 2, 3, 4, 5]; + var actual = _.removeAt(array, [4, 1, 0, 3]); + + deepEqual(array, [3]); + deepEqual(actual, [1, 2, 4, 5]); + }); + + test('should return `undefined` for nonexistent keys', 2, function() { + var array = ['a', 'b', 'c']; + var actual = _.removeAt(array, [0, 2, 4]); + + deepEqual(array, ['b']); + deepEqual(actual, ['a', 'c', undefined]); }); - test('should return an empty string for negative `n` or `n` of `0`', 2, function() { - strictEqual(_.repeat('abc', 0), ''); - strictEqual(_.repeat('abc', -2), ''); + test('should return an empty array when no keys are provided', 2, function() { + var array = ['a', 'b', 'c']; + var actual = _.removeAt(array); + + deepEqual(array, ['a', 'b', 'c']); + deepEqual(actual, []); }); - test('should coerce `n` to a number', 3, function() { - strictEqual(_.repeat('abc'), ''); - strictEqual(_.repeat('abc', '2'), 'abcabc'); - strictEqual(_.repeat('*', { 'valueOf': _.constant(3) }), '***'); + test('should accept multiple index arguments', 2, function() { + var array = ['a', 'b', 'c', 'd']; + var actual = _.removeAt(array, 0, 2, 3); + + deepEqual(array, ['b']); + deepEqual(actual, ['a', 'c', 'd']); }); - test('should coerce `string` to a string', 2, function() { - strictEqual(_.repeat(Object('abc'), 2), 'abcabc'); - strictEqual(_.repeat({ 'toString': _.constant('*') }, 3), '***'); + test('should work when used as a callback for `_.map`', 2, function() { + var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + var actual = _.map(array, _.removeAt); + + deepEqual(array, [[2, 3], [4, 6], [7, 8]]); + deepEqual(actual, [[1], [5], [9]]); }); }()); @@ -7741,13 +6871,13 @@ strictEqual(_.result(object, 'd'), undefined); }); - test('should return `undefined` when `object` is nullish', 2, function() { + test('should return `undefined` when `object` is `null` or `undefined`', 2, function() { strictEqual(_.result(null, 'a'), undefined); strictEqual(_.result(undefined, 'a'), undefined); }); test('should return the specified default value for undefined properties', 1, function() { - var values = falsey.concat(1, _.constant(1)); + var values = falsey.concat(1, function() { return 1; }); var expected = _.transform(values, function(result, value) { result.push(value, value); @@ -7778,7 +6908,7 @@ ]; test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, _.constant([])); + var expected = _.map(falsey, function() { return []; }); var actual = _.map(falsey, function(value, index) { try { @@ -7797,26 +6927,14 @@ deepEqual(_.rest(array, 2), [3]); }); - test('should treat falsey `n` values, except nullish, as `0`', 1, function() { - var expected = _.map(falsey, function(value) { - return value == null ? [2, 3] : array; - }); - - var actual = _.map(falsey, function(n) { - return _.rest(array, n); - }); - - deepEqual(actual, expected); - }); - test('should return all elements when `n` < `1`', 3, function() { - _.each([0, -1, -Infinity], function(n) { - deepEqual(_.rest(array, n), array); + _.forEach([0, -1, -2], function(n) { + deepEqual(_.rest(array, n), [1, 2, 3]); }); }); - test('should return an empty array when `n` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { + test('should return an empty array when `n` >= `array.length`', 2, function() { + _.forEach([3, 4], function(n) { deepEqual(_.rest(array, n), []); }); }); @@ -7850,7 +6968,7 @@ deepEqual(args, [1, 0, array]); }); - test('should support the `thisArg` argument', 1, function() { + test('supports the `thisArg` argument', 1, function() { var actual = _.rest(array, function(num, index) { return this[index] < 3; }, array); @@ -7917,26 +7035,14 @@ deepEqual(actual.sort(), array); }); - test('should treat falsey `n` values, except nullish, as `0`', 1, function() { - var expected = _.map(falsey, function(value) { - return value == null ? 1 : []; - }); - - var actual = _.map(falsey, function(n) { - return _.sample([1], n); - }); - - deepEqual(actual, expected); - }); - - test('should return an empty array when `n` < `1` or `NaN`', 3, function() { - _.each([0, -1, -Infinity], function(n) { + test('should return an empty array when `n` < `1`', 3, function() { + _.forEach([0, -1, -2], function(n) { deepEqual(_.sample(array, n), []); }); }); - test('should return all elements when `n` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { + test('should return all elements when `n` >= `array.length`', 2, function() { + _.forEach([3, 4], function(n) { deepEqual(_.sample(array, n).sort(), array); }); }); @@ -7952,7 +7058,7 @@ result.push([], []); }); - _.each(empties, function(value) { + _.forEach(empties, function(value) { try { actual.push(_.shuffle(value), _.shuffle(value, 1)); } catch(e) { } @@ -8000,7 +7106,7 @@ } }); - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -8037,11 +7143,7 @@ deepEqual(actual.sort(), array); }); - test('should treat number values for `collection` as empty', 1, function() { - deepEqual(_.shuffle(1), []); - }); - - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -8062,15 +7164,15 @@ array = [1, 2, 3]; test('should return the number of own enumerable properties of an object', 1, function() { - strictEqual(_.size({ 'one': 1, 'two': 2, 'three': 3 }), 3); + equal(_.size({ 'one': 1, 'two': 2, 'three': 3 }), 3); }); test('should return the length of an array', 1, function() { - strictEqual(_.size(array), 3); + equal(_.size(array), 3); }); test('should accept a falsey `object` argument', 1, function() { - var expected = _.map(falsey, _.constant(0)); + var expected = _.map(falsey, function() { return 0; }); var actual = _.map(falsey, function(value, index) { try { @@ -8081,34 +7183,26 @@ deepEqual(actual, expected); }); - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - strictEqual(_.size(args), 3); - }); - test('should work with jQuery/MooTools DOM query collections', 1, function() { function Foo(elements) { push.apply(this, elements); } Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; - strictEqual(_.size(new Foo(array)), 3); - }); - - test('should not treat objects with negative lengths as array-like', 1, function() { - strictEqual(_.size({ 'length': -1 }), 1); - }); - - test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() { - strictEqual(_.size({ 'length': maxSafeInteger + 1 }), 1); + equal(_.size(new Foo(array)), 3); }); - test('should not treat objects with non-number lengths as array-like', 1, function() { - strictEqual(_.size({ 'length': '0' }), 1); + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + if (!isPhantomPage) { + equal(_.size(args), 3); + } else { + skipTest(); + } }); - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { - strictEqual(_.size(shadowedObject), 7); + test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { + equal(_.size(shadowedObject), 7); }); - _.each({ + _.forEach({ 'literal': 'abc', 'object': Object('abc') }, @@ -8130,28 +7224,18 @@ deepEqual(_.slice(array, 1), [2, 3]); }); - test('should work with a `start` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(start) { + test('should work with a `start` >= `array.length`', 2, function() { + _.forEach([3, 4], function(start) { deepEqual(_.slice(array, start), []); }); }); - test('should treat falsey `start` values as `0`', 1, function() { - var expected = _.map(falsey, _.constant(array)); - - var actual = _.map(falsey, function(start) { - return _.slice(array, start); - }); - - deepEqual(actual, expected); - }); - test('should work with a negative `start`', 1, function() { deepEqual(_.slice(array, -1), [3]); }); - test('should work with a negative `start` <= negative `array.length`', 3, function() { - _.each([-3, -4, -Infinity], function(start) { + test('should work with a negative `start` <= negative `array.length`', 2, function() { + _.forEach([-3, -4], function(start) { deepEqual(_.slice(array, start), [1, 2, 3]); }); }); @@ -8160,38 +7244,21 @@ deepEqual(_.slice(array, 0, 1), [1]); }); - test('should work with a `end` >= `array.length`', 4, function() { - _.each([3, 4, Math.pow(2, 32), Infinity], function(end) { + test('should work with a `end` >= `array.length`', 2, function() { + _.forEach([3, 4], function(end) { deepEqual(_.slice(array, 0, end), [1, 2, 3]); }); }); - test('should treat falsey `end` values, except `undefined`, as `0`', 1, function() { - var expected = _.map(falsey, function(value) { - return value === undefined ? array : []; - }); - - var actual = _.map(falsey, function(end) { - return _.slice(array, 0, end); - }); - - deepEqual(actual, expected); - }); - test('should work with a negative `end`', 1, function() { deepEqual(_.slice(array, 0, -1), [1, 2]); }); - test('should work with a negative `end` <= negative `array.length`', 3, function() { - _.each([-3, -4, -Infinity], function(end) { + test('should work with a negative `end` <= negative `array.length`', 2, function() { + _.forEach([-3, -4], function(end) { deepEqual(_.slice(array, 0, end), []); }); }); - - test('should coerce `start` and `end` to finite numbers', 1, function() { - var actual = [_.slice(array, '0', 1), _.slice(array, 0, '1'), _.slice(array, '1'), _.slice(array, NaN, 1), _.slice(array, 1, NaN)]; - deepEqual(actual, [[1], [1], [2, 3], [1], []]); - }); }()); /*--------------------------------------------------------------------------*/ @@ -8200,7 +7267,7 @@ (function() { test('should return `false` for empty or falsey collections', 1, function() { - var expected = _.map(empties, _.constant(false)); + var expected = _.map(empties, function() { return false; }); var actual = _.map(empties, function(value) { try { @@ -8211,7 +7278,7 @@ deepEqual(actual, expected); }); - test('should return `true` if the callback returns truthy for any element in the collection', 2, function() { + test('should return `true` if the callback returns truey for any element in the collection', 2, function() { strictEqual(_.some([false, 1, ''], _.identity), true); strictEqual(_.some([null, 'x', 0], _.identity), true); }); @@ -8221,7 +7288,7 @@ strictEqual(_.some([null, 0, ''], _.identity), false); }); - test('should return `true` as soon as the `callback` result is truthy', 1, function() { + test('should return `true` as soon as the `callback` result is truey', 1, function() { strictEqual(_.some([null, true, null], _.identity), true); }); @@ -8323,10 +7390,6 @@ deepEqual(actual, [3, 1, 2]); }); - test('should treat number values for `collection` as empty', 1, function() { - deepEqual(_.sortBy(1), []); - }); - test('should support sorting by an array of properties', 1, function() { var actual = _.sortBy(objects, ['a', 'b']); deepEqual(actual, [objects[2], objects[0], objects[3], objects[1]]); @@ -8357,8 +7420,8 @@ objects = [{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }]; test('should return the insert index of a given value', 2, function() { - strictEqual(_.sortedIndex(array, 40), 2); - strictEqual(_.sortedIndex(array, 30), 1); + equal(_.sortedIndex(array, 40), 2); + equal(_.sortedIndex(array, 30), 1); }); test('should pass the correct `callback` arguments', 1, function() { @@ -8381,7 +7444,7 @@ test('should work with a string for `callback`', 1, function() { var actual = _.sortedIndex(objects, { 'x': 40 }, 'x'); - strictEqual(actual, 2); + equal(actual, 2); }); test('supports arrays with lengths larger than `Math.pow(2, 31) - 1`', 1, function() { @@ -8393,7 +7456,7 @@ if (array.length == length) { array[index] = index; _.sortedIndex(array, index, function() { steps++; }); - strictEqual(steps, 33); + equal(steps, 33); } else { skipTest(); @@ -8407,9 +7470,7 @@ (function() { test('should contain properties with boolean values', 1, function() { - ok(_.every(_.values(_.support), function(value) { - return value === true || value === false; - })); + ok(_.every(_.values(_.support), _.isBoolean)); }); test('should not contain minified properties (test production builds)', 1, function() { @@ -8425,94 +7486,17 @@ 'nodeClass', 'nonEnumArgs', 'nonEnumShadows', - 'nonEnumStrings', 'ownLast', 'spliceObjects', 'unindexedChars' ]; - ok(_.isEmpty(_.difference(_.keys(_.support), props))); - }); - }()); - - /*--------------------------------------------------------------------------*/ - - QUnit.module('lodash.startsWith'); - - (function() { - var string = 'abc'; - - test('should return `true` if a string starts with `target`', 1, function() { - strictEqual(_.startsWith(string, 'a'), true); - }); - - test('should return `false` if a string does not start with `target`', 1, function() { - strictEqual(_.startsWith(string, 'b'), false); - }); - - test('should work with a `position` argument', 1, function() { - strictEqual(_.startsWith(string, 'b', 1), true); - }); - - test('should work with `position` >= `string.length`', 4, function() { - _.each([3, 5, maxSafeInteger, Infinity], function(position) { - strictEqual(_.startsWith(string, 'a', position), false); - }); - }); - - test('should treat falsey `position` values as `0`', 1, function() { - var expected = _.map(falsey, _.constant(true)); - - var actual = _.map(falsey, function(position) { - return _.startsWith(string, 'a', position); - }); - - deepEqual(actual, expected); - }); - - test('should treat a negative `position` as `0`', 6, function() { - _.each([-1, -3, -Infinity], function(position) { - strictEqual(_.startsWith(string, 'a', position), true); - strictEqual(_.startsWith(string, 'b', position), false); - }); - }); - - test('should always return `true` when `target` is an empty string regardless of `position`', 1, function() { - ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, maxSafeInteger, Infinity], function(position) { - return _.startsWith(string, '', position, true); - })); + ok(!_.size(_.difference(_.keys(_.support), props))); }); }()); /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.startsWith and lodash.endsWith'); - - _.each(['startsWith', 'endsWith'], function(methodName) { - var func = _[methodName], - isEndsWith = methodName == 'endsWith', - chr = isEndsWith ? 'c' : 'a', - string = 'abc'; - - test('`_.' + methodName + '` should coerce `string` to a string', 2, function() { - strictEqual(func(Object(string), chr), true); - strictEqual(func({ 'toString': _.constant(string) }, chr), true); - }); - - test('`_.' + methodName + '` should coerce `target` to a string', 2, function() { - strictEqual(func(string, Object(chr)), true); - strictEqual(func(string, { 'toString': _.constant(chr) }), true); - }); - - test('`_.' + methodName + '` should coerce `position` to a number', 2, function() { - var position = isEndsWith ? 2 : 1; - strictEqual(func(string, 'b', Object(position)), true); - strictEqual(func(string, 'b', { 'toString': _.constant(String(position)) }), true); - }); - }); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.tap'); (function() { @@ -8577,7 +7561,7 @@ unescaped = '&<>"\'\/'; var compiled = _.template('

    <%- value %>

    '); - strictEqual(compiled({ 'value': unescaped }), escaped); + equal(compiled({ 'value': unescaped }), escaped); }); test('should evaluate JavaScript in "evaluate" delimiters', 1, function() { @@ -8589,24 +7573,24 @@ ); var actual = compiled({ 'collection': { 'a': 'A', 'b': 'B' } }); - strictEqual(actual, '
    • A
    • B
    '); + equal(actual, '
    • A
    • B
    '); }); test('should interpolate data object properties', 1, function() { var compiled = _.template('<%= a %>BC'); - strictEqual(compiled({ 'a': 'A' }), 'ABC'); + equal(compiled({ 'a': 'A' }), 'ABC'); }); test('should support escaped values in "interpolation" delimiters', 1, function() { var compiled = _.template('<%= a ? "a=\\"A\\"" : "" %>'); - strictEqual(compiled({ 'a': true }), 'a="A"'); + equal(compiled({ 'a': true }), 'a="A"'); }); test('should work with "interpolate" delimiters containing ternary operators', 1, function() { var compiled = _.template('<%= value ? value : "b" %>'), data = { 'value': 'a' }; - strictEqual(compiled(data), 'a'); + equal(compiled(data), 'a'); }); test('should work with "interpolate" delimiters containing global values', 1, function() { @@ -8616,11 +7600,11 @@ var actual = compiled(); } catch(e) { } - strictEqual(actual, 'function'); + equal(actual, 'function'); }); test('should work with complex "interpolate" delimiters', 22, function() { - _.each({ + _.forEach({ '<%= a + b %>': '3', '<%= b - a %>': '1', '<%= a = b %>': '2', @@ -8648,19 +7632,19 @@ var compiled = _.template(key), data = { 'a': 1, 'b': 2 }; - strictEqual(compiled(data), value, key); + equal(compiled(data), value, key); }); }); test('should parse ES6 template delimiters', 2, function() { var data = { 'value': 2 }; strictEqual(_.template('1${value}3', data), '123'); - strictEqual(_.template('${"{" + value + "\\}"}', data), '{2}'); + equal(_.template('${"{" + value + "\\}"}', data), '{2}'); }); test('should not reference `_.escape` when "escape" delimiters are not used', 1, function() { var compiled = _.template('<%= typeof __e %>'); - strictEqual(compiled({}), 'undefined'); + equal(compiled({}), 'undefined'); }); test('should allow referencing variables declared in "evaluate" delimiters from other delimiters', 1, function() { @@ -8672,7 +7656,7 @@ test('should support single line comments in "evaluate" delimiters (test production builds)', 1, function() { var compiled = _.template('<% // comment %><% if (value) { %>yap<% } else { %>nope<% } %>'); - strictEqual(compiled({ 'value': true }), 'yap'); + equal(compiled({ 'value': true }), 'yap'); }); test('should work with custom `_.templateSettings` delimiters', 1, function() { @@ -8684,10 +7668,10 @@ 'interpolate': /\{\{=([\s\S]+?)\}\}/g }); - var compiled = _.template('
      {{ _.each(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    '), + var compiled = _.template('
      {{ _.forEach(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    '), expected = '
    • 0: a & A
    • 1: b & B
    '; - strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected); + equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected); _.assign(_.templateSettings, settings); }); @@ -8700,16 +7684,16 @@ 'interpolate': /<\?=([\s\S]+?)\?>/g }); - var compiled = _.template('
    • :
    '), + var compiled = _.template('
    • :
    '), expected = '
    • 0: a & A
    • 1: b & B
    '; - strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected); + equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected); _.assign(_.templateSettings, settings); }); test('should work with no delimiters', 1, function() { var expected = 'abc'; - strictEqual(_.template(expected, {}), expected); + equal(_.template(expected, {}), expected); }); test('should support the "imports" option', 1, function() { @@ -8721,7 +7705,7 @@ test('should support the "variable" options', 1, function() { var compiled = _.template( - '<% _.each( data.a, function( value ) { %>' + + '<% _.forEach( data.a, function( value ) { %>' + '<%= value.valueOf() %>' + '<% }) %>', null, { 'variable': 'data' } ); @@ -8735,32 +7719,32 @@ }); test('should use a `with` statement by default', 1, function() { - var compiled = _.template('<%= index %><%= collection[index] %><% _.each(collection, function(value, index) { %><%= index %><% }); %>'), + var compiled = _.template('<%= index %><%= collection[index] %><% _.forEach(collection, function(value, index) { %><%= index %><% }); %>'), actual = compiled({ 'index': 1, 'collection': ['a', 'b', 'c'] }); - strictEqual(actual, '1b012'); + equal(actual, '1b012'); }); test('should work correctly with `this` references', 2, function() { var compiled = _.template('a<%= this.String("b") %>c'); - strictEqual(compiled(), 'abc'); + equal(compiled(), 'abc'); var object = { 'b': 'B' }; object.compiled = _.template('A<%= this.b %>C', null, { 'variable': 'obj' }); - strictEqual(object.compiled(), 'ABC'); + equal(object.compiled(), 'ABC'); }); test('should work with backslashes', 1, function() { var compiled = _.template('<%= a %> \\b'); - strictEqual(compiled({ 'a': 'A' }), 'A \\b'); + equal(compiled({ 'a': 'A' }), 'A \\b'); }); test('should work with escaped characters in string literals', 2, function() { var compiled = _.template('<% print("\'\\n\\r\\t\\u2028\\u2029\\\\") %>'); - strictEqual(compiled(), "'\n\r\t\u2028\u2029\\"); + equal(compiled(), "'\n\r\t\u2028\u2029\\"); compiled = _.template('\'\n\r\t<%= a %>\u2028\u2029\\"'); - strictEqual(compiled({ 'a': 'A' }), '\'\n\r\tA\u2028\u2029\\"'); + equal(compiled({ 'a': 'A' }), '\'\n\r\tA\u2028\u2029\\"'); }); test('should handle \\u2028 & \\u2029 characters', 1, function() { @@ -8775,7 +7759,7 @@ } %>" ); - strictEqual(compiled({ 'a': 'A' }), "'a',\"A\""); + equal(compiled({ 'a': 'A' }), "'a',\"A\""); }); test('should work with templates containing newlines and comments', 1, function() { @@ -8785,7 +7769,7 @@ %>

    <%= value %>

    ' ); - strictEqual(compiled({ 'value': 3 }), '

    6

    '); + equal(compiled({ 'value': 3 }), '

    6

    '); }); test('should not error with IE conditional comments enabled (test with development build)', 1, function() { @@ -8805,7 +7789,7 @@ var compiled = _.template(''), data = { 'type': 1 }; - strictEqual(compiled(data), ''); + equal(compiled(data), ''); }); test('should evaluate delimiters once', 1, function() { @@ -8818,10 +7802,10 @@ test('should match delimiters before escaping text', 1, function() { var compiled = _.template('<<\n a \n>>', null, { 'evaluate': /<<(.*?)>>/g }); - strictEqual(compiled(), '<<\n a \n>>'); + equal(compiled(), '<<\n a \n>>'); }); - test('should resolve `null` and `undefined` values to an empty string', 4, function() { + test('should resolve `null` and `undefined` values to empty strings', 4, function() { var compiled = _.template('<%= a %><%- a %>'); strictEqual(compiled({ 'a': null }), ''); strictEqual(compiled({ 'a': undefined }), ''); @@ -8836,14 +7820,14 @@ compiled = _.template(expected, null, { 'evaluate': /<<(.+?)>>/g }), data = { 'value': true }; - strictEqual(compiled(data), expected); + equal(compiled(data), expected); }); test('should support recursive calls', 1, function() { var compiled = _.template('<%= a %><% a = _.template(c, obj) %><%= a %>'), data = { 'a': 'A', 'b': 'B', 'c': '<%= b %>' }; - strictEqual(compiled(data), 'AB'); + equal(compiled(data), 'AB'); }); test('should coerce `text` argument to a string', 1, function() { @@ -8860,10 +7844,10 @@ }); test('should not modify `_.templateSettings` when `options` are provided', 2, function() { - ok(!('a' in _.templateSettings)); + equal('a' in _.templateSettings, false); _.template('', {}, { 'a': 1 }); - ok(!('a' in _.templateSettings)); + equal('a' in _.templateSettings, false); delete _.templateSettings.a; }); @@ -8900,60 +7884,6 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.truncate'); - - (function() { - var string = 'hi-diddly-ho there, neighborino'; - - test('should truncate to a length of `30` by default', 1, function() { - strictEqual(_.truncate(string), 'hi-diddly-ho there, neighbo...'); - }); - - test('should not truncate if `string` is <= `length`', 2, function() { - strictEqual(_.truncate(string, string.length), string); - strictEqual(_.truncate(string, string.length + 2), string); - }); - - test('should truncate string the given length', 1, function() { - strictEqual(_.truncate(string, 24), 'hi-diddly-ho there, n...'); - }); - - test('should support a `omission` option', 1, function() { - strictEqual(_.truncate(string, { 'omission': ' [...]' }), 'hi-diddly-ho there, neig [...]'); - }); - - test('should support a `length` option', 1, function() { - strictEqual(_.truncate(string, { 'length': 4 }), 'h...'); - }); - - test('should support a `separator` option', 2, function() { - strictEqual(_.truncate(string, { 'length': 24, 'separator': ' ' }), 'hi-diddly-ho there,...'); - strictEqual(_.truncate(string, { 'length': 24, 'separator': /,? +/ }), 'hi-diddly-ho there...'); - }); - - test('should treat negative `length` as `0`', 4, function() { - _.each([0, -2], function(length) { - strictEqual(_.truncate(string, length), '...'); - strictEqual(_.truncate(string, { 'length': length }), '...'); - }); - }); - - test('should coerce `length` to a number', 4, function() { - _.each(['', '4'], function(length, index) { - var actual = index ? 'h...' : '...'; - strictEqual(_.truncate(string, length), actual); - strictEqual(_.truncate(string, { 'length': { 'valueOf': _.constant(length) } }), actual); - }); - }); - - test('should coerce `string` to a string', 2, function() { - strictEqual(_.truncate(Object(string), 4), 'h...'); - strictEqual(_.truncate({ 'toString': _.constant(string) }, 5), 'hi...'); - }); - }()); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.throttle'); (function() { @@ -8982,7 +7912,7 @@ asyncTest('subsequent calls should return the result of the first call', 5, function() { if (!(isRhino && isModularize)) { - var throttled = _.throttle(_.identity, 32), + var throttled = _.throttle(function(value) { return value; }, 32), result = [throttled('a'), throttled('b')]; deepEqual(result, ['a', 'a']); @@ -9027,7 +7957,7 @@ throttled(); setTimeout(function() { - strictEqual(callCount, 2); + equal(callCount, 2); QUnit.start(); }, 64); } @@ -9053,7 +7983,7 @@ }, 32); throttled.call(object, 'a'); - strictEqual(count, 1); + equal(count, 1); setTimeout(function() { ok(count < 3); @@ -9073,10 +8003,10 @@ throttled = _.throttle(function() { count++; }, 32); throttled(); - strictEqual(count, 1); + equal(count, 1); setTimeout(function() { - strictEqual(count, 1); + equal(count, 1); QUnit.start(); }, 64); } @@ -9118,8 +8048,8 @@ return value; }, 32, {}); - strictEqual(throttled('a'), 'a'); - strictEqual(throttled('b'), 'a'); + equal(throttled('a'), 'a'); + equal(throttled('b'), 'a'); setTimeout(function() { strictEqual(count, 2); @@ -9132,14 +8062,14 @@ } }); - test('should support a `leading` option', 4, function() { + test('should work with `leading` option', 4, function() { if (!(isRhino && isModularize)) { - _.each([true, { 'leading': true }], function(options) { + _.forEach([true, { 'leading': true }], function(options) { var withLeading = _.throttle(_.identity, 32, options); - strictEqual(withLeading('a'), 'a'); + equal(withLeading('a'), 'a'); }); - _.each([false, { 'leading': false }], function(options) { + _.forEach([false, { 'leading': false }], function(options) { var withoutLeading = _.throttle(_.identity, 32, options); strictEqual(withoutLeading('a'), undefined); }); @@ -9149,7 +8079,7 @@ } }); - asyncTest('should support a `trailing` option', 6, function() { + asyncTest('should work with `trailing` option', 6, function() { if (!(isRhino && isModularize)) { var withCount = 0, withoutCount = 0; @@ -9164,14 +8094,14 @@ return value; }, 64, { 'trailing': false }); - strictEqual(withTrailing('a'), 'a'); - strictEqual(withTrailing('b'), 'a'); + equal(withTrailing('a'), 'a'); + equal(withTrailing('b'), 'a'); - strictEqual(withoutTrailing('a'), 'a'); - strictEqual(withoutTrailing('b'), 'a'); + equal(withoutTrailing('a'), 'a'); + equal(withoutTrailing('b'), 'a'); setTimeout(function() { - strictEqual(withCount, 2); + equal(withCount, 2); strictEqual(withoutCount, 1); QUnit.start(); }, 256); @@ -9214,15 +8144,14 @@ QUnit.module('lodash.debounce and lodash.throttle'); - _.each(['debounce', 'throttle'], function(methodName) { - var func = _[methodName], - isThrottle = methodName == 'throttle'; + _.forEach(['debounce', 'throttle'], function(methodName) { + var func = _[methodName]; test('_.' + methodName + ' should not error for non-object `options` values', 1, function() { var pass = true; try { - func(_.noop, 32, 1); + func(noop, 32, 1); } catch(e) { pass = false; } @@ -9238,11 +8167,11 @@ }; object.funced(); - if (isThrottle) { + if (methodName == 'throttle') { object.funced(); } setTimeout(function() { - deepEqual(actual, isThrottle ? [object, object] : [object]); + deepEqual(actual, methodName == 'throttle' ? [object, object] : [object]); QUnit.start(); }, 64); } @@ -9275,7 +8204,7 @@ setTimeout(function() { funced(); - strictEqual(callCount, isThrottle ? 2 : 1); + equal(callCount, methodName == 'throttle' ? 2 : 1); QUnit.start(); }, 64); } @@ -9308,7 +8237,7 @@ QUnit.module('lodash.slice and lodash.toArray'); - _.each(['slice', 'toArray'], function(methodName) { + _.forEach(['slice', 'toArray'], function(methodName) { var args = (function() { return arguments; }(1, 2, 3)), array = [1, 2, 3], func = _[methodName]; @@ -9319,8 +8248,8 @@ var actual = func(sparse); - ok('0' in actual); - ok('2' in actual); + ok(0 in actual); + ok(2 in actual); deepEqual(actual, sparse); }); @@ -9354,17 +8283,6 @@ QUnit.module('lodash.times'); (function() { - test('should rollover large `n` values', 1, function() { - var actual = _.times(Math.pow(2, 32) + 1); - deepEqual(actual, [0]); - }); - - test('should coerce non-finite `n` values to `0`', 3, function() { - _.each([-Infinity, NaN, Infinity], function(n) { - deepEqual(_.times(n), []); - }); - }); - test('should pass the correct `callback` arguments', 1, function() { var args; @@ -9396,7 +8314,7 @@ test('should return an empty array for falsey and negative `n` arguments', 1, function() { var values = falsey.concat(-1, -Infinity), - expected = _.map(values, _.constant([])); + expected = _.map(values, function() { return []; }); var actual = _.map(values, function(value, index) { return index ? _.times(value) : _.times(); @@ -9450,11 +8368,7 @@ ok(_.transform(new Foo) instanceof Foo); }); - test('should check that `object` is an object before using it as the `accumulator` `[[Prototype]]', 1, function() { - ok(!(_.transform(1) instanceof Number)); - }); - - _.each({ + _.forEach({ 'array': [1, 2, 3], 'object': { 'a': 1, 'b': 2, 'c': 3 } }, @@ -9468,10 +8382,10 @@ var first = args[0]; if (key == 'array') { - ok(first !== object && _.isArray(first)); + ok(first != object && _.isArray(first)); deepEqual(args, [first, 1, 0, object]); } else { - ok(first !== object && _.isPlainObject(first)); + ok(first != object && _.isPlainObject(first)); deepEqual(args, [first, 1, 'a', object]); } }); @@ -9491,7 +8405,7 @@ QUnit.module('trim methods'); - _.each(['trim', 'trimLeft', 'trimRight'], function(methodName, index) { + _.forEach(['trim', 'trimLeft', 'trimRight'], function(methodName, index) { var func = _[methodName]; var parts = []; @@ -9508,13 +8422,6 @@ strictEqual(func(string), (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : '')); }); - test('`_.' + methodName + '` should not remove non-whitespace characters', 1, function() { - var problemChars = '\x85\u200b\ufffe', - string = problemChars + 'a b c' + problemChars; - - strictEqual(func(string), string); - }); - test('`_.' + methodName + '` should coerce `string` to a string', 1, function() { var object = { 'toString': function() { return whitespace + 'a b c' + whitespace; } }; strictEqual(func(object), (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : '')); @@ -9532,22 +8439,13 @@ strictEqual(func(string, object), (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : '')); }); - test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string and `chars`', 6, function() { - _.each([null, '_-'], function(chars) { - strictEqual(func(null, chars), ''); - strictEqual(func(undefined, chars), ''); - strictEqual(func('', chars), ''); + test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty strings', 6, function() { + _.forEach([null, '_-'], function(arg) { + strictEqual(func.call(_, null, arg), ''); + strictEqual(func.call(_, undefined, arg), ''); + strictEqual(func.call(_, '', arg), ''); }); }); - - test('`_.' + methodName + '` should work with `null`, `undefined`, or empty string for `chars`', 3, function() { - var string = whitespace + 'a b c' + whitespace, - expected = (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : ''); - - strictEqual(func(string, null), expected); - strictEqual(func(string, undefined), expected); - strictEqual(func(string, ''), string); - }); }); /*--------------------------------------------------------------------------*/ @@ -9559,23 +8457,29 @@ unescaped = '&<>"\'\/'; test('should unescape entities in the correct order', 1, function() { - strictEqual(_.unescape('&lt;'), '<'); + equal(_.unescape('&lt;'), '<'); }); test('should unescape the proper entities', 1, function() { - strictEqual(_.unescape(escaped), unescaped); + equal(_.unescape(escaped), unescaped); }); test('should not unescape the "/" entity', 1, function() { - strictEqual(_.unescape('/'), '/'); + equal(_.unescape('/'), '/'); }); test('should handle strings with nothing to unescape', 1, function() { - strictEqual(_.unescape('abc'), 'abc'); + equal(_.unescape('abc'), 'abc'); }); test('should unescape the same characters escaped by `_.escape`', 1, function() { - strictEqual(_.unescape(_.escape(unescaped)), unescaped); + equal(_.unescape(_.escape(unescaped)), unescaped); + }); + + test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() { + strictEqual(_.unescape(null), ''); + strictEqual(_.unescape(undefined), ''); + strictEqual(_.unescape(''), ''); }); }()); @@ -9584,25 +8488,28 @@ QUnit.module('lodash.union'); (function() { - var args = arguments; - test('should return the union of the given arrays', 1, function() { - var actual = _.union([1, 3, 2], [5, 2, 1, 4], [2, 1]); - deepEqual(actual, [1, 3, 2, 5, 4]); + var actual = _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); + deepEqual(actual, [1, 2, 3, 5, 4]); }); test('should not flatten nested arrays', 1, function() { - var actual = _.union([1, 3, 2], [1, [5]], [2, [4]]); - deepEqual(actual, [1, 3, 2, [5], [4]]); + var actual = _.union([1, 2, 3], [1, [5]], [2, [4]]); + deepEqual(actual, [1, 2, 3, [5], [4]]); }); - test('should ignore values that are not arrays or `arguments` objects', 3, function() { - var array = [0]; - deepEqual(_.union(array, 3, null, { '0': 1 }), array); - deepEqual(_.union(null, array, null, [2, 1]), [0, 2, 1]); - deepEqual(_.union(null, array, null, args), [0, 1, 2, 3]); + test('should produce correct results when provided a falsey `array` argument', 1, function() { + var expected = [1, 2, 3], + actual = _.union(null, expected); + + deepEqual(actual, expected); }); - }(1, 2, 3)); + + test('should ignore individual secondary values', 1, function() { + var array = [1]; + deepEqual(_.union(array, 1, 2, 3), array); + }); + }()); /*--------------------------------------------------------------------------*/ @@ -9660,7 +8567,7 @@ test('should work with large arrays', 1, function() { var object = {}; - var largeArray = _.times(largeArraySize, function(index) { + var largeArray = _.times(LARGE_ARRAY_SIZE, function(index) { switch (index % 3) { case 0: return 0; case 1: return 'a'; @@ -9674,19 +8581,18 @@ test('should work with large arrays of boolean, `null`, and `undefined` values', 1, function() { var array = [], expected = [true, false, null, undefined], - count = Math.ceil(largeArraySize / expected.length); + count = Math.ceil(LARGE_ARRAY_SIZE / expected.length); _.times(count, function() { push.apply(array, expected); }); - deepEqual(_.uniq(array), expected); }); test('should distinguish between numbers and numeric strings', 1, function() { var array = [], expected = ['2', 2, Object('2'), Object(2)], - count = Math.ceil(largeArraySize / expected.length); + count = Math.ceil(LARGE_ARRAY_SIZE / expected.length); _.times(count, function() { push.apply(array, expected); @@ -9695,7 +8601,7 @@ deepEqual(_.uniq(array), expected); }); - _.each({ + _.forEach({ 'an object': ['a'], 'a number': 0, 'a string': '0' @@ -9723,11 +8629,11 @@ actual.push(_.uniqueId()); }); - strictEqual(_.uniq(actual).length, actual.length); + equal(_.uniq(actual).length, actual.length); }); test('should return a string value when not passing a prefix argument', 1, function() { - strictEqual(typeof _.uniqueId(), 'string'); + equal(typeof _.uniqueId(), 'string'); }); test('should coerce the prefix argument to a string', 1, function() { @@ -9757,7 +8663,7 @@ QUnit.module('lodash.where'); (function() { - var objects = [ + var array = [ { 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }, @@ -9765,27 +8671,22 @@ { 'a': 3 } ]; - test('should filter by `source` properties', 6, function() { - deepEqual(_.where(objects, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]); - deepEqual(_.where(objects, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]); - deepEqual(_.where(objects, { 'a': 3 }), [{ 'a': 3 }]); - deepEqual(_.where(objects, { 'b': 1 }), []); - deepEqual(_.where(objects, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); - deepEqual(_.where(objects, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]); + test('should filter by properties', 6, function() { + deepEqual(_.where(array, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]); + deepEqual(_.where(array, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]); + deepEqual(_.where(array, { 'a': 3 }), [{ 'a': 3 }]); + deepEqual(_.where(array, { 'b': 1 }), []); + deepEqual(_.where(array, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); + deepEqual(_.where(array, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]); }); - test('should not filter by inherited `source` properties', 2, function() { + test('should not filter by inherited properties', 1, function() { function Foo() {} Foo.prototype = { 'a': 2 }; - var source = new Foo; - source.b = 2; - - var expected = [objects[2], objects[3]], - actual = _.where(objects, source); - - deepEqual(actual, expected); - ok(_.isEmpty(_.difference(actual, objects))); + var properties = new Foo; + properties.b = 2; + deepEqual(_.where(array, properties), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); }); test('should filter by problem JScript properties (test in IE < 9)', 1, function() { @@ -9793,83 +8694,47 @@ deepEqual(_.where(collection, shadowedObject), [shadowedObject]); }); - test('should work with an object for `collection`', 2, function() { + test('should work with an object for `collection`', 1, function() { var collection = { 'x': { 'a': 1 }, 'y': { 'a': 3 }, 'z': { 'a': 1, 'b': 2 } }; - var expected = [collection.x, collection.z], - actual = _.where(collection, { 'a': 1 }); - - deepEqual(actual, expected); - ok(_.isEmpty(_.difference(actual, _.values(collection)))); - }); - - test('should work with a function for `source`', 1, function() { - function source() {} - source.a = 2; - - deepEqual(_.where(objects, source), [{ 'a': 2, 'b': 2 }]); + deepEqual(_.where(collection, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1, 'b': 2 }]); }); - test('should match all elements when provided an empty `source`', 1, function() { - var expected = _.map(empties, _.constant(objects)); - - var actual = _.map(empties, function(value) { - var result = _.where(objects, value); - return result !== objects && result; - }); - - deepEqual(actual, expected); + test('should return an empty array when provided an empty `properties` object', 1, function() { + deepEqual(_.where(array, {}), []); }); - test('should perform a deep partial comparison of `source`', 2, function() { + test('should deep compare `properties` values', 1, function() { var collection = [{ 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4 }], - expected = collection.slice(), - actual = _.where(collection, { 'a': { 'b': { 'c': 1 } } }); + expected = _.cloneDeep(collection); - deepEqual(actual, expected); - ok(_.isEmpty(_.difference(actual, collection))); + deepEqual(_.where(collection, { 'a': { 'b': { 'c': 1 } } }), expected); }); test('should search of arrays for values', 2, function() { var collection = [{ 'a': [1, 2] }], - expected = collection.slice(); + expected = _.cloneDeep(collection); deepEqual(_.where(collection, { 'a': [] }), []); deepEqual(_.where(collection, { 'a': [2] }), expected); }); - test('should perform a partial comparison of *all* objects within arrays of `source`', 2, function() { - var collection = [ - { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 5, 'd': 6 }] }, - { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 6, 'd': 7 }] } - ]; - - var actual = _.where(collection, { 'a': [{ 'b': 1, 'c': 2 }, { 'b': 4, 'c': 5 }] }); - deepEqual(actual, [collection[0]]); - ok(_.isEmpty(_.difference(actual, collection))); - }); - - test('should handle a `source` with `undefined` values', 4, function() { - var source = { 'b': undefined }, - actual = _.where([{ 'a': 1 }, { 'a': 1, 'b': 1 }], source); - - deepEqual(actual, []); + test('should handle `properties` with `undefined` values', 4, function() { + var properties = { 'b': undefined }; + deepEqual(_.where([{ 'a': 1 }, { 'a': 1, 'b': 1 }], properties), []); var object = { 'a': 1, 'b': undefined }; - actual = _.where([object], source); - deepEqual(actual, [object]); + deepEqual(_.where([object], properties), [object]); - source = { 'a': { 'c': undefined } }; - actual = _.where([{ 'a': { 'b': 1 } }, { 'a':{ 'b':1 , 'c': 1 } }], source); - deepEqual(actual, []); + properties = { 'a': { 'c': undefined } }; + deepEqual(_.where([{ 'a': { 'b': 1 } }, { 'a':{ 'b':1 , 'c': 1 } }], properties), []); object = { 'a': { 'b': 1, 'c': undefined } }; - actual = _.where([object], source); - deepEqual(actual, [object]); + deepEqual(_.where([object], properties), [object]); }); }()); @@ -9903,18 +8768,18 @@ return '

    ' + func(text) + '

    '; }); - strictEqual(p('fred, barney, & pebbles'), '

    fred, barney, & pebbles

    '); + equal(p('fred, barney, & pebbles'), '

    fred, barney, & pebbles

    '); }); test('should pass the correct `wrapper` arguments', 1, function() { var args; - var wrapped = _.wrap(_.noop, function() { + var wrapped = _.wrap(noop, function() { args || (args = slice.call(arguments)); }); wrapped(1, 2, 3); - deepEqual(args, [_.noop, 1, 2, 3]); + deepEqual(args, [noop, 1, 2, 3]); }); test('should not set a `this` binding', 1, function() { @@ -9923,7 +8788,7 @@ }); var object = { 'p': p, 'text': 'fred, barney, & pebbles' }; - strictEqual(object.p(), '

    fred, barney, & pebbles

    '); + equal(object.p(), '

    fred, barney, & pebbles

    '); }); }()); @@ -9932,8 +8797,6 @@ QUnit.module('lodash.xor'); (function() { - var args = arguments; - test('should return the symmetric difference of the given arrays', 1, function() { var actual = _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); deepEqual(actual, [1, 4, 5]); @@ -9963,18 +8826,11 @@ } }); - test('should ignore individual secondary arguments', 1, function() { - var array = [0]; - deepEqual(_.xor(array, 3, null, { '0': 1 }), array); + test('should ignore individual secondary values', 1, function() { + var array = [1, null, 3]; + deepEqual(_.xor(array, 3, null), array); }); - - test('should ignore values that are not arrays or `arguments` objects', 3, function() { - var array = [1, 2]; - deepEqual(_.xor(array, 3, null, { '0': 1 }), array); - deepEqual(_.xor(null, array, null, [2, 3]), [1, 3]); - deepEqual(_.xor(null, array, null, args), [3]); - }); - }(1, 2, 3)); + }()); /*--------------------------------------------------------------------------*/ @@ -10015,11 +8871,11 @@ ]; var actual = _.zip(pair[0]); - ok('0' in actual[2]); + ok(0 in actual[2]); deepEqual(actual, pair[1]); actual = _.zip.apply(_, actual); - ok('2' in actual[0]); + ok(2 in actual[0]); deepEqual(actual, [['barney', 36, undefined], ['fred', 40, false]]); }); @@ -10066,7 +8922,7 @@ }); test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, _.constant({})); + var expected = _.map(falsey, function() { return {}; }); var actual = _.map(falsey, function(value, index) { try { @@ -10097,7 +8953,7 @@ wrapped.shift(); deepEqual(wrapped.keys().value(), ['length']); - strictEqual(wrapped.first(), undefined); + equal(wrapped.first(), undefined); } else { skipTest(2); @@ -10116,7 +8972,7 @@ wrapped.splice(0, 1); deepEqual(wrapped.keys().value(), ['length']); - strictEqual(wrapped.first(), undefined); + equal(wrapped.first(), undefined); } else { skipTest(2); @@ -10132,7 +8988,7 @@ test('should return the `toString` result of the wrapped value', 1, function() { if (!isNpm) { var wrapped = _([1, 2, 3]); - strictEqual(String(wrapped), '1,2,3'); + equal(String(wrapped), '1,2,3'); } else { skipTest(); @@ -10148,33 +9004,12 @@ test('should return the `valueOf` result of the wrapped value', 1, function() { if (!isNpm) { var wrapped = _(123); - strictEqual(Number(wrapped), 123); - } - else { - skipTest(); - } - }); - - test('should stringify the wrapped value when passed to `JSON.stringify`', 1, function() { - if (!isNpm && JSON) { - var wrapped = _([1, 2, 3]); - strictEqual(JSON.stringify(wrapped), '[1,2,3]'); + equal(Number(wrapped), 123); } else { skipTest(); } }); - - test('should be aliased', 2, function() { - if (!isNpm) { - var expected = _.prototype.valueOf; - strictEqual(_.prototype.toJSON, expected); - strictEqual(_.prototype.value, expected); - } - else { - skipTest(2); - } - }); }()); /*--------------------------------------------------------------------------*/ @@ -10192,7 +9027,7 @@ 'unshift' ]; - _.each(funcs, function(methodName) { + _.forEach(funcs, function(methodName) { test('`_(...).' + methodName + '` should return the existing wrapped value', 1, function() { if (!isNpm) { strictEqual(wrapped[methodName](), wrapped); @@ -10218,7 +9053,7 @@ 'splice' ]; - _.each(funcs, function(methodName) { + _.forEach(funcs, function(methodName) { test('`_(...).' + methodName + '` should return a new wrapped value', 1, function() { if (!isNpm) { ok(wrapped[methodName]() instanceof _); @@ -10271,14 +9106,14 @@ 'some' ]; - _.each(funcs, function(methodName) { + _.forEach(funcs, function(methodName) { test('`_(...).' + methodName + '` should return an unwrapped value', 1, function() { if (!isNpm) { var actual = methodName == 'reduceRight' ? wrapped[methodName](_.identity) : wrapped[methodName](); - ok(!(actual instanceof _)); + equal(actual instanceof _, false); } else { skipTest(); @@ -10301,10 +9136,10 @@ 'sample' ]; - _.each(funcs, function(methodName) { + _.forEach(funcs, function(methodName) { test('`_(...).' + methodName + '` called without an `n` argument should return an unwrapped value', 1, function() { if (!isNpm) { - strictEqual(typeof wrapped[methodName](), 'number'); + equal(typeof wrapped[methodName](), 'number'); } else { skipTest(); @@ -10323,10 +9158,10 @@ test('`_.' + methodName + '` should return `undefined` when querying falsey arguments without an `n` argument', 1, function() { if (!isNpm) { var actual = [], - expected = _.map(falsey, _.constant()), + expected = _.map(falsey, function() { return undefined; }), func = _[methodName]; - _.each(falsey, function(value, index) { + _.forEach(falsey, function(value, index) { try { actual.push(index ? func(value) : func()); } catch(e) { } @@ -10341,7 +9176,7 @@ test('`_.' + methodName + '` should return an empty array when querying falsey arguments with an `n` argument', 1, function() { if (!isNpm) { - var expected = _.map(falsey, _.constant([])), + var expected = _.map(falsey, function() { return []; }), func = _[methodName]; var actual = _.map(falsey, function(value, index) { @@ -10402,22 +9237,21 @@ deepEqual([args[0], args[1], args[2]], [1, [3], 5], message('pull')); _.remove(args, function(value) { return typeof value == 'number'; }); - ok(args.length === 1 && _.isEqual(args[0], [3]), message('remove')); + ok(args.length == 1 && _.isEqual(args[0], [3]), message('remove')); } else { skipTest(2) } }); - test('should accept falsey primary arguments', 4, function() { + test('should accept falsey primary arguments', 3, function() { function message(methodName) { return '`_.' + methodName + '` should accept falsey primary arguments'; } - deepEqual(_.difference(null, array), array, message('difference')); - deepEqual(_.intersection(null, array), array, message('intersection')); + deepEqual(_.difference(null, array), [], message('difference')); + deepEqual(_.intersection(null, array), [], message('intersection')); deepEqual(_.union(null, array), array, message('union')); - deepEqual(_.xor(null, array), array, message('xor')); }); test('should accept falsey secondary arguments', 3, function() { @@ -10426,49 +9260,13 @@ } deepEqual(_.difference(array, null), array, message('difference')); - deepEqual(_.intersection(array, null), array, message('intersection')); + deepEqual(_.intersection(array, null), [], message('intersection')); deepEqual(_.union(array, null), array, message('union')); }); }(1, null, [3], null, 5)); /*--------------------------------------------------------------------------*/ - /*--------------------------------------------------------------------------*/ - - QUnit.module('"Strings" category methods'); - - (function() { - var stringMethods = [ - 'camelCase', - 'capitalize', - 'escape', - 'escapeRegExp', - 'kebabCase', - 'pad', - 'padLeft', - 'padRight', - 'repeat', - 'snakeCase', - 'trim', - 'trimLeft', - 'trimRight', - 'truncate', - 'unescape' - ]; - - _.each(stringMethods, function(methodName) { - var func = _[methodName]; - - test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string', 3, function() { - strictEqual(func(null), ''); - strictEqual(func(undefined), ''); - strictEqual(func(''), ''); - }); - }); - }()); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash methods'); (function() { @@ -10496,6 +9294,7 @@ 'range', 'reject', 'remove', + 'removeAt', 'rest', 'sample', 'shuffle', @@ -10520,7 +9319,6 @@ 'defer', 'delay', 'memoize', - 'negate', 'once', 'partial', 'partialRight', @@ -10531,12 +9329,12 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 185, function() { - var emptyArrays = _.map(falsey, _.constant([])), + test('should accept falsey arguments', 167, function() { + var emptyArrays = _.map(falsey, function() { return []; }), isExposed = '_' in root, oldDash = root._; - _.each(acceptFalsey, function(methodName) { + _.forEach(acceptFalsey, function(methodName) { var expected = emptyArrays, func = _[methodName], pass = true; @@ -10567,17 +9365,17 @@ }); // skip tests for missing methods of modularized builds - _.each(['noConflict', 'runInContext', 'tap'], function(methodName) { + _.forEach(['noConflict', 'runInContext', 'tap'], function(methodName) { if (!_[methodName]) { skipTest(); } }); }); - test('should return an array', 64, function() { + test('should return an array', 66, function() { var array = [1, 2, 3]; - _.each(returnArrays, function(methodName) { + _.forEach(returnArrays, function(methodName) { var actual, func = _[methodName]; @@ -10596,13 +9394,13 @@ ok(_.isArray(actual), '_.' + methodName + ' returns an array'); var isPull = methodName == 'pull'; - strictEqual(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array'); + equal(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array'); }); }); - test('should throw a TypeError for falsey arguments', 15, function() { - _.each(rejectFalsey, function(methodName) { - var expected = _.map(falsey, _.constant(true)), + test('should reject falsey arguments', 14, function() { + _.forEach(rejectFalsey, function(methodName) { + var expected = _.map(falsey, function() { return true; }), func = _[methodName]; var actual = _.map(falsey, function(value, index) { @@ -10619,18 +9417,14 @@ }); }); - test('should handle `null` `thisArg` arguments', 44, function() { - var expected = (function() { return this; }).call(null); + test('should handle `null` `thisArg` arguments', 30, function() { + var thisArg, + callback = function() { thisArg = this; }, + expected = (function() { return this; }).call(null); var funcs = [ - 'assign', - 'clone', - 'cloneDeep', 'countBy', - 'dropWhile', - 'dropRightWhile', 'every', - 'flatten', 'filter', 'find', 'findIndex', @@ -10645,14 +9439,10 @@ 'forOwn', 'forOwnRight', 'groupBy', - 'isEqual', 'map', - 'mapValues', 'max', - 'merge', 'min', 'omit', - 'partition', 'pick', 'reduce', 'reduceRight', @@ -10661,46 +9451,38 @@ 'some', 'sortBy', 'sortedIndex', - 'takeWhile', - 'takeRightWhile', - 'tap', 'times', - 'transform', 'uniq' ]; - _.each(funcs, function(methodName) { - var actual, - array = ['a'], + _.forEach(funcs, function(methodName) { + var array = ['a'], func = _[methodName], message = '`_.' + methodName + '` handles `null` `thisArg` arguments'; - function callback() { - actual = this; - } - if (func) { - if (/^reduce/.test(methodName) || methodName == 'transform') { - func(array, callback, 0, null); - } else if (_.contains(['assign', 'merge'], methodName)) { - func(array, array, callback, null); - } else if (_.contains(['isEqual', 'sortedIndex'], methodName)) { - func(array, 'a', callback, null); - } else if (methodName == 'times') { - func(1, callback, null); - } else { - func(array, callback, null); - } - strictEqual(actual, expected, message); + thisArg = undefined; + + if (/^reduce/.test(methodName)) { + func(array, callback, 0, null); + } else if (methodName == 'sortedIndex') { + func(array, 'a', callback, null); + } else if (methodName == 'times') { + func(1, callback, null); + } else { + func(array, callback, null); } - else { - skipTest(); + + if (expected === null) { + strictEqual(thisArg, null, message); + } else { + equal(thisArg, expected, message); } }); }); test('should not contain minified method names (test production builds)', 1, function() { ok(_.every(_.functions(_), function(methodName) { - return methodName.length > 2 || methodName === 'at'; + return methodName.length > 2 || methodName == 'at'; })); }); }()); From ff26080c5c378fd7af282e5b72c500832c1ddbbf Mon Sep 17 00:00:00 2001 From: Dan Allison Date: Sat, 1 Mar 2014 08:56:44 -0800 Subject: [PATCH 0612/1608] fix `_.removeAt` with repeated indexes --- lodash.js | 12 ++++++++++-- test/test.js | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index 673d907494..f4ee952ae7 100644 --- a/lodash.js +++ b/lodash.js @@ -2927,9 +2927,17 @@ } else { removals.sort(baseCompareAscending); } - var result = Array(length); + var result = Array(length), + adjust = -1, + removal, prev; while(++index < length) { - result[index] = splice.call(array, removals[index] - index, 1)[0]; + removal = removals[index]; + if (removal === prev) { + result[index] = result[index - 1]; + continue; + } + prev = removal; + result[index] = splice.call(array, removal - ++adjust, 1)[0]; } return result; } diff --git a/test/test.js b/test/test.js index 1212c67590..69e153d3e0 100644 --- a/test/test.js +++ b/test/test.js @@ -6820,6 +6820,14 @@ deepEqual(actual, [1, 2, 4, 5]); }); + test('should work with repeated indexes', 2, function() { + var array = [1, 2, 3, 4, 5]; + var actual = _.removeAt(array, [0, 0, 1, 2, 2, 2]); + + deepEqual(array, [4, 5]); + deepEqual(actual, [1, 1, 2, 3, 3, 3]); + }); + test('should return `undefined` for nonexistent keys', 2, function() { var array = ['a', 'b', 'c']; var actual = _.removeAt(array, [0, 2, 4]); From d25ab4f2044fc88e1271e7deae351766dcb36b6e Mon Sep 17 00:00:00 2001 From: Dan Allison Date: Sat, 1 Mar 2014 10:23:51 -0800 Subject: [PATCH 0613/1608] use more descriptive variable name --- lodash.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index f4ee952ae7..a7510874d4 100644 --- a/lodash.js +++ b/lodash.js @@ -2929,14 +2929,14 @@ } var result = Array(length), adjust = -1, - removal, prev; + removal, previous; while(++index < length) { removal = removals[index]; - if (removal === prev) { + if (removal === previous) { result[index] = result[index - 1]; continue; } - prev = removal; + previous = removal; result[index] = splice.call(array, removal - ++adjust, 1)[0]; } return result; From 0dc2e8994be75d1caa462f46bdb030d5b21fe2bd Mon Sep 17 00:00:00 2001 From: Dan Allison Date: Sat, 1 Mar 2014 18:30:03 -0800 Subject: [PATCH 0614/1608] use `else` instead of `continue` --- lodash.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index a7510874d4..ec1a9a8d47 100644 --- a/lodash.js +++ b/lodash.js @@ -2934,10 +2934,10 @@ removal = removals[index]; if (removal === previous) { result[index] = result[index - 1]; - continue; + } else { + previous = removal; + result[index] = splice.call(array, removal - ++adjust, 1)[0]; } - previous = removal; - result[index] = splice.call(array, removal - ++adjust, 1)[0]; } return result; } From 8c618780b74ec90226a6714d1ab60c10423f0df0 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 02:18:57 -0700 Subject: [PATCH 0615/1608] Rename `_.removeAt` to `_.pullAt`. [closes #490] --- lodash.js | 4046 ++++++++++++++++++++++++++++++-------------------- test/test.js | 3129 ++++++++++++++++++++++++++------------ 2 files changed, 4594 insertions(+), 2581 deletions(-) diff --git a/lodash.js b/lodash.js index ec1a9a8d47..eae8c26cd2 100644 --- a/lodash.js +++ b/lodash.js @@ -3,7 +3,7 @@ * Lo-Dash 2.4.1 * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ ;(function() { @@ -25,9 +25,15 @@ /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; + /** Used as the TypeError message for "Functions" methods */ + var funcErrorText = 'Expected a function'; + /** Used to generate unique IDs */ var idCounter = 0; + /** Used to detect words composed of all capital letters */ + var reAllCaps = /^[A-Z]+$/; + /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, @@ -43,12 +49,13 @@ reInterpolate = /<%=([\s\S]+?)%>/g; /** - * Used to match ES6 template delimiters - * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals + * Used to match ES6 template delimiters. + * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) + * for more details. */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; - /** Used to match regexp flags from their coerced string values */ + /** Used to match `RegExp` flags from their coerced string values */ var reFlags = /\w*$/; /** Used to detected named functions */ @@ -57,14 +64,27 @@ /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; + /** Used to match latin-1 supplement letters */ + var reLatin1 = /[\xC0-\xFF]/g; + /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; + /** + * Used to match `RegExp` special characters. + * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) + * for more details. + */ + var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g; + /** Used to detect functions containing a `this` reference */ var reThis = /\bthis\b/; /** Used to match unescaped characters in compiled string literals */ - var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to match words to create compound words */ + var reWords = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g; /** Used to detect and test whitespace */ var whitespace = ( @@ -85,13 +105,13 @@ 'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError' ]; - /** Used to fix the JScript [[DontEnum]] bug */ + /** Used to fix the JScript `[[DontEnum]]` bug */ var shadowedProps = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; - /** Used to make template sourceURLs easier to identify */ + /** Used to make template `sourceURL`s easier to identify */ var templateCounter = 0; /** `Object#toString` result shortcuts */ @@ -114,7 +134,7 @@ cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; - /** Used as an internal `_.debounce` options object */ + /** Used as an internal `_.debounce` options object by `_.throttle` */ var debounceOptions = { 'leading': false, 'maxWait': 0, @@ -155,7 +175,32 @@ ''': "'" }; - /** Used to determine if values are of the language type Object */ + /** + * Used to convert latin-1 supplement letters to basic latin (ASCII) letters. + * See [Wikipedia](http://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * for more details. + */ + var deburredLetters = { + '\xC0': 'A', '\xC1': 'A', '\xC2': 'A', '\xC3': 'A', '\xC4': 'A', '\xC5': 'A', + '\xE0': 'a', '\xE1': 'a', '\xE2': 'a', '\xE3': 'a', '\xE4': 'a', '\xE5': 'a', + '\xC7': 'C', '\xE7': 'c', + '\xD0': 'D', '\xF0': 'd', + '\xC8': 'E', '\xC9': 'E', '\xCA': 'E', '\xCB': 'E', + '\xE8': 'e', '\xE9': 'e', '\xEA': 'e', '\xEB': 'e', + '\xCC': 'I', '\xCD': 'I', '\xCE': 'I', '\xCF': 'I', + '\xEC': 'i', '\xED': 'i', '\xEE': 'i', '\xEF': 'i', + '\xD1': 'N', '\xF1': 'n', + '\xD2': 'O', '\xD3': 'O', '\xD4': 'O', '\xD5': 'O', '\xD6': 'O', '\xD8': 'O', + '\xF2': 'o', '\xF3': 'o', '\xF4': 'o', '\xF5': 'o', '\xF6': 'o', '\xF8': 'o', + '\xD9': 'U', '\xDA': 'U', '\xDB': 'U', '\xDC': 'U', + '\xF9': 'u', '\xFA': 'u', '\xFB': 'u', '\xFC': 'u', + '\xDD': 'Y', '\xFD': 'y', '\xFF': 'y', + '\xC6': 'AE', '\xE6': 'ae', + '\xDE': 'Th', '\xFE': 'th', + '\xDF': 'ss', '\xD7': ' ', '\xF7': ' ' + }; + + /** Used to determine if values are of the language type `Object` */ var objectTypes = { 'function': true, 'object': true @@ -167,7 +212,6 @@ "'": "'", '\n': 'n', '\r': 'r', - '\t': 't', '\u2028': 'u2028', '\u2029': 'u2029' }; @@ -192,21 +236,33 @@ /*--------------------------------------------------------------------------*/ + /** + * Used by `_.defaults` to customize its `_.assign` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function assignDefaults(objectValue, sourceValue) { + return typeof objectValue == 'undefined' ? sourceValue : objectValue; + } + /** * The base implementation of `compareAscending` used to compare values and * sort them in ascending order without guaranteeing a stable sort. * * @private - * @param {*} a The value to compare to `b`. - * @param {*} b The value to compare to `a`. - * @returns {number} Returns the sort order indicator for `a`. + * @param {*} value The value to compare to `other`. + * @param {*} other The value to compare to `value`. + * @returns {number} Returns the sort order indicator for `value`. */ - function baseCompareAscending(a, b) { - if (a !== b) { - if (a > b || typeof a == 'undefined') { + function baseCompareAscending(value, other) { + if (value !== other) { + if (value > other || typeof value == 'undefined') { return 1; } - if (a < b || typeof b == 'undefined') { + if (value < other || typeof other == 'undefined') { return -1; } } @@ -220,7 +276,7 @@ * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, @@ -248,22 +304,24 @@ } /** - * Used by `_.max` and `_.min` as the default callback when a given - * collection is a string value. + * Used by `_.max` and `_.min` as the default callback when a given collection + * is a string value. * * @private - * @param {string} value The character to inspect. - * @returns {number} Returns the code unit of given character. + * @param {string} string The string to inspect. + * @returns {number} Returns the code unit of the first character of the string. */ - function charAtCallback(value) { - return value.charCodeAt(0); + function charAtCallback(string) { + return string.charCodeAt(0); } /** - * Gets the index of the first character of `string` that is not found in `chars`. + * Used by `_.trim` and `_.trimLeft` to get the index of the first character + * of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. + * @param {string} chars The characters to find. * @returns {number} Returns the index of the first character not found in `chars`. */ function charsLeftIndex(string, chars) { @@ -279,10 +337,12 @@ } /** - * Gets the index of the last character of `string` that is not found in `chars`. + * Used by `_.trim` and `_.trimRight` to get the index of the last character + * of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. + * @param {string} chars The characters to find. * @returns {number} Returns the index of the last character not found in `chars`. */ function charsRightIndex(string, chars) { @@ -296,149 +356,121 @@ } /** - * Used by `sortBy` to compare transformed elements of a collection and stable + * Used by `_.sortBy` to compare transformed elements of a collection and stable * sort them in ascending order. * * @private - * @param {Object} a The object to compare to `b`. - * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator for `a`. + * @param {Object} object The object to compare to `other`. + * @param {Object} other The object to compare to `object`. + * @returns {number} Returns the sort order indicator for `object`. */ - function compareAscending(a, b) { - return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; } /** - * Used by `sortBy` to compare multiple properties of each element in a + * Used by `_.sortBy` to compare multiple properties of each element in a * collection and stable sort them in ascending order. * * @private - * @param {Object} a The object to compare to `b`. - * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator for `a`. + * @param {Object} object The object to compare to `other`. + * @param {Object} other The object to compare to `object`. + * @returns {number} Returns the sort order indicator for `object`. */ - function compareMultipleAscending(a, b) { - var ac = a.criteria, - bc = b.criteria, - index = -1, - length = ac.length; + function compareMultipleAscending(object, other) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length; while (++index < length) { - var result = baseCompareAscending(ac[index], bc[index]); + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); if (result) { return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to provided the same value - // for `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provide the same value + // for `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See https://code.google.com/p/v8/issues/detail?id=90 - return a.index - b.index; + return object.index - other.index; } /** - * Used by `escape` to convert characters to HTML entities. + * Creates a function that produces compound words out of the words in a + * given string. * * @private - * @param {string} match The matched character to escape. - * @returns {string} Returns the escaped character. + * @param {Function} callback The function called to combine each word. + * @returns {Function} Returns the new compounder function. */ - function escapeHtmlChar(match) { - return htmlEscapes[match]; - } + function createCompounder(callback) { + return function(string) { + var index = -1, + words = string != null && String(string).replace(reLatin1, deburrLetter).match(reWords), + length = words ? words.length : 0, + result = ''; - /** - * Used by `template` to escape characters for inclusion in compiled - * string literals. - * - * @private - * @param {string} match The matched character to escape. - * @returns {string} Returns the escaped character. - */ - function escapeStringChar(match) { - return '\\' + stringEscapes[match]; + while (++index < length) { + result = callback(result, words[index], index, words); + } + return result; + }; } /** - * Checks if `value` is a DOM node in IE < 9. + * Used by `createCompounder` to convert latin-1 supplement letters to basic + * latin (ASCII) letters. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`. + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. */ - function isNode(value) { - // IE < 9 presents DOM nodes as `Object` objects except they have `toString` - // methods that are `typeof` "string" and still can coerce nodes to strings - return typeof value.toString != 'function' && typeof (value + '') == 'string'; + function deburrLetter(letter) { + return deburredLetters[letter]; } /** - * A fallback implementation of `trim` to remove leading and trailing - * whitespace or specified characters from `string`. + * Used by `_.escape` to convert characters to HTML entities. * * @private - * @param {string} string The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @returns {string} Returns the trimmed string. + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. */ - function shimTrim(string, chars) { - string = string == null ? '' : String(string); - if (!string) { - return string; - } - if (chars == null) { - return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); - } - chars = String(chars); - return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; } /** - * A fallback implementation of `trimLeft` to remove leading whitespace or - * specified characters from `string`. + * Used by `_.template` to escape characters for inclusion in compiled + * string literals. * * @private - * @param {string} string The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @returns {string} Returns the trimmed string. + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. */ - function shimTrimLeft(string, chars) { - string = string == null ? '' : String(string); - if (!string) { - return string; - } - if (chars == null) { - return string.slice(trimmedLeftIndex(string)) - } - chars = String(chars); - return string.slice(charsLeftIndex(string, chars)); + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; } /** - * A fallback implementation of `trimRight` to remove trailing whitespace or - * specified characters from `string`. + * Checks if `value` is a DOM node in IE < 9. * * @private - * @param {string} string The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @returns {string} Returns the trimmed string. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM node, else `false`. */ - function shimTrimRight(string, chars) { - string = string == null ? '' : String(string); - if (!string) { - return string; - } - if (chars == null) { - return string.slice(0, trimmedRightIndex(string) + 1) - } - chars = String(chars); - return string.slice(0, charsRightIndex(string, chars) + 1); + function isNode(value) { + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings + return typeof value.toString != 'function' && typeof (value + '') == 'string'; } /** - * Gets the index of the first non-whitespace character of `string`. + * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace + * character of `string`. * * @private * @param {string} string The string to inspect. @@ -459,7 +491,8 @@ } /** - * Gets the index of the last non-whitespace character of `string`. + * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace + * character of `string`. * * @private * @param {string} string The string to inspect. @@ -478,20 +511,20 @@ } /** - * Used by `unescape` to convert HTML entities to characters. + * Used by `_.unescape` to convert HTML entities to characters. * * @private - * @param {string} match The matched character to unescape. + * @param {string} chr The matched character to unescape. * @returns {string} Returns the unescaped character. */ - function unescapeHtmlChar(match) { - return htmlUnescapes[match]; + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; } /*--------------------------------------------------------------------------*/ /** - * Create a new `lodash` function using the given context object. + * Create a new `lodash` function using the given `context` object. * * @static * @memberOf _ @@ -528,17 +561,23 @@ /** Used to detect DOM support */ var document = (document = context.window) && document.document; - /** Used to restore the original `_` reference in `noConflict` */ + /** Used to restore the original `_` reference in `_.noConflict` */ var oldDash = context._; - /** Used to resolve the internal [[Class]] of values */ + /** + * Used as the maximum length of an array-like object. + * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + */ + var maxSafeInteger = Math.pow(2, 53) - 1; + + /** Used to resolve the internal `[[Class]]` of values */ var toString = objectProto.toString; /** Used to detect if a method is native */ var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + escapeRegExp(toString) + .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method shortcuts */ @@ -555,7 +594,7 @@ splice = arrayRef.splice, unshift = arrayRef.unshift; - /** Used to set meta data on functions */ + /** Used to set metadata on functions */ var defineProperty = (function() { // IE 8 only accepts DOM elements try { @@ -577,12 +616,9 @@ nativeMin = Math.min, nativeNow = isNative(nativeNow = Date.now) && nativeNow, nativeParseInt = context.parseInt, - nativeRandom = Math.random, - nativeTrim = isNative(nativeTrim = stringProto.trim) && !nativeTrim.call(whitespace) && nativeTrim, - nativeTrimLeft = isNative(nativeTrimLeft = stringProto.trimLeft) && !nativeTrimLeft.call(whitespace) && nativeTrimLeft, - nativeTrimRight = isNative(nativeTrimRight = stringProto.trimRight) && !nativeTrimRight.call(whitespace) && nativeTrimRight; + nativeRandom = Math.random; - /** Used to lookup a built-in constructor by [[Class]] */ + /** Used to lookup built-in constructors by `[[Class]]` */ var ctorByClass = {}; ctorByClass[arrayClass] = Array; ctorByClass[boolClass] = Boolean; @@ -593,7 +629,7 @@ ctorByClass[regexpClass] = RegExp; ctorByClass[stringClass] = String; - /** Used to avoid iterating non-enumerable properties in IE < 9 */ + /** Used to avoid iterating over non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true }; @@ -626,18 +662,18 @@ * implicitly or explicitly included in the build. * * The chainable wrapper functions are: - * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, + * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, * `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`, * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, - * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, - * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, - * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, - * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, - * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, - * and `zip` + * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, + * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, + * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, + * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, + * `xor`, and `zip` * * The non-chainable wrapper functions are: * `capitalize`, `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, @@ -645,10 +681,10 @@ * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, * `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, * `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, - * `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `now`, - * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, - * `size`, `some`, `sortedIndex`, `runInContext`, `template`, `trim`, - * `trimLeft`, `trimRight`, `unescape`, `uniqueId`, and `value` + * `isUndefined`, `join`, `lastIndexOf`, `noConflict`, `now`, `parseInt`, + * `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`, + * `sortedIndex`, `runInContext`, `template`, `trim`, `trimLeft`, `trimRight`, + * `unescape`, `uniqueId`, and `value` * * The wrapper functions `first`, `last`, and `sample` return wrapped values * when `n` is provided, otherwise they return unwrapped values. @@ -693,7 +729,7 @@ * * @private * @param {*} value The value to wrap in a `lodash` instance. - * @param {boolean} [chainAll=false] A flag to enable chaining for all methods + * @param {boolean} [chainAll=false] A flag to enable chaining for all methods. * @returns {Object} Returns a `lodash` instance. */ function lodashWrapper(value, chainAll) { @@ -712,17 +748,19 @@ */ var support = lodash.support = {}; - (function() { + (function(x) { var ctor = function() { this.x = 1; }, object = { '0': 1, 'length': 1 }, props = []; ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new ctor) { props.push(key); } - for (key in arguments) { } + for (var argsKey in arguments) { } + for (var strKey in 'x') { } /** - * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9). + * Detect if the `[[Class]]` of `arguments` objects is resolvable + * (all but Firefox < 4, IE < 9). * * @memberOf _.support * @type boolean @@ -730,7 +768,8 @@ support.argsClass = toString.call(arguments) == argsClass; /** - * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5). + * Detect if `arguments` objects are `Object` objects + * (all but Narwhal and Opera < 10.5). * * @memberOf _.support * @type boolean @@ -739,20 +778,21 @@ /** * Detect if `name` or `message` properties of `Error.prototype` are - * enumerable by default. (IE < 9, Safari < 5.1) + * enumerable by default (IE < 9, Safari < 5.1). * * @memberOf _.support * @type boolean */ - support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name'); + support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || + propertyIsEnumerable.call(errorProto, 'name'); /** * Detect if `prototype` properties are enumerable by default. * * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 * (if the prototype or a property on the prototype has been set) - * incorrectly sets a function's `prototype` property [[Enumerable]] - * value to `true`. + * incorrectly sets the `[[Enumerable]]` value of a function's `prototype` + * property to `true`. * * @memberOf _.support * @type boolean @@ -761,7 +801,8 @@ /** * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). + * (all but Firefox OS certified apps, older Opera mobile browsers, and + * the PlayStation 3; forced `false` for Windows 8 apps). * * @memberOf _.support * @type boolean @@ -777,19 +818,20 @@ support.funcNames = typeof Function.name == 'string'; /** - * Detect if `arguments` object indexes are non-enumerable - * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1). + * Detect if string indexes are non-enumerable + * (IE < 9, RingoJS, Rhino, Narwhal). * * @memberOf _.support * @type boolean */ - support.nonEnumArgs = key != 0; + support.nonEnumStrings = strKey != '0'; /** - * Detect if properties shadowing those on `Object.prototype` are non-enumerable. + * Detect if properties shadowing those on `Object.prototype` are + * non-enumerable. * - * In IE < 9 an objects own properties, shadowing non-enumerable ones, are - * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug). + * In IE < 9 an object's own properties, shadowing non-enumerable ones, + * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). * * @memberOf _.support * @type boolean @@ -797,7 +839,8 @@ support.nonEnumShadows = !/valueOf/.test(props); /** - * Detect if own properties are iterated after inherited properties (all but IE < 9). + * Detect if own properties are iterated after inherited properties + * (all but IE < 9). * * @memberOf _.support * @type boolean @@ -805,13 +848,15 @@ support.ownLast = props[0] != 'x'; /** - * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * correctly. * * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` * and `splice()` functions that fail to remove the last element, `value[0]`, * of array-like objects even though the `length` property is set to `0`. * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` - * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode + * in IE 9. * * @memberOf _.support * @type boolean @@ -821,8 +866,8 @@ /** * Detect lack of support for accessing string characters by index. * - * IE < 8 can't access characters by index and IE 8 can only access - * characters by index on string literals. + * IE < 8 can't access characters by index. IE 8 can only access characters + * by index on string literals, not string objects. * * @memberOf _.support * @type boolean @@ -842,9 +887,9 @@ } /** - * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9) - * and that the JS engine errors when attempting to coerce an object to - * a string without a `toString` function. + * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9) + * and that the JS engine errors when attempting to coerce an object to a + * string without a `toString` function. * * @memberOf _.support * @type boolean @@ -854,12 +899,31 @@ } catch(e) { support.nodeClass = true; } - }(1)); + + /** + * 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 their function's formal parameters with + * associated values of `0`. + * + * @memberOf _.support + * @type boolean + */ + try { + support.nonEnumArgs = !(argsKey == '1' && hasOwnProperty.call(arguments, argsKey) && + propertyIsEnumerable.call(arguments, argsKey)); + } catch(e) { + support.nonEnumArgs = true; + } + }(0, 0)); /** - * By default, the template delimiters used by Lo-Dash are similar to those in - * embedded Ruby (ERB). Change the following template settings to use alternative - * delimiters. + * By default, the template delimiters used by Lo-Dash are similar to those + * in embedded Ruby (ERB). Change the following template settings to use + * alternative delimiters. * * @static * @memberOf _ @@ -920,88 +984,68 @@ /*--------------------------------------------------------------------------*/ /** - * The template used to create iterator functions. + * A specialized version of `_.forEach` for arrays without support for + * callback shorthands or `this` binding. * * @private - * @param {Object} data The data object used to populate the text. - * @returns {string} Returns the interpolated text. - */ - var iteratorTemplate = template( - // assign the `result` variable an initial value - 'var result = <%= init %>;\n' + - - // exit early if the first argument is not an object - "if (!isObject(object)) {\n" + - ' return result;\n' + - '}' + - - // add support for iterating over `arguments` objects if needed - '<% if (support.nonEnumArgs) { %>\n' + - 'var length = object.length;\n' + - 'if (length && isArguments(object)) {\n' + - ' key = -1;\n' + - ' while (++key < length) {\n' + - " key += '';\n" + - ' <%= loop %>;\n' + - ' }\n' + - ' return result;\n' + - '}' + - '<% } %>' + - - // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari - '<% if (support.enumPrototypes) { %>\n' + - "var skipProto = typeof object == 'function';\n" + - '<% } %>' + - - // avoid iterating over `Error.prototype` properties in older IE and Safari - '<% if (support.enumErrorProps) { %>\n' + - 'var skipErrorProps = object === errorProto || object instanceof Error;\n' + - '<% } %>' + - - // define conditions used in the loop - '<%' + - 'var conditions = [];\n' + - "if (support.enumPrototypes) { conditions.push('!(skipProto && key == \\'prototype\\')'); }\n" + - "if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (key == \\'message\\' || key == \\'name\\'))'); }" + - '%>\n' + - - // iterate over the object - 'for (var key in object) {\n<%' + - " if (useHas) { conditions.push('hasOwnProperty.call(object, key)'); }\n" + - " if (conditions.length) { %> if (<%= conditions.join(' && ') %>) {\n <% } %>" + - ' <%= loop %>;' + - ' <% if (conditions.length) { %>\n }<% } %>\n' + - '}\n' + + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, callback) { + var index = -1, + length = array ? array.length : 0; - // Lo-Dash skips the `constructor` property when it infers it's iterating - // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` - // attribute of an existing property and the `constructor` property of a - // prototype defaults to non-enumerable. - '<% if (support.nonEnumShadows) { %>\n' + - 'if (object !== objectProto) {\n' + - " var ctor = object.constructor,\n" + - ' isProto = object === (ctor && ctor.prototype),\n' + - ' className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object),\n' + - ' nonEnum = nonEnumProps[className];\n' + - ' <% for (var index = 0; index < 7; index++) { %>\n' + - " key = '<%= shadowedProps[index] %>';\n" + - ' if ((!(isProto && nonEnum[key]) && hasOwnProperty.call(object, key))<%' + - ' if (!useHas) { %> || (!nonEnum[key] && object[key] !== objectProto[key])<% }' + - ' %>) {\n' + - ' <%= loop %>;\n' + - ' }' + - ' <% } %>\n' + - '}' + - '<% } %>\n' + - - 'return result;' - ); + while (++index < length) { + if (callback(array[index], index, array) === false) { + break; + } + } + return array; + } - /*--------------------------------------------------------------------------*/ + /** + * A specialized version of `_.forEachRight` for arrays without support for + * callback shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, callback) { + var length = array ? array.length : 0; + while (length--) { + if (callback(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.map` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, callback) { + var index = -1, + length = array ? array.length >>> 0 : 0, + result = Array(length); + + while (++index < length) { + result[index] = callback(array[index], index, array); + } + return result; + } /** * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. + * sets its metadata. * * @private * @param {Array} data The metadata array. @@ -1020,8 +1064,8 @@ // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` var index = -1, - length = arguments.length, - args = Array(length); + length = arguments.length, + args = Array(length); while (++index < length) { args[index] = arguments[index]; @@ -1045,7 +1089,7 @@ /** * The base implementation of `_.clone` without argument juggling or support - * for `thisArg` binding. + * for `this` binding. * * @private * @param {*} value The value to clone. @@ -1062,7 +1106,6 @@ return result; } } - // inspect [[Class]] var isObj = isObject(value); if (isObj) { var className = toString.call(value); @@ -1090,7 +1133,6 @@ var isArr = isArray(value); if (isDeep) { // check for circular references and return corresponding clone - var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); @@ -1124,8 +1166,8 @@ stackB.push(result); // recursively populate clone (susceptible to call stack limits) - (isArr ? baseEach : baseForOwn)(value, function(objValue, key) { - result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); + (isArr ? arrayEach : baseForOwn)(value, function(valValue, key) { + result[key] = baseClone(valValue, isDeep, callback, stackA, stackB); }); return result; @@ -1165,7 +1207,7 @@ * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. + * @returns {Function} Returns the new function. */ function baseCreateCallback(func, thisArg, argCount) { if (typeof func != 'function') { @@ -1201,8 +1243,8 @@ case 1: return function(value) { return func.call(thisArg, value); }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); + case 2: return function(value, other) { + return func.call(thisArg, value, other); }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); @@ -1216,7 +1258,7 @@ /** * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. + * sets its metadata. * * @private * @param {Array} data The metadata array. @@ -1252,14 +1294,19 @@ if (partialRightArgs) { args = composeArgsRight(partialRightArgs, partialRightHolders, args); } - if (isCurry && length < arity) { - bitmask |= PARTIAL_FLAG; - bitmask &= ~PARTIAL_RIGHT_FLAG - if (!isCurryBound) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + if (isCurry) { + var newPartialHolders = getHolders(args); + length -= newPartialHolders.length; + + if (length < arity) { + bitmask |= PARTIAL_FLAG; + bitmask &= ~PARTIAL_RIGHT_FLAG + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newArity = nativeMax(arity - length, 0); + return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, newPartialHolders]); } - var newArity = nativeMax(0, arity - length); - return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, []]); } var thisBinding = isBind ? thisArg : this; if (isBindKey) { @@ -1283,7 +1330,7 @@ * @private * @param {Array} array The array to process. * @param {Array} [values] The array of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @returns {Array} Returns the new array of filtered values. */ function baseDifference(array, values) { var length = array ? array.length : 0; @@ -1324,7 +1371,7 @@ /** * The base implementation of `_.forEach` without support for callback - * shorthands or `thisArg` binding. + * shorthands or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -1336,7 +1383,7 @@ iterable = collection, length = collection ? collection.length : 0; - if (typeof length == 'number') { + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { if (support.unindexedChars && isString(iterable)) { iterable = iterable.split(''); } @@ -1353,7 +1400,7 @@ /** * The base implementation of `_.forEachRight` without support for callback - * shorthands or `thisArg` binding. + * shorthands or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -1364,7 +1411,7 @@ var iterable = collection, length = collection ? collection.length : 0; - if (typeof length == 'number') { + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { if (support.unindexedChars && isString(iterable)) { iterable = iterable.split(''); } @@ -1379,16 +1426,41 @@ return collection; } + /** + * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey` + * without support for callback shorthands or `this` binding which iterates + * over `collection` using the provided `eachFunc`. + * + * @private + * @param {Array|Object|string} collection The collection to search. + * @param {Function} predicate The function called per iteration. + * @param {Function} eachFunc The function to iterate over the collection. + * @param {boolean} [retKey=false] A flag to indicate returning the key of + * the found element instead of the element itself. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + /** * The base implementation of `_.flatten` without support for callback - * shorthands or `thisArg` binding. + * shorthands or `this` binding. * * @private * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. - * @returns {Array} Returns a new flattened array. + * @returns {Array} Returns the new flattened array. */ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, @@ -1420,17 +1492,20 @@ } /** - * The base implementation of `_.forOwn` without support for callback - * shorthands or `thisArg` binding. + * The base implementation of `baseForIn` and `baseForOwn` which iterates + * over `object` properties returned by `keysFunc` executing the callback + * for each property. Callbacks may exit iteration early by explicitly + * returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForOwn(object, callback) { + function baseFor(object, callback, keysFunc) { var index = -1, - props = keys(object), + props = keysFunc(object), length = props.length; while (++index < length) { @@ -1443,16 +1518,17 @@ } /** - * The base implementation of `_.forOwnRight` without support for callback - * shorthands or `thisArg` binding. + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForOwnRight(object, callback) { - var props = keys(object), + function baseForRight(object, callback, keysFunc) { + var props = keysFunc(object), length = props.length; while (length--) { @@ -1465,137 +1541,190 @@ } /** - * The base implementation of `_.isEqual`, without support for `thisArg` binding, - * that allows partial "_.where" style comparisons. + * The base implementation of `_.forIn` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Object} Returns `object`. + */ + function baseForIn(object, callback) { + return baseFor(object, callback, keysIn); + } + + /** + * The base implementation of `_.forOwn` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, callback) { + return baseFor(object, callback, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, callback) { + return baseForRight(object, callback, keys); + } + + /** + * The base implementation of `_.isEqual`, without support for `thisArg` + * binding, that allows partial "_.where" style comparisons. * * @private - * @param {*} a The value to compare. - * @param {*} b The other value to compare. + * @param {*} value The value to compare to `other`. + * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `a` objects. - * @param {Array} [stackB=[]] Tracks traversed `b` objects. + * @param {Array} [stackA=[]] Tracks traversed `value` objects. + * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ - function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { + function baseIsEqual(value, other, callback, isWhere, stackA, stackB) { if (callback) { - var result = callback(a, b); + var result = callback(value, other); if (typeof result != 'undefined') { return !!result; } } // exit early for identical values - if (a === b) { + if (value === other) { // treat `+0` vs. `-0` as not equal - return a !== 0 || (1 / a == 1 / b); + return value !== 0 || (1 / value == 1 / other); } - var type = typeof a, - otherType = typeof b; + var valType = typeof value, + othType = typeof other; // exit early for unlike primitive values - if (a === a && (a == null || b == null || - (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { + if (value === value && (value == null || other == null || + (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { return false; } - // compare [[Class]] names - var className = toString.call(a), - otherClass = toString.call(b); + var valClass = toString.call(value), + othClass = toString.call(other), + valIsArg = valClass == argsClass, + othIsArg = othClass == argsClass; - if (className == argsClass) { - className = objectClass; + if (valIsArg) { + valClass = objectClass; } - if (otherClass == argsClass) { - otherClass = objectClass; + if (othIsArg) { + othClass = objectClass; } - if (className != otherClass) { + if (valClass != othClass) { return false; } - switch (className) { + switch (valClass) { case boolClass: case dateClass: // coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +a == +b; + return +value == +other; case numberClass: // treat `NaN` vs. `NaN` as equal - return (a != +a) - ? b != +b + return (value != +value) + ? other != +other // but treat `-0` vs. `+0` as not equal - : (a == 0 ? (1 / a == 1 / b) : a == +b); + : (value == 0 ? (1 / value == 1 / other) : value == +other); case regexpClass: case stringClass: // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) // treat string primitives and their corresponding object instances as equal - return a == String(b); + return value == String(other); } - var isArr = className == arrayClass; + var isArr = valClass == arrayClass; if (!isArr) { + // exit for functions and DOM nodes + if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) { + return false; + } // unwrap any `lodash` wrapped values - var aWrapped = hasOwnProperty.call(a, '__wrapped__'), - bWrapped = hasOwnProperty.call(b, '__wrapped__'); + var valWrapped = hasOwnProperty.call(value, '__wrapped__'), + othWrapped = hasOwnProperty.call(other, '__wrapped__'); - if (aWrapped || bWrapped) { - return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); + if (valWrapped || othWrapped) { + return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, callback, isWhere, stackA, stackB); } - // exit for functions and DOM nodes - if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) { - return false; + if (!support.argsObject) { + valIsArg = isArguments(value); + othIsArg = isArguments(other); } - // in older versions of Opera, `arguments` objects have `Array` constructors - var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor, - ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor; - - // non `Object` object instances with different constructors are not equal - if (ctorA != ctorB && - !(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) && - !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && - ('constructor' in a && 'constructor' in b) - ) { + var hasValCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), + hasOthCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); + + if (hasValCtor != hasOthCtor) { return false; } + if (!hasValCtor) { + // in older versions of Opera, `arguments` objects have `Array` constructors + var valCtor = valIsArg ? Object : value.constructor, + othCtor = othIsArg ? Object : other.constructor; + + // non `Object` object instances with different constructors are not equal + if (valCtor != othCtor && + !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && + ('constructor' in value && 'constructor' in other) + ) { + return false; + } + } } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) - var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { - if (stackA[length] == a) { - return stackB[length] == b; + if (stackA[length] == value) { + return stackB[length] == other; } } var size = 0; result = true; - // add `a` and `b` to the stack of traversed objects - stackA.push(a); - stackB.push(b); + // add `value` and `other` to the stack of traversed objects + stackA.push(value); + stackB.push(other); // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { // compare lengths to determine if a deep comparison is necessary - length = a.length; - size = b.length; + length = value.length; + size = other.length; result = size == length; if (result || isWhere) { // deep compare the contents, ignoring non-numeric properties while (size--) { var index = length, - value = b[size]; + othValue = other[size]; if (isWhere) { while (index--) { - if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { + if ((result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB))) { break; } } - } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { + if (!result) { + break; + } + } else if (!(result = baseIsEqual(value[size], othValue, callback, isWhere, stackA, stackB))) { break; } } @@ -1604,20 +1733,20 @@ else { // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` // which, in this case, is more costly - baseForIn(b, function(value, key, b) { - if (hasOwnProperty.call(b, key)) { + baseForIn(other, function(othValue, key, other) { + if (hasOwnProperty.call(other, key)) { // count the number of properties. size++; // deep compare each property value. - return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); + return (result = hasOwnProperty.call(value, key) && baseIsEqual(value[key], othValue, callback, isWhere, stackA, stackB)); } }); if (result && !isWhere) { // ensure both objects have the same number of properties - baseForIn(a, function(value, key, a) { - if (hasOwnProperty.call(a, key)) { - // `size` will be `-1` if `a` has more properties than `b` + baseForIn(value, function(valValue, key, value) { + if (hasOwnProperty.call(value, key)) { + // `size` will be `-1` if `value` has more properties than `other` return (result = --size > -1); } }); @@ -1631,7 +1760,7 @@ /** * The base implementation of `_.merge` without argument juggling or support - * for `thisArg` binding. + * for `this` binding. * * @private * @param {Object} object The destination object. @@ -1641,7 +1770,7 @@ * @param {Array} [stackB=[]] Associates values with source counterparts. */ function baseMerge(object, source, callback, stackA, stackB) { - (isArray(source) ? baseEach : baseForOwn)(source, function(source, key) { + (isArray(source) ? arrayEach : baseForOwn)(source, function(source, key) { var found, isArr, result = source, @@ -1701,7 +1830,7 @@ * @private * @param {number} min The minimum possible value. * @param {number} max The maximum possible value. - * @returns {number} Returns a random number. + * @returns {number} Returns the random number. */ function baseRandom(min, max) { return min + floor(nativeRandom() * (max - min + 1)); @@ -1709,13 +1838,13 @@ /** * The base implementation of `_.uniq` without support for callback shorthands - * or `thisArg` binding. + * or `this` binding. * * @private * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. - * @returns {Array} Returns a duplicate-value-free array. + * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, isSorted, callback) { var length = array ? array.length : 0; @@ -1768,15 +1897,37 @@ return result; } + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * returned by `keysFunc`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, keysFunc) { + var index = -1, + props = keysFunc(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private - * @param {Array} partialArg An array of arguments to prepend to those provided. + * @param {Array} partialArgs An array of arguments to prepend to those provided. * @param {Array} partialHolders An array of `partialArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. - * @returns {Array} Returns a new array of composed arguments. + * @returns {Array} Returns the new array of composed arguments. */ function composeArgs(partialArgs, partialHolders, args) { var holdersLength = partialHolders.length, @@ -1803,10 +1954,10 @@ * is tailored for `_.partialRight`. * * @private - * @param {Array} partialRightArg An array of arguments to append to those provided. + * @param {Array} partialRightArgs An array of arguments to append to those provided. * @param {Array} partialHolders An array of `partialRightArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. - * @returns {Array} Returns a new array of composed arguments. + * @returns {Array} Returns the new array of composed arguments. */ function composeArgsRight(partialRightArgs, partialRightHolders, args) { var holdersIndex = -1, @@ -1831,22 +1982,22 @@ } /** - * Creates a function that aggregates a collection, creating an object or - * array composed from the results of running each element of the collection - * through a callback. The given `setter` function sets the keys and values - * of the composed object or array. + * Creates a function that aggregates a collection, creating an accumulator + * object composed from the results of running each element in the collection + * through a callback. The given setter function sets the keys and values of + * the accumulator object. If `initializer` is provided will be used to + * initialize the accumulator object. * * @private - * @param {Function} setter The setter function. - * @param {boolean} [retArray=false] A flag to indicate that the aggregator - * function should return an array. + * @param {Function} setter The function to set keys and values of the accumulator object. + * @param {Function} [initializer] The function to initialize the accumulator object. * @returns {Function} Returns the new aggregator function. */ - function createAggregator(setter, retArray) { + function createAggregator(setter, initializer) { return function(collection, callback, thisArg) { - var result = retArray ? [[], []] : {}; - + var result = initializer ? initializer() : {}; callback = lodash.createCallback(callback, thisArg, 3); + if (isArray(collection)) { var index = -1, length = collection.length; @@ -1869,7 +2020,7 @@ * * @private * @param {Array} [array=[]] The array to search. - * @returns {Object} Returns the cache object. + * @returns {Object} Returns the new cache object. */ var createCache = Set && function(array) { var cache = new Set, @@ -1883,8 +2034,31 @@ }; /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. + * Creates the pad required for `string` based on the given padding length. + * The `chars` string may be truncated if the number of padding characters + * exceeds the padding length. + * + * @private + * @param {string} string The string to create padding for. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the pad for `string`. + */ + function createPad(string, length, chars) { + var strLength = string.length; + length = +length; + + if (strLength >= length || !nativeIsFinite(length)) { + return ''; + } + var padLength = length - strLength; + chars = chars == null ? ' ' : String(chars); + return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + } + + /** + * Creates a function that either curries or invokes `func` with an optional + * `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to reference. @@ -1902,18 +2076,16 @@ * provided to the new function. * @param {Array} [partialRightArgs] An array of arguments to append to those * provided to the new function. - * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. - * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ - function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders) { + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isPartial = bitmask & PARTIAL_FLAG, isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (!isBindKey && !isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } if (isPartial && !partialArgs.length) { bitmask &= ~PARTIAL_FLAG; @@ -1969,17 +2141,17 @@ data[1] |= bitmask; return createWrapper.apply(null, data); } - if (arity == null) { - arity = isBindKey ? 0 : func.length; - } else if (arity < 0) { - arity = 0; - } if (isPartial) { - partialHolders = getHolders(partialArgs); + var partialHolders = getHolders(partialArgs); } if (isPartialRight) { - partialRightHolders = getHolders(partialRightArgs); + var partialRightHolders = getHolders(partialRightArgs); + } + if (arity == null) { + arity = isBindKey ? 0 : func.length; } + arity = nativeMax(arity, 0); + // fast path for `_.bind` data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders]; return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) @@ -1988,40 +2160,11 @@ } /** - * Creates compiled iteration functions. - * - * @private - * @param {Object} [options] The compile options object. - * @param {string} [options.args] A comma separated string of iteration function arguments. - * @param {string} [options.init] The string representation of the initial `result` value. - * @param {string} [options.loop] Code to execute in the object loop. - * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop. - * @returns {Function} Returns the compiled function. - */ - function createIterator(options) { - options.shadowedProps = shadowedProps; - options.support = support; - - // create the function factory - var factory = Function( - 'errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, ' + - 'nonEnumProps, stringClass, stringProto, toString', - 'return function(' + options.args + ') {\n' + iteratorTemplate(options) + '\n}' - ); - - // return the compiled function - return factory( - errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, - nonEnumProps, stringClass, stringProto, toString - ); - } - - /** - * Finds the indexes of all placeholder elements in a given array. + * Finds the indexes of all placeholder elements in `array`. * * @private * @param {Array} array The array to inspect. - * @returns {Array} Returns a new array of placeholder indexes. + * @returns {Array} Returns the new array of placeholder indexes. */ function getHolders(array) { var index = -1, @@ -2038,15 +2181,15 @@ /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized this method returns the custom method, otherwise it returns + * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. * * @private * @returns {Function} Returns the "indexOf" function. */ function getIndexOf() { - var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result; - return result; + var result = lodash.indexOf || indexOf; + return result === indexOf ? baseIndexOf : result; } /** @@ -2054,7 +2197,7 @@ * * @private * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. */ function isNative(value) { return typeof value == 'function' && reNative.test(fnToString.call(value)); @@ -2073,10 +2216,9 @@ }; /** - * A fallback implementation of `isPlainObject` which checks if a given value - * is an object created by the `Object` constructor, assuming objects created - * by the `Object` constructor have no inherited enumerable properties and that - * there are no `Object.prototype` extensions. + * A fallback implementation of `_.isPlainObject` which checks if `value` + * is an object created by the `Object` constructor or has a `[[Prototype]]` + * of `null`. * * @private * @param {*} value The value to check. @@ -2086,7 +2228,7 @@ var ctor, result; - // avoid non Object objects, `arguments` objects, and DOM elements + // avoid non `Object` objects, `arguments` objects, and DOM elements if (!(value && toString.call(value) == objectClass) || (!hasOwnProperty.call(value, 'constructor') && (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) || @@ -2113,126 +2255,242 @@ return typeof result == 'undefined' || hasOwnProperty.call(value, result); } + /** + * A fallback implementation of `Object.keys` which creates an array of the + * own enumerable property names of `object`. + * + * @private + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. + */ + function shimKeys(object) { + var keyIndex, + index = -1, + props = keysIn(object), + length = props.length, + objLength = length && object.length, + maxIndex = objLength - 1, + result = []; + + var allowIndexes = typeof objLength == 'number' && objLength > 0 && + (isArray(object) || (support.nonEnumArgs && isArguments(object)) || + (support.nonEnumStrings && isString(object))); + + while (++index < length) { + var key = props[index]; + if ((allowIndexes && (keyIndex = +key, keyIndex > -1 && keyIndex <= maxIndex && keyIndex % 1 == 0)) || + hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + /*--------------------------------------------------------------------------*/ /** - * Checks if `value` is an `arguments` object. + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are all falsey. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`. + * @category Arrays + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. * @example * - * (function() { return _.isArguments(arguments); })(1, 2, 3); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] */ - function isArguments(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == argsClass || false; - } - // fallback for environments that can't detect `arguments` objects by [[Class]] - if (!support.argsClass) { - isArguments = function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false; - }; - } + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } /** - * The base implementation of `_.forIn` without support for callback - * shorthands or `thisArg` binding. + * Creates an array excluding all values of the provided arrays using strict + * equality for comparisons, i.e. `===`. * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {Object} Returns `object`. + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {...Array} [values] The arrays of values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.difference([1, 2, 3], [5, 2, 10]); + * // => [1, 3] */ - var baseForIn = createIterator({ - 'args': 'object, callback', - 'init': 'object', - 'loop': 'if (callback(object[key], key, object) === false) {\n return result;\n }', - 'useHas': false - }); + function difference() { + var index = -1, + length = arguments.length; + + while (++index < length) { + var value = arguments[index]; + if (isArray(value) || isArguments(value)) { + break; + } + } + return baseDifference(arguments[index], baseFlatten(arguments, true, true, ++index)); + } /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. + * Creates a slice of `array` with `n` elements dropped from the beginning. * - * @private + * @static + * @memberOf _ * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. + * @category Arrays + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3], 1); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] */ - var shimKeys = createIterator({ - 'args': 'object', - 'init': '[]', - 'loop': 'result.push(key)', - 'useHas': true - }); - - /*--------------------------------------------------------------------------*/ + var drop = rest; /** - * Creates an array with all falsey values removed. The values `false`, `null`, - * `0`, `""`, `undefined`, and `NaN` are all falsey. + * Creates a slice of `array` with `n` elements dropped from the end. * * @static * @memberOf _ + * @type Function * @category Arrays - * @param {Array} array The array to compact. - * @returns {Array} Returns a new array of filtered values. + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @returns {Array} Returns the slice of `array`. * @example * - * _.compact([0, 1, false, 2, '', 3]); + * _.dropRight([1, 2, 3], 1); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); * // => [1, 2, 3] */ - function compact(array) { - var index = -1, - length = array ? array.length : 0, - resIndex = 0, - result = []; + var dropRight = initial; - while (++index < length) { - var value = array[index]; - if (value) { - result[resIndex++] = value; - } - } - return result; - } + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements will be dropped until the predicate returns falsey. The predicate + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `predicate` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=identity] The function called + * per element. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRightWhile([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [1] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate' }, + * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.dropRightWhile(characters, 'blocked'), 'name'); + * // => ['barney'] + * + * // using "_.where" callback shorthand + * _.pluck(_.dropRightWhile(characters, { 'employer': 'na' }), 'name'); + * // => ['barney', 'fred'] + */ + var dropRightWhile = initial; /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements will be dropped until the predicate returns falsey. The predicate + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `predicate` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. * * @static * @memberOf _ + * @type Function * @category Arrays - * @param {Array} array The array to process. - * @param {...Array} [values] The arrays of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=identity] The function called + * per element. + * @returns {Array} Returns the slice of `array`. * @example * - * _.difference([1, 2, 3], [5, 2, 10]); - * // => [1, 3] + * _.dropWhile([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [3] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, + * { 'name': 'fred', 'employer': 'slate' }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.dropWhile(characters, 'blocked'), 'name'); + * // => ['fred', 'pebbles'] + * + * // using "_.where" callback shorthand + * _.pluck(_.dropWhile(characters, { 'employer': 'slate' }), 'name'); + * // => ['pebbles'] */ - function difference(array) { - return baseDifference(array, baseFlatten(arguments, true, true, 1)); - } + var dropWhile = rest; /** * This method is like `_.find` except that it returns the index of the first - * element that passes the callback check, instead of the element itself. + * element the predicate returns truthy for, instead of the element itself. * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -2240,10 +2498,10 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * @@ -2266,13 +2524,13 @@ * _.findIndex(characters, 'blocked'); * // => 1 */ - function findIndex(array, callback, thisArg) { + function findIndex(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0; - callback = lodash.createCallback(callback, thisArg, 3); + predicate = lodash.createCallback(predicate, thisArg, 3); while (++index < length) { - if (callback(array[index], index, array)) { + if (predicate(array[index], index, array)) { return index; } } @@ -2281,12 +2539,12 @@ /** * This method is like `_.findIndex` except that it iterates over elements - * of a `collection` from right to left. + * of a collection from right to left. * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -2294,10 +2552,10 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * @@ -2320,12 +2578,12 @@ * _.findLastIndex(characters, 'blocked'); * // => 2 */ - function findLastIndex(array, callback, thisArg) { + function findLastIndex(array, predicate, thisArg) { var length = array ? array.length : 0; - callback = lodash.createCallback(callback, thisArg, 3); + predicate = lodash.createCallback(predicate, thisArg, 3); while (length--) { - if (callback(array[length], length, array)) { + if (predicate(array[length], length, array)) { return length; } } @@ -2333,80 +2591,47 @@ } /** - * Gets the first element or first `n` elements of an array. If a callback - * is provided elements at the beginning of the array are returned as long - * as the callback returns truey. The callback is bound to `thisArg` and - * invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Gets the first element of `array`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Note: The `n` and `predicate` arguments are deprecated; replace with + * `_.take` and `_.takeWhile` respectively. * * @static * @memberOf _ - * @alias head, take + * @alias head * @category Arrays * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the first element(s) of `array`. + * @returns {*} Returns the first element of `array`. * @example * * _.first([1, 2, 3]); * // => 1 * - * // returns the first two elements - * _.first([1, 2, 3], 2); - * // => [1, 2] - * - * // returns elements from the beginning until the callback result is falsey - * _.first([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [1, 2] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, - * { 'name': 'fred', 'employer': 'slate' }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.first(characters, 'blocked'); - * // => [{ 'name': 'barney', 'employer': 'slate', 'blocked': true }] - * - * // using "_.where" callback shorthand - * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); - * // => ['barney', 'fred'] + * _.first([]); + * // => undefined */ - function first(array, callback, thisArg) { - if (typeof callback != 'number' && callback != null) { + function first(array, predicate, thisArg) { + if (typeof predicate != 'number' && predicate != null) { var index = -1, length = array ? array.length : 0, n = 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { + predicate = lodash.createCallback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) { n++; } } else { - n = callback; + n = predicate; if (n == null || thisArg) { return array ? array[0] : undefined; } } - return slice(array, 0, n > 0 ? n : 0); + return slice(array, 0, n < 0 ? 0 : n); } /** * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truey, the array will only be flattened a single level. If a callback + * is truthy, the array will only be flattened a single level. If a callback * is provided each element of the array is passed through the callback before * flattening. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). @@ -2423,11 +2648,11 @@ * @category Arrays * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {Function|Object|string} [callback] The function called per iteration. + * If a property name or object is provided it will be used to create a "_.pluck" + * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new flattened array. + * @returns {Array} Returns the new flattened array. * @example * * _.flatten([1, [2], [3, [[4]]]]); @@ -2481,7 +2706,7 @@ * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=0] The index to search from or `true` * to perform a binary search on a sorted array. - * @returns {number} Returns the index of the matched value or `-1`. + * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.indexOf([1, 2, 3, 1, 2, 3], 2); @@ -2498,7 +2723,7 @@ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (typeof fromIndex == 'number') { - fromIndex = fromIndex < 0 ? nativeMax(0, length + fromIndex) : (fromIndex || 0); + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } else if (fromIndex) { var index = sortedIndex(array, value); return (length && array[index] === value) ? index : -1; @@ -2507,73 +2732,37 @@ } /** - * Gets all but the last element or last `n` elements of an array. If a - * callback is provided elements at the end of the array are excluded from - * the result as long as the callback returns truey. The callback is bound - * to `thisArg` and invoked with three arguments; (value, index, array). + * Gets all but the last element of `array`. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Note: The `n` and `predicate` arguments are deprecated; replace with + * `_.dropRight` and `_.dropRightWhile` respectively. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @returns {Array} Returns the slice of `array`. * @example * * _.initial([1, 2, 3]); * // => [1, 2] - * - * // excludes the last two elements - * _.initial([1, 2, 3], 2); - * // => [1] - * - * // excludes elements from the end until the callback fails - * _.initial([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [1] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate' }, - * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.initial(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }] - * - * // using "_.where" callback shorthand - * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); - * // => ['barney', 'fred'] */ - function initial(array, callback, thisArg) { + function initial(array, predicate, thisArg) { var length = array ? array.length : 0; - if (typeof callback != 'number' && callback != null) { + if (typeof predicate != 'number' && predicate != null) { var index = length, n = 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { + predicate = lodash.createCallback(predicate, thisArg, 3); + while (index-- && predicate(array[index], index, array)) { n++; } } else { - n = (callback == null || thisArg) ? 1 : callback; + n = (predicate == null || thisArg) ? 1 : predicate; } - n = length - n; - return slice(array, 0, n > 0 ? n : 0); + n = length - (n || 0); + return slice(array, 0, n < 0 ? 0 : n); } /** @@ -2583,8 +2772,8 @@ * @static * @memberOf _ * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of shared values. + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of shared values. * @example * * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); @@ -2596,36 +2785,37 @@ argsLength = arguments.length, caches = [], indexOf = getIndexOf(), - prereq = createCache && indexOf === baseIndexOf, - seen = []; + prereq = createCache && indexOf === baseIndexOf; while (++argsIndex < argsLength) { var value = arguments[argsIndex]; if (isArray(value) || isArguments(value)) { args.push(value); caches.push(prereq && value.length >= 120 && - createCache(argsIndex ? args[argsIndex] : seen)); + createCache(argsIndex && value)); } } + argsLength = args.length; var array = args[0], index = -1, length = array ? array.length : 0, - result = []; + result = [], + seen = caches[0]; outer: while (++index < length) { - var cache = caches[0]; value = array[index]; - - if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) { argsIndex = argsLength; - (cache || seen).push(value); while (--argsIndex) { - cache = caches[argsIndex]; + var cache = caches[argsIndex]; if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { continue outer; } } + if (seen) { + seen.push(value); + } result.push(value); } } @@ -2633,89 +2823,46 @@ } /** - * Gets the last element or last `n` elements of an array. If a callback is - * provided elements at the end of the array are returned as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Gets the last element of `array`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Note: The `n` and `predicate` arguments are deprecated; replace with + * `_.takeRight` and `_.takeRightWhile` respectively. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the last element(s) of `array`. + * @returns {*} Returns the last element of `array`. * @example * * _.last([1, 2, 3]); * // => 3 - * - * // returns the last two elements - * _.last([1, 2, 3], 2); - * // => [2, 3] - * - * // returns elements from the end until the callback fails - * _.last([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [2, 3] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate' }, - * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.last(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.last(characters, { 'employer': 'na' }); - * // => [{ 'name': 'pebbles', 'employer': 'na', 'blocked': true }] */ - function last(array, callback, thisArg) { + function last(array, predicate, thisArg) { var length = array ? array.length : 0; - if (typeof callback != 'number' && callback != null) { + if (typeof predicate != 'number' && predicate != null) { var index = length, n = 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { + predicate = lodash.createCallback(predicate, thisArg, 3); + while (index-- && predicate(array[index], index, array)) { n++; } } else { - n = callback; + n = predicate; if (n == null || thisArg) { return array ? array[length - 1] : undefined; } } - n = length - n; - return slice(array, n > 0 ? n : 0); + n = length - (n || 0); + return slice(array, n < 0 ? 0 : n); } /** - * Gets the index at which the last occurrence of `value` is found using strict - * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used - * as the offset from the end of the collection. - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Gets the index at which the last occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, + * it is used as the offset from the end of the collection. * * @static * @memberOf _ @@ -2723,7 +2870,7 @@ * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); @@ -2736,7 +2883,7 @@ function lastIndexOf(array, value, fromIndex) { var index = array ? array.length : 0; if (typeof fromIndex == 'number') { - index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + index = (fromIndex < 0 ? nativeMax(index + fromIndex, 0) : nativeMin(fromIndex || 0, index - 1)) + 1; } while (index--) { if (array[index] === value) { @@ -2750,11 +2897,13 @@ * Removes all provided values from `array` using strict equality for * comparisons, i.e. `===`. * + * Note: Unlike `_.without`, this method mutates `array`. + * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to modify. - * @param {...*} [value] The values to remove. + * @param {...*} [values] The values to remove. * @returns {Array} Returns `array`. * @example * @@ -2783,79 +2932,74 @@ } /** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to but not including `end`. If `start` is less than `stop` a - * zero-length range is created unless a negative `step` is specified. + * Removes elements located at the given indexes and returns an array of + * removed elements. Indexes may be specified as an array of indexes or as + * individual arguments. + * + * Note: Like `_.pull`, this method mutates `array`. * * @static * @memberOf _ * @category Arrays - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns a new range array. + * @param {Array} array The array to modify. + * @param {...(number|number[])} [index] The indexes of values to remove, + * specified as individual indexes or arrays of indexes. + * @returns {Array} Returns the new array of removed elements. * @example * - * _.range(4); - * // => [0, 1, 2, 3] - * - * _.range(1, 5); - * // => [1, 2, 3, 4] - * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] - * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] + * var array = [5, 10, 15, 20]; + * var evens = _.removeAt(array, [1, 3]); * - * _.range(1, 4, 0); - * // => [1, 1, 1] + * console.log(array); + * // => [5, 15] * - * _.range(0); - * // => [] + * console.log(evens); + * // => [10, 20] */ - function range(start, end, step) { - start = +start || 0; - step = typeof step == 'number' ? step : (+step || 1); - - if (end == null) { - end = start; - start = 0; - } - // use `Array(length)` so engines like Chakra and V8 avoid slower modes - // http://youtu.be/XAqIpGU8ZZk#t=17m25s - var index = -1, - length = nativeMax(0, ceil((end - start) / (step || 1))), + function pullAt(array) { + var previous, + index = -1, + removals = baseFlatten(arguments, true, false, 1), + length = removals.length, result = Array(length); while (++index < length) { - result[index] = start; - start += step; + result[index] = array[removals[index]]; + } + removals.sort(baseCompareAscending); + while (length--) { + var removal = removals[length]; + if (removal != previous) { + splice.call(array, removal, 1); + previous = removal; + } } return result; } /** - * Removes all elements from an array that the callback returns truey for - * and returns an array of removed elements. The callback is bound to `thisArg` + * Removes all elements from `array` that the predicate returns truthy for + * and returns an array of removed elements. The predicate is bound to `thisArg` * and invoked with three arguments; (value, index, array). * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * + * Note: Unlike `_.filter`, this method mutates `array`. + * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to modify. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of removed elements. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the array of removed elements. * @example * * var array = [1, 2, 3, 4, 5, 6]; @@ -2867,15 +3011,15 @@ * console.log(evens); * // => [2, 4, 6] */ - function remove(array, callback, thisArg) { + function remove(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0, result = []; - callback = lodash.createCallback(callback, thisArg, 3); + predicate = lodash.createCallback(predicate, thisArg, 3); while (++index < length) { var value = array[index]; - if (callback(value, index, array)) { + if (predicate(value, index, array)) { result.push(value); splice.call(array, index--, 1); length--; @@ -2885,132 +3029,36 @@ } /** - * Removes elements located at the given indexes and returns an array of - * removed elements. A hybrid of "_.remove" and "_.at". Indexes may be - * specified as an array of indexes or as individual arguments. - * - * @static - * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {...(number|number[])} [index] The indexes of `array` to remove - * @returns {Array} Returns a new array of removed elements. - * @example - * - * var array = [5, 10, 15, 20, 25, 30]; - * var evens = _.removeAt(array, [1, 3, 5]); - * - * console.log(array); - * // => [5, 15, 25] - * - * console.log(evens); - * // => [10, 20, 30] - * - * var greeting = ('good morning').split(''); - * var vowels = _.removeAt(greeting, 1, 2, 6, 9); - * - * console.log(greeting.join('')); - * // => 'gd mrnng' - * - * console.log(vowels.join('')); - * // => 'oooi' - */ - function removeAt(array, guard) { - var args = arguments, - index = -1, - removals = baseFlatten(args, true, false, 1), - length = removals.length; - - // enables use as a callback for functions like `_.map` - if (typeof guard == 'number' && args[2] && args[2][guard] === array) { - length = 1; - } else { - removals.sort(baseCompareAscending); - } - var result = Array(length), - adjust = -1, - removal, previous; - while(++index < length) { - removal = removals[index]; - if (removal === previous) { - result[index] = result[index - 1]; - } else { - previous = removal; - result[index] = splice.call(array, removal - ++adjust, 1)[0]; - } - } - return result; - } - - - /** - * The opposite of `_.initial`; this method gets all but the first element or - * first `n` elements of an array. If a callback function is provided elements - * at the beginning of the array are excluded from the result as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Gets all but the first element of `array`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Note: The `n` and `predicate` arguments are deprecated; replace with + * `_.drop` and `_.dropWhile` respectively. * * @static * @memberOf _ - * @alias drop, tail + * @alias tail * @category Arrays * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @returns {Array} Returns the slice of `array`. * @example * * _.rest([1, 2, 3]); * // => [2, 3] - * - * // excludes the first two elements - * _.rest([1, 2, 3], 2); - * // => [3] - * - * // excludes elements from the beginning until the callback fails - * _.rest([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [3] - * - * var characters = [ - * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, - * { 'name': 'fred', 'employer': 'slate' }, - * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.rest(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.rest(characters, { 'employer': 'slate' }); - * // => [{ 'name': 'pebbles', 'employer': 'na', 'blocked': true }] */ - function rest(array, callback, thisArg) { - if (typeof callback != 'number' && callback != null) { + function rest(array, predicate, thisArg) { + if (typeof predicate != 'number' && predicate != null) { var index = -1, length = array ? array.length : 0, n = 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { + predicate = lodash.createCallback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) { n++; } - } else if (callback == null || thisArg) { + } else if (predicate == null || thisArg) { n = 1; } else { - n = callback > 0 ? callback : 0; + n = predicate < 0 ? 0 : predicate; } return slice(array, n); } @@ -3027,27 +3075,25 @@ * @param {Array} array The array to slice. * @param {number} [start=0] The start index. * @param {number} [end=array.length] The end index. - * @returns {Array} Returns the new array. + * @returns {Array} Returns the slice of `array`. */ function slice(array, start, end) { var index = -1, length = array ? array.length : 0; - if (typeof start == 'undefined') { - start = 0; - } else if (start < 0) { + start = typeof start == 'undefined' ? 0 : (+start || 0); + if (start < 0) { start = nativeMax(length + start, 0); } else if (start > length) { start = length; } - if (typeof end == 'undefined') { - end = length; - } else if (end < 0) { + end = typeof end == 'undefined' ? length : (+end || 0); + if (end < 0) { end = nativeMax(length + end, 0); } else if (end > length) { end = length; } - length = end - start || 0; + length = start > end ? 0 : (end - start); var result = Array(length); while (++index < length) { @@ -3077,7 +3123,7 @@ * @param {*} value The value to evaluate. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. @@ -3087,17 +3133,17 @@ * // => 2 * * var dict = { - * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'forty': 40, 'fifty': 50 } * }; * * // using `callback` - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'forty', function(word) { * return dict.wordToNumber[word]; * }); * // => 2 * * // using `callback` with `thisArg` - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'forty', function(word) { * return this.wordToNumber[word]; * }, dict); * // => 2 @@ -3123,6 +3169,144 @@ return low; } + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @type Function + * @category Arrays + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3], 1); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + var take = first; + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @type Function + * @category Arrays + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3], 1); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + var takeRight = last; + + /** + * Creates a slice of `array` with elements taken from the end. Elements will + * be taken until the predicate returns falsey. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `predicate` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=identity] The function called + * per element. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRightWhile([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [2, 3] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate' }, + * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.takeRightWhile(characters, 'blocked'), 'name'); + * // => ['fred', 'pebbles'] + * + * // using "_.where" callback shorthand + * _.pluck(_.takeRightWhile(characters, { 'employer': 'na' }), 'name'); + * // => ['pebbles'] + */ + var takeRightWhile = last; + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * will be taken until the predicate returns falsey. The predicate is bound + * to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is provided for `predicate` the created "_.where" style callback + * will return `true` for elements that have the properties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=identity] The function called + * per element. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeWhile([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [1, 2] + * + * var characters = [ + * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, + * { 'name': 'fred', 'employer': 'slate' }, + * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.pluck(_.takeWhile(characters, 'blocked'), 'name'); + * // => ['barney'] + * + * // using "_.where" callback shorthand + * _.pluck(_.takeWhile(characters, { 'employer': 'slate' }), 'name'); + * // => ['barney', 'fred'] + */ + var takeWhile = first; + /** * Creates an array of unique values, in order, of the provided arrays using * strict equality for comparisons, i.e. `===`. @@ -3130,8 +3314,8 @@ * @static * @memberOf _ * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of combined values. + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. * @example * * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); @@ -3143,11 +3327,11 @@ /** * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing - * `true` for `isSorted` will use a faster algorithm. If a callback is provided - * each element of `array` is passed through the callback before uniqueness - * is computed. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). + * for comparisons, i.e. `===`. If the array is sorted, providing `true` for + * `isSorted` will use a faster algorithm. If a callback is provided it will + * be executed for each value in the array to generate the criterion by which + * uniqueness is computed. The callback is bound to `thisArg` and invoked with + * three arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. @@ -3162,11 +3346,11 @@ * @category Arrays * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {Function|Object|string} [callback] The function called per iteration. + * If a property name or object is provided it will be used to create a "_.pluck" + * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a duplicate-value-free array. + * @returns {Array} Returns the new duplicate-value-free array. * @example * * _.uniq([1, 2, 1, 3, 1]); @@ -3219,26 +3403,27 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to filter. - * @param {...*} [value] The values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. * @example * * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ - function without(array) { - return baseDifference(array, slice(arguments, 1)); + function without() { + return baseDifference(arguments[0], slice(arguments, 1)); } /** * Creates an array that is the symmetric difference of the provided arrays. - * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. + * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for + * more details. * * @static * @memberOf _ * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of values. + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of values. * @example * * _.xor([1, 2, 3], [5, 2, 1, 4]); @@ -3272,8 +3457,8 @@ * @memberOf _ * @alias unzip * @category Arrays - * @param {...Array} [array] The arrays to process. - * @returns {Array} Returns a new array of grouped elements. + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the array of grouped elements. * @example * * _.zip(['fred', 'barney'], [30, 40], [true, false]); @@ -3305,8 +3490,7 @@ * @category Arrays * @param {Array} keys The array of keys. * @param {Array} [values=[]] The array of values. - * @returns {Object} Returns an object composed of the given keys and - * corresponding values. + * @returns {Object} Returns the new object. * @example * * _.zipObject(['fred', 'barney'], [30, 40]); @@ -3341,7 +3525,7 @@ * @memberOf _ * @category Chaining * @param {*} value The value to wrap. - * @returns {Object} Returns the wrapper object. + * @returns {Object} Returns the new wrapper object. * @example * * var characters = [ @@ -3358,9 +3542,7 @@ * // => 'pebbles is 1' */ function chain(value) { - value = new lodashWrapper(value); - value.__chain__ = true; - return value; + return new lodashWrapper(value, true); } /** @@ -3420,12 +3602,12 @@ } /** - * Produces the `toString` result of the wrapped value. + * Produces the result of coercing the wrapped value to a string. * * @name toString * @memberOf _ * @category Chaining - * @returns {string} Returns the string result. + * @returns {string} Returns the coerced string value. * @example * * _([1, 2, 3]).toString(); @@ -3440,7 +3622,7 @@ * * @name valueOf * @memberOf _ - * @alias value + * @alias toJSON, value * @category Chaining * @returns {*} Returns the wrapped value. * @example @@ -3454,7 +3636,6 @@ /*--------------------------------------------------------------------------*/ - /** * Creates an array of elements from the specified indexes, or keys, of the * `collection`. Indexes may be specified as individual arguments or as arrays @@ -3464,10 +3645,9 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` - * to retrieve, specified as individual indexes or arrays of indexes. - * @returns {Array} Returns a new array of elements corresponding to the - * provided indexes. + * @param {...(number|number[]|string|string[])} [keys] The keys of elements + * to pick, specified as individual keys or arrays of keys. + * @returns {Array} Returns the array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); @@ -3476,17 +3656,11 @@ * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ - function at(collection, guard) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), - length = props.length, - type = typeof guard; + function at(collection) { + var index = -1, + props = baseFlatten(arguments, true, false, 1), + length = props.length; - // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) { - length = 1; - } if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } @@ -3506,10 +3680,10 @@ * @memberOf _ * @alias include * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object|string} collection The collection to search. * @param {*} target The value to check for. * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if the `target` element is found, else `false`. + * @returns {boolean} Returns `true` if a matching element is found, else `false`. * @example * * _.contains([1, 2, 3], 1); @@ -3526,31 +3700,25 @@ */ function contains(collection, target, fromIndex) { var length = collection ? collection.length : 0; - fromIndex = typeof fromIndex == 'number' ? fromIndex : 0; - - if (typeof length == 'number') { + if (!(typeof length == 'number' && length > -1 && length <= maxSafeInteger)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); + } else { + fromIndex = 0; + } + if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { if (fromIndex >= length) { return false; } - if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { - return nativeContains - ? nativeContains.call(collection, target, fromIndex) - : collection.indexOf(target, fromIndex) > -1; - } - var indexOf = getIndexOf(); - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; - return indexOf(collection, target, fromIndex) > -1; + return nativeContains + ? nativeContains.call(collection, target, fromIndex) + : collection.indexOf(target, fromIndex) > -1; } - var index = -1, - result = false; - - baseEach(collection, function(value) { - if (++index >= fromIndex) { - return !(result = value === target); - } - }); - - return result; + var indexOf = getIndexOf(); + return indexOf(collection, target, fromIndex) > -1; } /** @@ -3573,7 +3741,7 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -3592,14 +3760,14 @@ }); /** - * Checks if the callback returns truey value for **all** elements of a - * collection. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index|key, collection). + * Checks if the predicate returns truthy for **all** elements of a collection. + * The predicate is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -3608,11 +3776,11 @@ * @alias all * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if all elements passed the callback check, + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {boolean} Returns `true` if all elements passed the predicate check, * else `false`. * @example * @@ -3632,36 +3800,36 @@ * _.every(characters, { 'age': 36 }); * // => false */ - function every(collection, callback, thisArg) { + function every(collection, predicate, thisArg) { var result = true; + predicate = lodash.createCallback(predicate, thisArg, 3); - callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { - if (!callback(collection[index], index, collection)) { + if (!predicate(collection[index], index, collection)) { return false; } } } else { baseEach(collection, function(value, index, collection) { - return (result = !!callback(value, index, collection)); + return (result = !!predicate(value, index, collection)); }); } return result; } /** - * Iterates over elements of a collection, returning an array of all elements - * the callback returns truey for. The callback is bound to `thisArg` and + * Iterates over elements of a collection returning an array of all elements + * the predicate returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -3670,11 +3838,11 @@ * @alias select * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of elements that passed the callback check. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new filtered array. * @example * * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); @@ -3693,23 +3861,23 @@ * _.filter(characters, { 'age': 36 }); * // => [{ 'name': 'barney', 'age': 36 }] */ - function filter(collection, callback, thisArg) { + function filter(collection, predicate, thisArg) { var result = []; + predicate = lodash.createCallback(predicate, thisArg, 3); - callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; - if (callback(value, index, collection)) { + if (predicate(value, index, collection)) { result.push(value); } } } else { baseEach(collection, function(value, index, collection) { - if (callback(value, index, collection)) { + if (predicate(value, index, collection)) { result.push(value); } }); @@ -3719,26 +3887,26 @@ /** * Iterates over elements of a collection, returning the first element that - * the callback returns truey for. The callback is bound to `thisArg` and + * the predicate returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ - * @alias detect, findWhere + * @alias detect * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the found element, else `undefined`. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. * @example * * var characters = [ @@ -3760,43 +3928,28 @@ * _.find(characters, 'blocked'); * // => { 'name': 'fred', 'age': 40, 'blocked': true } */ - function find(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); + function find(collection, predicate, thisArg) { if (isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - var value = collection[index]; - if (callback(value, index, collection)) { - return value; - } - } - } else { - var result; - baseEach(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result = value; - return false; - } - }); - return result; + var index = findIndex(collection, predicate, thisArg); + return index > -1 ? collection[index] : undefined; } + predicate = lodash.createCallback(predicate, thisArg, 3); + return baseFind(collection, predicate, baseEach); } /** - * This method is like `_.find` except that it iterates over elements - * of a `collection` from right to left. + * This method is like `_.find` except that it iterates over elements of a + * collection from right to left. * * @static * @memberOf _ * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the found element, else `undefined`. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. * @example * * _.findLast([1, 2, 3, 4], function(num) { @@ -3804,24 +3957,44 @@ * }); * // => 3 */ - function findLast(collection, callback, thisArg) { - var result; - - callback = lodash.createCallback(callback, thisArg, 3); - baseEachRight(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result = value; - return false; - } - }); - return result; + function findLast(collection, predicate, thisArg) { + predicate = lodash.createCallback(predicate, thisArg, 3); + return baseFind(collection, predicate, baseEachRight); } /** - * Iterates over elements of a collection, executing the callback for each - * element. The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). Callbacks may exit iteration early by - * explicitly returning `false`. + * Performs a deep comparison between each element in `collection` and the + * source object, returning the first element that has equivalent property + * values. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|string} collection The collection to search. + * @param {Object} source The object of property values to match. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var characters = [ + * { 'name': 'barney', 'age': 36, 'employer': 'slate' }, + * { 'name': 'fred', 'age': 40, 'employer': 'slate' } + * ]; + * + * _.findWhere(characters, { 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } + * + * _.findWhere(characters, { 'age': 40 }); + * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' } + */ + function findWhere(collection, source) { + return find(collection, matches(source)); + } + + /** + * Iterates over elements of a collection executing the callback for each + * element. The callback is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). Callbacks may exit iteration early by + * explicitly returning `false`. * * Note: As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` @@ -3844,24 +4017,14 @@ * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { - if (callback && typeof thisArg == 'undefined' && isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - if (callback(collection[index], index, collection) === false) { - break; - } - } - } else { - baseEach(collection, baseCreateCallback(callback, thisArg, 3)); - } - return collection; + return (callback && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, callback) + : baseEach(collection, baseCreateCallback(callback, thisArg, 3)); } /** - * This method is like `_.forEach` except that it iterates over elements - * of a `collection` from right to left. + * This method is like `_.forEach` except that it iterates over elements of + * a collection from right to left. * * @static * @memberOf _ @@ -3877,17 +4040,9 @@ * // => logs each number from right to left and returns '3,2,1' */ function forEachRight(collection, callback, thisArg) { - if (callback && typeof thisArg == 'undefined' && isArray(collection)) { - var length = collection.length; - while (length--) { - if (callback(collection[length], length, collection) === false) { - break; - } - } - } else { - baseEachRight(collection, baseCreateCallback(callback, thisArg, 3)); - } - return collection; + return (callback && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEachRight(collection, callback) + : baseEachRight(collection, baseCreateCallback(callback, thisArg, 3)); } /** @@ -3910,7 +4065,7 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -3953,23 +4108,23 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * var keys = [ + * var keyData = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * - * _.indexBy(keys, 'dir'); + * _.indexBy(keyData, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } * - * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); }); + * _.indexBy(keyData, function(object) { return String.fromCharCode(object.code); }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * - * _.indexBy(keys, function(key) { return this.fromCharCode(key.code); }, String); + * _.indexBy(keyData, function(object) { return this.fromCharCode(object.code); }, String); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } */ var indexBy = createAggregator(function(result, value, key) { @@ -3977,10 +4132,10 @@ }); /** - * Invokes the method named by `methodName` on each element in the `collection` + * Invokes the method named by `methodName` on each element in the collection * returning an array of the results of each invoked method. Additional arguments * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the `collection`. + * will be invoked for, and `this` bound to, each element in the collection. * * @static * @memberOf _ @@ -3989,7 +4144,7 @@ * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {...*} [args] Arguments to invoke the method with. - * @returns {Array} Returns a new array of the results of each invoked method. + * @returns {Array} Returns the array of results. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); @@ -3999,22 +4154,16 @@ * // => [['1', '2', '3'], ['4', '5', '6']] */ function invoke(collection, methodName) { - var index = -1, + var args = slice(arguments, 2), + index = -1, isFunc = typeof methodName == 'function', - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); + length = collection && collection.length, + result = Array(length < 0 ? 0 : length >>> 0); - if (arguments.length < 3 && isArray(collection)) { - while (++index < length) { - var value = collection[index]; - result[index] = isFunc ? methodName.call(value) : value[methodName](); - } - } else { - var args = slice(arguments, 2); - baseEach(collection, function(value) { - result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); - }); - } + baseEach(collection, function(value) { + var func = isFunc ? methodName : (value != null && value[methodName]); + result[++index] = func ? func.apply(value, args) : undefined; + }); return result; } @@ -4037,9 +4186,9 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of the results of each `callback` execution. + * @returns {Array} Returns the new mapped array. * @example * * _.map([1, 2, 3], function(num) { return num * 3; }); @@ -4058,20 +4207,17 @@ * // => ['barney', 'fred'] */ function map(collection, callback, thisArg) { - var index = -1, - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); - callback = lodash.createCallback(callback, thisArg, 3); + if (isArray(collection)) { - while (++index < length) { - result[index] = callback(collection[index], index, collection); - } - } else { - baseEach(collection, function(value, key, collection) { - result[++index] = callback(value, key, collection); - }); + return arrayMap(collection, callback, thisArg); } + var index = -1, + result = []; + + baseEach(collection, function(value, key, collection) { + result[++index] = callback(value, key, collection); + }); return result; } @@ -4093,9 +4239,9 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {Function|Object|string} [callback] The function called per iteration. + * If a property name or object is provided it will be used to create a "_.pluck" + * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the maximum value. * @example @@ -4103,6 +4249,9 @@ * _.max([4, 2, 8, 6]); * // => 8 * + * _.max([]); + * // => -Infinity + * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } @@ -4141,7 +4290,7 @@ baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); - if (current > computed) { + if (current > computed || (current === -Infinity && current === result)) { computed = current; result = value; } @@ -4168,9 +4317,9 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {Function|Object|string} [callback] The function called per iteration. + * If a property name or object is provided it will be used to create a "_.pluck" + * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the minimum value. * @example @@ -4178,6 +4327,9 @@ * _.min([4, 2, 8, 6]); * // => 2 * + * _.min([]); + * // => Infinity + * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } @@ -4216,7 +4368,7 @@ baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); - if (current < computed) { + if (current < computed || (current === Infinity && current === result)) { computed = current; result = value; } @@ -4227,14 +4379,14 @@ /** * Creates an array of elements split into two groups, the first of which - * contains elements the callback returns truey for, while the second of which - * contains elements the callback returns falsey for. The callback is bound + * contains elements the predicate returns truthy for, while the second of which + * contains elements the predicate returns falsey for. The predicate is bound * to `thisArg` and invoked with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -4242,11 +4394,11 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of grouped elements. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the array of grouped elements. * @example * * _.partition([1, 2, 3], function(num) { return num % 2; }); @@ -4271,18 +4423,17 @@ */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); - }, true); + }, function() { return [[], []]; }); /** * Retrieves the value of a specified property from all elements in the collection. * * @static * @memberOf _ - * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {string} key The name of the property to pluck. - * @returns {Array} Returns a new array of property values. + * @returns {Array} Returns the property values. * @example * * var characters = [ @@ -4293,7 +4444,9 @@ * _.pluck(characters, 'name'); * // => ['barney', 'fred'] */ - var pluck = map; + function pluck(collection, key) { + return map(collection, property(key)); + } /** * Reduces a collection to a value which is the accumulated result of running @@ -4327,8 +4480,8 @@ */ function reduce(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); + if (isArray(collection)) { var index = -1, length = collection.length; @@ -4350,8 +4503,8 @@ } /** - * This method is like `_.reduce` except that it iterates over elements - * of a `collection` from right to left. + * This method is like `_.reduce` except that it iterates over elements of a + * collection from right to left. * * @static * @memberOf _ @@ -4364,14 +4517,14 @@ * @returns {*} Returns the accumulated value. * @example * - * var list = [[0, 1], [2, 3], [4, 5]]; - * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); + * var array = [[0, 1], [2, 3], [4, 5]]; + * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ function reduceRight(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); + baseEachRight(collection, function(value, index, collection) { accumulator = noaccum ? (noaccum = false, value) @@ -4381,13 +4534,13 @@ } /** - * The opposite of `_.filter`; this method returns the elements of a - * collection that the callback does **not** return truey for. + * The opposite of `_.filter`; this method returns the elements of a collection + * the predicate does **not** return truthy for. * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -4395,11 +4548,11 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of elements that failed the callback check. + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new filtered array. * @example * * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); @@ -4418,11 +4571,9 @@ * _.reject(characters, { 'age': 36 }); * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ - function reject(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); - return filter(collection, function(value, index, collection) { - return !callback(value, index, collection); - }); + function reject(collection, predicate, thisArg) { + predicate = lodash.createCallback(predicate, thisArg, 3); + return filter(collection, negate(predicate)); } /** @@ -4434,7 +4585,7 @@ * @param {Array|Object|string} collection The collection to sample. * @param {number} [n] The number of elements to sample. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {*} Returns the random sample(s) of `collection`. + * @returns {*} Returns the random sample(s). * @example * * _.sample([1, 2, 3, 4]); @@ -4450,22 +4601,24 @@ collection = collection.split(''); } if (n == null || guard) { - return collection ? collection[baseRandom(0, collection.length - 1)] : undefined; + var length = collection ? collection.length : 0; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; } var result = shuffle(collection); - result.length = nativeMin(nativeMax(0, n), result.length); + result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length); return result; } /** * Creates an array of shuffled values, using a version of the Fisher-Yates - * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) for more details. + * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) + * for more details. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to shuffle. - * @returns {Array} Returns a new shuffled collection. + * @returns {Array} Returns the new shuffled array. * @example * * _.shuffle([1, 2, 3, 4]); @@ -4473,20 +4626,19 @@ */ function shuffle(collection) { var index = -1, - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); + length = collection && collection.length, + result = Array(length < 0 ? 0 : length >>> 0); baseEach(collection, function(value) { var rand = baseRandom(0, ++index); result[index] = result[rand]; result[rand] = value; }); - return result; } /** - * Gets the size of the `collection` by returning `collection.length` for arrays + * Gets the size of the collection by returning `collection.length` for arrays * and array-like objects or the number of own enumerable properties for objects. * * @static @@ -4507,19 +4659,21 @@ */ function size(collection) { var length = collection ? collection.length : 0; - return typeof length == 'number' ? length : keys(collection).length; + return (typeof length == 'number' && length > -1 && length <= maxSafeInteger) + ? length + : keys(collection).length; } /** - * Checks if the callback returns a truey value for **any** element of a - * collection. The function returns as soon as it finds a passing value and - * does not iterate over the entire collection. The callback is bound to - * `thisArg` and invoked with three arguments; (value, index|key, collection). + * Checks if the predicate returns truthy for **any** element of a collection. + * The function returns as soon as it finds a passing value and does not iterate + * over the entire collection. The predicate is bound to `thisArg` and invoked + * with three arguments; (value, index|key, collection). * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -4528,11 +4682,11 @@ * @alias any * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if any element passed the callback check, + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. * @example * @@ -4552,22 +4706,22 @@ * _.some(characters, { 'age': 1 }); * // => false */ - function some(collection, callback, thisArg) { + function some(collection, predicate, thisArg) { var result; + predicate = lodash.createCallback(predicate, thisArg, 3); - callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { - if (callback(collection[index], index, collection)) { + if (predicate(collection[index], index, collection)) { return true; } } } else { baseEach(collection, function(value, index, collection) { - return !(result = callback(value, index, collection)); + return !(result = predicate(value, index, collection)); }); } return !!result; @@ -4594,11 +4748,11 @@ * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * @param {Array|Function|Object|string} [callback=identity] The function + * called per iteration. If a property name or object is provided it will + * be used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of sorted elements. + * @returns {Array} Returns the new sorted array. * @example * * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); @@ -4624,9 +4778,9 @@ */ function sortBy(collection, callback, thisArg) { var index = -1, + length = collection && collection.length, multi = callback && isArray(callback), - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); + result = Array(length < 0 ? 0 : length >>> 0); if (!multi) { callback = lodash.createCallback(callback, thisArg, 3); @@ -4654,7 +4808,7 @@ } /** - * Converts the `collection` to an array. + * Converts `collection` to an array. * * @static * @memberOf _ @@ -4667,7 +4821,8 @@ * // => [2, 3, 4] */ function toArray(collection) { - if (collection && typeof collection.length == 'number') { + var length = collection && collection.length; + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { return (support.unindexedChars && isString(collection)) ? collection.split('') : slice(collection); @@ -4677,35 +4832,39 @@ /** * Performs a deep comparison between each element in `collection` and the - * `source` object, returning an array of all elements that have equivalent + * source object, returning an array of all elements that have equivalent * property values. * * @static * @memberOf _ - * @type Function * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Object} source The object of property values to filter by. - * @returns {Array} Returns a new array of elements that have the given properties. + * @param {Array|Object|string} collection The collection to search. + * @param {Object} source The object of property values to match. + * @returns {Array} Returns the new filtered array. * @example * * var characters = [ - * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } + * { 'name': 'barney', 'age': 36, 'employer': 'slate', 'pets': ['hoppy'] }, + * { 'name': 'fred', 'age': 40, 'employer': 'slate', 'pets': ['baby puss', 'dino'] } * ]; * - * _.where(characters, { 'age': 36 }); - * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }] + * _.pluck(_.where(characters, { 'age': 36 }), 'name'); + * // => ['barney'] + * + * _.pluck(_.where(characters, { 'pets': ['dino'] }), 'name'); + * // => ['fred'] * - * _.where(characters, { 'pets': ['dino'] }); - * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }] + * _.pluck(_.where(characters, { 'employer': 'slate' }), 'name'); + * // => ['barney', 'fred'] */ - var where = filter; + function where(collection, source) { + return filter(collection, matches(source)); + } /*--------------------------------------------------------------------------*/ /** - * Creates a function that executes `func`, with the `this` binding and + * Creates a function that executes `func`, with the `this` binding and * arguments of the created function, only after being called `n` times. * * @static @@ -4730,8 +4889,9 @@ */ function after(n, func) { if (!isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } + n = nativeIsFinite(n = +n) ? n : 0; return function() { if (--n < 1) { return func.apply(this, arguments); @@ -4740,9 +4900,9 @@ } /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and prepends any additional `bind` arguments to those provided to the bound + * function. * * Note: Unlike native `Function#bind` this method does not set the `length` * property of bound functions. @@ -4789,8 +4949,8 @@ * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. + * @param {...string} [methodNames] The object method names to bind, specified + * as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * @@ -4816,10 +4976,10 @@ } /** - * Creates a function that, when called, invokes the method at `object[key]` - * and prepends any additional `bindKey` arguments to those provided to the bound - * function. This method differs from `_.bind` by allowing bound functions to - * reference methods that will be redefined or don't yet exist. + * Creates a function that invokes the method at `object[key]` and prepends + * any additional `bindKey` arguments to those provided to the bound function. + * This method differs from `_.bind` by allowing bound functions to reference + * methods that will be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * @@ -4865,7 +5025,7 @@ * @static * @memberOf _ * @category Functions - * @param {...Function} [func] Functions to compose. + * @param {...Function} [funcs] Functions to compose. * @returns {Function} Returns the new composed function. * @example * @@ -4893,7 +5053,7 @@ while (length--) { if (!isFunction(funcs[length])) { - throw new TypeError; + throw new TypeError(funcErrorText); } } return function() { @@ -4951,7 +5111,7 @@ * the leading and/or trailing edge of the `wait` timeout. Subsequent calls * to the debounced function will return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true` `func` will be called + * Note: If `leading` and `trailing` options are `true`, `func` will be called * on the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * @@ -4996,15 +5156,15 @@ trailing = true; if (!isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } - wait = nativeMax(0, wait) || 0; + wait = wait < 0 ? 0 : wait; if (options === true) { var leading = true; trailing = false; } else if (isObject(options)) { leading = options.leading; - maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0); + maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); trailing = 'trailing' in options ? options.trailing : trailing; } var delayed = function() { @@ -5101,7 +5261,7 @@ */ function defer(func) { if (!isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } var args = slice(arguments, 1); return setTimeout(function() { func.apply(undefined, args); }, 1); @@ -5125,7 +5285,7 @@ */ function delay(func, wait) { if (!isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } var args = slice(arguments, 2); return setTimeout(function() { func.apply(undefined, args); }, wait); @@ -5143,7 +5303,7 @@ * @memberOf _ * @category Functions * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] A function used to resolve the cache key. + * @param {Function} [resolver] The function to resolve the cache key. * @returns {Function} Returns the new memoizing function. * @example * @@ -5169,8 +5329,8 @@ * // => { 'name': 'penelope', 'age': 1 } */ function memoize(func, resolver) { - if (!isFunction(func)) { - throw new TypeError; + if (!isFunction(func) || (resolver && !isFunction(resolver))) { + throw new TypeError(funcErrorText); } var memoized = function() { var cache = memoized.cache, @@ -5184,6 +5344,34 @@ return memoized; } + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` function is executed with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new function. + * @example + * + * function isEven(num) { + * return num % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (!isFunction(predicate)) { + throw new TypeError(funcErrorText); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + /** * Creates a function that is restricted to execute `func` once. Repeat calls to * the function will return the value of the first call. The `func` is executed @@ -5206,7 +5394,7 @@ result; if (!isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } return function() { if (ran) { @@ -5222,9 +5410,9 @@ } /** - * Creates a function that, when called, invokes `func` with any additional - * `partial` arguments prepended to those provided to the new function. This - * method is similar to `_.bind` except it does **not** alter the `this` binding. + * Creates a function that invokes `func` with any additional `partial` arguments + * prepended to those provided to the new function. This method is similar to + * `_.bind` except it does **not** alter the `this` binding. * * Note: This method does not set the `length` property of partially applied * functions. @@ -5267,20 +5455,15 @@ * @returns {Function} Returns the new partially applied function. * @example * - * var defaultsDeep = _.partialRight(_.merge, _.defaults); - * - * var options = { - * 'variable': 'data', - * 'imports': { 'jq': $ } - * }; - * - * defaultsDeep(options, _.templateSettings); + * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { + * return _.merge(value, other, deep); + * }); * - * options.variable - * // => 'data' + * var object = { 'a': { 'b': { 'c': 1 } } }, + * source = { 'a': { 'b': { 'c': 2, 'd': 2 } } }; * - * options.imports - * // => { '_': _, 'jq': $ } + * defaultsDeep(object, source); + * // => { 'a': { 'b': { 'c': 1, 'd': 2 } } } */ function partialRight(func) { if (func) { @@ -5299,7 +5482,7 @@ * of the `wait` timeout. Subsequent calls to the throttled function will * return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true` `func` will be called + * Note: If `leading` and `trailing` options are `true`, `func` will be called * on the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * @@ -5328,16 +5511,16 @@ trailing = true; if (!isFunction(func)) { - throw new TypeError; + throw new TypeError(funcErrorText); } if (options === false) { leading = false; } else if (isObject(options)) { - leading = 'leading' in options ? options.leading : leading; - trailing = 'trailing' in options ? options.trailing : trailing; + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; } debounceOptions.leading = leading; - debounceOptions.maxWait = wait; + debounceOptions.maxWait = +wait; debounceOptions.trailing = trailing; return debounce(func, wait, debounceOptions); @@ -5370,7 +5553,6 @@ /*--------------------------------------------------------------------------*/ - /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources will overwrite property assignments of previous @@ -5383,7 +5565,7 @@ * @alias extend * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -5392,16 +5574,19 @@ * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); * // => { 'name': 'fred', 'employer': 'slate' } * - * var defaults = _.partialRight(_.assign, function(a, b) { - * return typeof a == 'undefined' ? b : a; + * var defaults = _.partialRight(_.assign, function(value, other) { + * return typeof value == 'undefined' ? other : value; * }); * * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ function assign(object, source, guard) { - var args = arguments, - argsIndex = 0, + var args = arguments; + if (!object || args.length < 2) { + return object; + } + var argsIndex = 0, argsLength = args.length, type = typeof guard; @@ -5417,15 +5602,13 @@ } while (++argsIndex < argsLength) { source = args[argsIndex]; - if (isObject(source)) { - var index = -1, - props = keys(source), - length = props.length; + var index = -1, + props = keys(source), + length = props.length; - while (++index < length) { - var key = props[index]; - object[key] = callback ? callback(object[key], source[key]) : source[key]; - } + while (++index < length) { + var key = props[index]; + object[key] = callback ? callback(object[key], source[key]) : source[key]; } } return object; @@ -5583,11 +5766,14 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property will be ignored. * + * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * for a deep version of this method. + * * @static * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example @@ -5595,42 +5781,23 @@ * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ - function defaults(object, source, guard) { - var args = arguments, - argsIndex = 0, - argsLength = args.length, - type = typeof guard; - - // enables use as a callback for functions like `_.reduce` - if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { - argsLength = 2; - } - while (++argsIndex < argsLength) { - source = args[argsIndex]; - if (isObject(source)) { - var index = -1, - props = keys(source), - length = props.length; - - while (++index < length) { - var key = props[index]; - if (typeof object[key] == 'undefined') { - object[key] = source[key]; - } - } - } + function defaults(object) { + if (!object) { + return object; } - return object; + var args = slice(arguments); + args.push(assignDefaults); + return assign.apply(null, args); } /** * This method is like `_.findIndex` except that it returns the key of the - * first element that passes the callback check, instead of the element itself. + * first element the predicate returns truthy for, instead of the element itself. * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -5638,11 +5805,11 @@ * @memberOf _ * @category Objects * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @param {Function|Object|string} [predicate=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * * var characters = { @@ -5664,27 +5831,19 @@ * _.findKey(characters, 'blocked'); * // => 'fred' */ - function findKey(object, callback, thisArg) { - var result; - - callback = lodash.createCallback(callback, thisArg, 3); - baseForOwn(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; - } - }); - return result; + function findKey(object, predicate, thisArg) { + predicate = lodash.createCallback(predicate, thisArg, 3); + return baseFind(object, predicate, baseForOwn, true); } /** - * This method is like `_.findKey` except that it iterates over elements - * of a `collection` in the opposite order. + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. * - * If a property name is provided for `callback` the created "_.pluck" style + * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback + * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * @@ -5692,11 +5851,11 @@ * @memberOf _ * @category Objects * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @param {Function|Object|string} [predicate=identity] The function called + * per iteration. If a property name or object is provided it will be used + * to create a "_.pluck" or "_.where" style callback respectively. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * * var characters = { @@ -5718,28 +5877,19 @@ * _.findLastKey(characters, 'blocked'); * // => 'pebbles' */ - function findLastKey(object, callback, thisArg) { - var result; - - callback = lodash.createCallback(callback, thisArg, 3); - baseForOwnRight(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; - } - }); - return result; + function findLastKey(object, predicate, thisArg) { + predicate = lodash.createCallback(predicate, thisArg, 3); + return baseFind(object, predicate, baseForOwnRight, true); } /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. + * Iterates over own and inherited enumerable properties of an object executing + * the callback for each property. The callback is bound to `thisArg` and invoked + * with three arguments; (value, key, object). Callbacks may exit iteration + * early by explicitly returning `false`. * * @static * @memberOf _ - * @type Function * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. @@ -5752,24 +5902,21 @@ * this.y = 0; * } * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; + * Shape.prototype.z = 0; * * _.forIn(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) + * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments) */ function forIn(object, callback, thisArg) { callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - return baseForIn(object, callback); + return baseFor(object, callback, keysIn); } /** - * This method is like `_.forIn` except that it iterates over elements - * of a `collection` in the opposite order. + * This method is like `_.forIn` except that it iterates over elements of a + * collection in the opposite order. * * @static * @memberOf _ @@ -5785,34 +5932,20 @@ * this.y = 0; * } * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; + * Shape.prototype.z = 0; * * _.forInRight(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' + * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' */ function forInRight(object, callback, thisArg) { - var pairs = []; - baseForIn(object, function(value, key) { - pairs.push(key, value); - }); - - var length = pairs.length; callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - if (callback(pairs[length--], pairs[length], object) === false) { - break; - } - } - return object; + return baseForRight(object, callback, keysIn); } /** - * Iterates over own enumerable properties of an object, executing the callback + * Iterates over own enumerable properties of an object executing the callback * for each property. The callback is bound to `thisArg` and invoked with three * arguments; (value, key, object). Callbacks may exit iteration early by * explicitly returning `false`. @@ -5837,8 +5970,8 @@ } /** - * This method is like `_.forOwn` except that it iterates over elements - * of a `collection` in the opposite order. + * This method is like `_.forOwn` except that it iterates over elements of a + * collection in the opposite order. * * @static * @memberOf _ @@ -5855,17 +5988,8 @@ * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ function forOwnRight(object, callback, thisArg) { - var props = keys(object), - length = props.length; - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - var key = props[length]; - if (callback(object[key], key, object) === false) { - break; - } - } - return object; + return baseForRight(object, callback, keys); } /** @@ -5877,7 +6001,7 @@ * @alias methods * @category Objects * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names that have function values. + * @returns {Array} Returns the new sorted array of property names. * @example * * _.functions(_); @@ -5885,6 +6009,7 @@ */ function functions(object) { var result = []; + baseForIn(object, function(value, key) { if (isFunction(value)) { result.push(key); @@ -5923,7 +6048,7 @@ * @category Objects * @param {Object} object The object to invert. * @param {boolean} [multiValue=false] Allow multiple values per key. - * @returns {Object} Returns the created inverted object. + * @returns {Object} Returns the new inverted object. * @example * * _.invert({ 'first': 'fred', 'second': 'barney' }); @@ -5962,25 +6087,52 @@ } /** - * Checks if `value` is an array. + * Checks if `value` is an `arguments` object. * * @static * @memberOf _ - * @type Function * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, else `false`. * @example * - * (function() { return _.isArray(arguments); })(); + * (function() { return _.isArguments(arguments); })(); + * // => true + * + * _.isArguments([1, 2, 3]); * // => false + */ + function isArguments(value) { + return (value && typeof value == 'object' && typeof value.length == 'number' && + toString.call(value) == argsClass) || false; + } + // fallback for environments without a `[[Class]]` for `arguments` objects + if (!support.argsClass) { + isArguments = function(value) { + return (value && typeof value == 'object' && typeof value.length == 'number' && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee')) || false; + }; + } + + /** + * Checks if `value` is an array. + * + * @static + * @memberOf _ + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example * * _.isArray([1, 2, 3]); * // => true + * + * (function() { return _.isArray(arguments); })(); + * // => false */ var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; + return (value && typeof value == 'object' && typeof value.length == 'number' && + toString.call(value) == arrayClass) || false; }; /** @@ -5990,32 +6142,38 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. + * @returns {boolean} Returns `true` if `value` is a boolean value, else `false`. * @example * + * _.isBoolean(false); + * // => true + * * _.isBoolean(null); * // => false */ function isBoolean(value) { - return value === true || value === false || - value && typeof value == 'object' && toString.call(value) == boolClass || false; + return (value === true || value === false || + value && typeof value == 'object' && toString.call(value) == boolClass) || false; } /** - * Checks if `value` is a date. + * Checks if `value` is a `Date` object. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a date, else `false`. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. * @example * * _.isDate(new Date); * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false */ function isDate(value) { - return value && typeof value == 'object' && toString.call(value) == dateClass || false; + return (value && typeof value == 'object' && toString.call(value) == dateClass) || false; } /** @@ -6025,56 +6183,63 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true + * + * _.isElement(''); + * // => false */ function isElement(value) { - return value && typeof value == 'object' && value.nodeType === 1 && - (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value)) || false; + return (value && typeof value == 'object' && value.nodeType === 1 && + (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value))) || false; } // fallback for environments without DOM support if (!support.dom) { isElement = function(value) { - return value && typeof value == 'object' && value.nodeType === 1 && - !isPlainObject(value) || false; + return (value && typeof value == 'object' && value.nodeType === 1 && + !isPlainObject(value)) || false; }; } /** - * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a - * length of `0` and objects with no own enumerable properties are considered - * "empty". + * Checks if a collection is empty. A value is considered empty unless it is + * an array, array-like object, or string with a length greater than `0` or + * an object with own properties. * * @static * @memberOf _ * @category Objects * @param {Array|Object|string} value The value to inspect. - * @returns {boolean} Returns `true` if the `value` is empty, else `false`. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * - * _.isEmpty([1, 2, 3]); - * // => false + * _.isEmpty(null); + * // => true * - * _.isEmpty({}); + * _.isEmpty(true); * // => true * - * _.isEmpty(''); + * _.isEmpty(1); * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false */ function isEmpty(value) { var result = true; if (!value) { return result; } - var className = toString.call(value), - length = value.length; - - if ((className == arrayClass || className == stringClass || - (support.argsClass ? className == argsClass : isArguments(value))) || - (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + var length = value.length; + if ((length > -1 && length <= maxSafeInteger) && + (isArray(value) || isString(value) || isArguments(value) || + (typeof value == 'object' && isFunction(value.splice)))) { return !length; } baseForOwn(value, function() { @@ -6085,61 +6250,83 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent to each other. If a callback is provided it will be executed - * to compare values. If the callback returns `undefined` comparisons will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (a, b). + * equivalent. If a callback is provided it will be executed to compare + * values. If the callback returns `undefined` comparisons will be handled + * by the method instead. The callback is bound to `thisArg` and invoked + * with two arguments; (value, other). + * + * Note: This method supports comparing arrays, booleans, `Date` objects, + * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes + * are **not** supported. A callback may be used to extend support for + * comparing other values. * * @static * @memberOf _ * @category Objects - * @param {*} a The value to compare. - * @param {*} b The other value to compare. + * @param {*} value The value to compare to `other`. + * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'name': 'fred' }; - * var copy = { 'name': 'fred' }; + * var other = { 'name': 'fred' }; * - * object == copy; + * object == other; * // => false * - * _.isEqual(object, copy); + * _.isEqual(object, other); * // => true * * var words = ['hello', 'goodbye']; * var otherWords = ['hi', 'goodbye']; * - * _.isEqual(words, otherWords, function(a, b) { - * var reGreet = /^(?:hello|hi)$/i, - * aGreet = _.isString(a) && reGreet.test(a), - * bGreet = _.isString(b) && reGreet.test(b); - * - * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; + * _.isEqual(words, otherWords, function() { + * return _.every(arguments, _.bind(RegExp.prototype.test, /^h(?:i|ello)$/)) || undefined; * }); * // => true */ - function isEqual(a, b, callback, thisArg) { + function isEqual(value, other, callback, thisArg) { callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2); if (!callback) { // exit early for identical values - if (a === b) { + if (value === other) { // treat `-0` vs. `+0` as not equal - return a !== 0 || (1 / a == 1 / b); + return value !== 0 || (1 / value == 1 / other); } - var type = typeof a, - otherType = typeof b; + var valType = typeof value, + othType = typeof other; // exit early for unlike primitive values - if (a === a && (a == null || b == null || - (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { + if (value === value && (value == null || other == null || + (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { return false; } } - return baseIsEqual(a, b, callback); + return baseIsEqual(value, other, callback); + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @category Objects + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + return (value && typeof value == 'object' && toString.call(value) == errorClass) || false; } /** @@ -6153,7 +6340,7 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is finite, else `false`. + * @returns {boolean} Returns `true` if `value` is finite, else `false`. * @example * * _.isFinite(-101); @@ -6182,11 +6369,14 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. * @example * * _.isFunction(_); * // => true + * + * _.isFunction(/abc/); + * // => false */ function isFunction(value) { return typeof value == 'function'; @@ -6199,14 +6389,14 @@ } /** - * Checks if `value` is the language type of Object. + * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); @@ -6219,12 +6409,12 @@ * // => false */ function isObject(value) { - // check if the value is the ECMAScript language type of Object + // check if the value is the ECMAScript language type of `Object` // http://es5.github.io/#x8 // and avoid a V8 bug // https://code.google.com/p/v8/issues/detail?id=2291 var type = typeof value; - return value && (type == 'function' || type == 'object') || false; + return type == 'function' || (value && type == 'object') || false; } /** @@ -6238,7 +6428,7 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * * _.isNaN(NaN); @@ -6255,7 +6445,7 @@ */ function isNaN(value) { // `NaN` as a primitive is the only value that is not equal to itself - // (perform the [[Class]] check first to avoid errors with some host objects in IE) + // (perform the `[[Class]]` check first to avoid errors with some host objects in IE) return isNumber(value) && value != +value; } @@ -6266,13 +6456,13 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. * @example * * _.isNull(null); * // => true * - * _.isNull(undefined); + * _.isNull(void 0); * // => false */ function isNull(value) { @@ -6280,7 +6470,7 @@ } /** - * Checks if `value` is a number. + * Checks if `value` is a `Number` primitive or object. * * Note: `NaN` is considered a number. See the [ES5 spec](http://es5.github.io/#x8.5) * for more details. @@ -6289,20 +6479,30 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a number, else `false`. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. * @example * - * _.isNumber(8.4 * 5); + * _.isNumber(8.4); + * // => true + * + * _.isNumber(NaN); * // => true + * + * _.isNumber('8.4'); + * // => false */ function isNumber(value) { var type = typeof value; return type == 'number' || - value && type == 'object' && toString.call(value) == numberClass || false; + (value && type == 'object' && toString.call(value) == numberClass) || false; } /** - * Checks if `value` is an object created by the `Object` constructor. + * Checks if `value` is an object created by the `Object` constructor or has + * a `[[Prototype]]` of `null`. + * + * Note: This method assumes objects created by the `Object` constructor + * have no inherited enumerable properties. * * @static * @memberOf _ @@ -6324,6 +6524,9 @@ * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { @@ -6338,40 +6541,44 @@ }; /** - * Checks if `value` is a regular expression. + * Checks if `value` is a `RegExp` object. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. + * @returns {boolean} Returns `true` if `value` is a regexp object, else `false`. * @example * - * _.isRegExp(/fred/); + * _.isRegExp(/abc/); * // => true + * + * _.isRegExp('/abc/'); + * // => false */ function isRegExp(value) { - var type = typeof value; - return value && (type == 'function' || type == 'object') && - toString.call(value) == regexpClass || false; + return (isObject(value) && toString.call(value) == regexpClass) || false; } /** - * Checks if `value` is a string. + * Checks if `value` is a `String` primitive or object. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a string, else `false`. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. * @example * - * _.isString('fred'); + * _.isString('abc'); * // => true + * + * _.isString(1); + * // => false */ function isString(value) { return typeof value == 'string' || - value && typeof value == 'object' && toString.call(value) == stringClass || false; + (value && typeof value == 'object' && toString.call(value) == stringClass) || false; } /** @@ -6381,39 +6588,121 @@ * @memberOf _ * @category Objects * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true + * + * _.isUndefined(null); + * // => false */ function isUndefined(value) { return typeof value == 'undefined'; } /** - * Creates an array composed of the own enumerable property names of an object. + * Creates an array of the own enumerable property names of `object`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. + * @returns {Array} Returns the array of property names. * @example * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * Shape.prototype.z = 0; + * + * _.keys(new Shape); + * // => ['x', 'y'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { + var ctor = object && object.constructor, + length = object ? object.length : 0; + + if ((typeof length == 'number' && length > 0) || + (ctor && object === ctor.prototype)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * Shape.prototype.z = 0; + * + * _.keysIn(new Shape); + * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) + */ + function keysIn(object) { if (!isObject(object)) { return []; } - if ((support.enumPrototypes && typeof object == 'function') || - (support.nonEnumArgs && object.length && isArguments(object))) { - return shimKeys(object); + var length = object.length; + length = (typeof length == 'number' && length > 0 && + (isArray(object) || (support.nonEnumStrings && isString(object)) || + (support.nonEnumArgs && isArguments(object))) && length) >>> 0; + + var keyIndex, + ctor = object.constructor, + index = -1, + isProto = ctor && object === ctor.prototype, + maxIndex = length - 1, + result = Array(length), + skipIndexes = length > 0, + skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), + skipProto = support.enumPrototypes && typeof object == 'function'; + + while (++index < length) { + result[index] = String(index); } - return nativeKeys(object); - }; + for (var key in object) { + if (!(isProto && key == 'constructor') && + !(skipProto && key == 'prototype') && + !(skipErrorProps && (key == 'message' || key == 'name')) && + !(skipIndexes && (keyIndex = +key, keyIndex > -1 && keyIndex <= maxIndex && keyIndex % 1 == 0))) { + result.push(key); + } + } + // Lo-Dash skips the `constructor` property when it infers it's iterating + // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` + // attribute of an existing property and the `constructor` property of a + // prototype defaults to non-enumerable. + if (support.nonEnumShadows && object !== objectProto) { + index = -1; + length = shadowedProps.length; + + if (isProto) { + var className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object), + nonEnum = nonEnumProps[className]; + } + while (++index < length) { + key = shadowedProps[index]; + if (!(nonEnum && nonEnum[key]) && hasOwnProperty.call(object, key)) { + result.push(key); + } + } + } + return result; + } /** * Creates an object with the same keys as `object` and values generated by @@ -6434,9 +6723,9 @@ * @param {Object} object The object to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. + * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns a new object with values of the results of each `callback` execution. + * @returns {Object} Returns the new mapped object. * @example * * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); @@ -6453,8 +6742,8 @@ */ function mapValues(object, callback, thisArg) { var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); + baseForOwn(object, function(value, key, object) { result[key] = callback(value, key, object); }); @@ -6474,7 +6763,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -6513,13 +6802,13 @@ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } */ function merge(object, source, guard) { - if (!isObject(object)) { - return object; - } var args = arguments, length = args.length, type = typeof guard; + if (!object || length < 2) { + return object; + } // enables use as a callback for functions like `_.reduce` if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { length = 2; @@ -6530,7 +6819,7 @@ } else if (length > 2 && typeof args[length - 1] == 'function') { callback = args[--length]; } - var sources = slice(arguments, 1, length), + var sources = slice(args, 1, length), index = -1, stackA = [], stackB = []; @@ -6544,20 +6833,20 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` omitting the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it will be executed for each + * property of `object` omitting the properties the predicate returns truthy + * for. The predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The function called per + * @param {Function|...string|string[]} [predicate] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object without the omitted properties. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Object} Returns the new object. * @example * * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); @@ -6568,33 +6857,92 @@ * }); * // => { 'name': 'fred' } */ - function omit(object, callback, thisArg) { - var result = {}; + function omit(object, predicate, thisArg) { + if (typeof predicate == 'function') { + predicate = lodash.createCallback(predicate, thisArg, 3); + return pick(object, negate(predicate)); + } + var omitProps = baseFlatten(arguments, true, false, 1), + length = omitProps.length; - if (typeof callback != 'function') { - var omitProps = baseFlatten(arguments, true, false, 1), - length = omitProps.length; + while (length--) { + omitProps[length] = String(omitProps[length]); + } + return pick(object, baseDifference(keysIn(object), omitProps)); + } - while (length--) { - omitProps[length] = String(omitProps[length]); - } - var props = []; - baseForIn(object, function(value, key) { - props.push(key); - }); + /** + * Creates a two dimensional array of a given object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of key-value pairs. + * @example + * + * _.pairs({ 'barney': 36, 'fred': 40 }); + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + */ + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); - var index = -1; - props = baseDifference(props, omitProps); - length = props.length; + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; + } + + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a predicate is provided it will be executed for each + * property of `object` picking the properties the predicate returns truthy + * for. The predicate is bound to `thisArg` and invoked with three arguments; + * (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|...string|string[]} [predicate] The function called per + * iteration or property names to pick, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Object} Returns the new object. + * @example + * + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); + * // => { 'name': 'fred' } + * + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'fred' } + */ + function pick(object, predicate, thisArg) { + var result = {}; + + if (typeof predicate != 'function') { + var index = -1, + props = baseFlatten(arguments, true, false, 1), + length = isObject(object) ? props.length : 0; while (++index < length) { var key = props[index]; - result[key] = object[key]; + if (key in object) { + result[key] = object[key]; + } } } else { - callback = lodash.createCallback(callback, thisArg, 3); + predicate = lodash.createCallback(predicate, thisArg, 3); baseForIn(object, function(value, key, object) { - if (!callback(value, key, object)) { + if (predicate(value, key, object)) { result[key] = value; } }); @@ -6603,207 +6951,439 @@ } /** - * Creates a two dimensional array of an object's key-value pairs, - * i.e. `[[key1, value1], [key2, value2]]`. + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable properties through a callback, with each callback execution + * potentially mutating the `accumulator` object. The callback is bound to + * `thisArg` and invoked with four arguments; (accumulator, value, key, object). + * Callbacks may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Array|Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {*} Returns the accumulated value. + * @example + * + * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { + * num *= num; + * if (num % 2) { + * return result.push(num) < 3; + * } + * }); + * // => [1, 9, 25] + * + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { + * result[key] = num * 3; + * }); + * // => { 'a': 3, 'b': 6, 'c': 9 } + */ + function transform(object, callback, accumulator, thisArg) { + var isArr = isArray(object); + if (accumulator == null) { + if (isArr) { + accumulator = []; + } else { + if (isObject(object)) { + var ctor = object.constructor, + proto = ctor && ctor.prototype; + } + accumulator = baseCreate(proto); + } + } + if (callback) { + callback = lodash.createCallback(callback, thisArg, 4); + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return callback(accumulator, value, index, object); + }); + } + return accumulator; + } + + /** + * Creates an array of the own enumerable property values of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property values. + * @example + * + * function Shape(x, y) { + * this.x = x; + * this.y = y; + * } + * + * Shape.prototype.z = 0; + * + * _.values(new Shape(2, 1)); + * // => [2, 1] (property order is not guaranteed across environments) + */ + function values(object) { + return baseValues(object, keys); + } + + /** + * Creates an array of the own and inherited enumerable property values + * of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property values. + * @example + * + * function Shape(x, y) { + * this.x = x; + * this.y = y; + * } + * + * Shape.prototype.z = 0; + * + * _.valuesIn(new Shape(2, 1)); + * // => [2, 1, 0] (property order is not guaranteed across environments) + */ + function valuesIn(object) { + return baseValues(object, keysIn); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Converts `string` to camel case. + * See [Wikipedia](http://en.wikipedia.org/wiki/CamelCase) for more details. + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to camel case. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Hello world'); + * // => 'helloWorld' + * + * _.camelCase('--hello-world'); + * // => 'helloWorld' + * + * _.camelCase('__hello_world__'); + * // => 'helloWorld' + */ + var camelCase = createCompounder(function(result, word, index) { + if (!index && reAllCaps.test(word)) { + return result + word.toLowerCase(); + } + return result + (word.charAt(0)[index ? 'toUpperCase' : 'toLowerCase']() + word.slice(1)); + }); + + /** + * Capitalizes the first character of `string`. + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('fred'); + * // => 'Fred' + */ + function capitalize(string) { + if (string == null) { + return ''; + } + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * Checks if `string` ends with a given target string. + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to search. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search from. + * @returns {boolean} Returns `true` if the given string ends with the + * target string, else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = string == null ? '' : String(string); + target = String(target); + + var length = string.length; + position = (typeof position == 'undefined' ? length : nativeMin(position < 0 ? 0 : (+position || 0), length)) - target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to + * their corresponding HTML entities. + * + * Note: No other characters are escaped. To escape additional characters + * use a third-party library like [_he_](http://mths.be/he). + * + * When working with HTML you should always quote attribute values to reduce + * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) + * for more details. + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); + } + + /** + * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", + * "+", "(", ")", "[", "]", "{" and "}" in `string`. + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](http://lodash.com)'); + * // => '\[lodash\]\(http://lodash\.com\)' + */ + function escapeRegExp(string) { + return string == null ? '' : String(string).replace(reRegExpChars, '\\$&'); + } + + /** + * Converts `string` to kebab case (a.k.a. spinal case). + * See [Wikipedia](http://en.wikipedia.org/wiki/Letter_case#Computers) for + * more details. + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to kebab case. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Hello world'); + * // => 'hello-world' + * + * _.kebabCase('helloWorld'); + * // => 'hello-world' + * + * _.kebabCase('__hello_world__'); + * // => 'hello-world' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Pads `string` on the left and right sides if it is shorter then the given + * padding length. The `chars` string may be truncated if the number of padding + * characters can't be evenly divided by the padding length. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns new array of key-value pairs. + * @category Strings + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. * @example * - * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' */ - function pairs(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); + function pad(string, length, chars) { + string = string == null ? '' : String(string); + length = +length; - while (++index < length) { - var key = props[index]; - result[index] = [key, object[key]]; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; } - return result; + var mid = (length - strLength) / 2, + leftLength = floor(mid), + rightLength = ceil(mid); + + chars = createPad('', rightLength, chars); + return chars.slice(0, leftLength) + string + chars; } /** - * Creates a shallow clone of `object` composed of the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` picking the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * Pads `string` on the left side if it is shorter then the given padding + * length. The `chars` string may be truncated if the number of padding + * characters exceeds the padding length. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The function called per - * iteration or property names to pick, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object composed of the picked properties. + * @category Strings + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. * @example * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); - * // => { 'name': 'fred' } + * _.padLeft('abc', 6); + * // => ' abc' * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { - * return key.charAt(0) != '_'; - * }); - * // => { 'name': 'fred' } + * _.padLeft('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padLeft('abc', 3); + * // => 'abc' */ - function pick(object, callback, thisArg) { - var result = {}; - - if (typeof callback != 'function') { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = isObject(object) ? props.length : 0; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - baseForIn(object, function(value, key, object) { - if (callback(value, key, object)) { - result[key] = value; - } - }); - } - return result; + function padLeft(string, length, chars) { + string = string == null ? '' : String(string); + return createPad(string, length, chars) + string; } /** - * An alternative to `_.reduce`; this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable properties through a callback, with each callback execution - * potentially mutating the `accumulator` object. The callback is bound to - * `thisArg` and invoked with four arguments; (accumulator, value, key, object). - * Callbacks may exit iteration early by explicitly returning `false`. + * Pads `string` on the right side if it is shorter then the given padding + * length. The `chars` string may be truncated if the number of padding + * characters exceeds the padding length. * * @static * @memberOf _ - * @category Objects - * @param {Array|Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. + * @category Strings + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. * @example * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; - * } - * }); - * // => [1, 9, 25] + * _.padRight('abc', 6); + * // => 'abc ' * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; - * }); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * _.padRight('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padRight('abc', 3); + * // => 'abc' */ - function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); - if (accumulator == null) { - if (isArr) { - accumulator = []; - } else { - var ctor = object && object.constructor, - proto = ctor && ctor.prototype; - - accumulator = baseCreate(proto); - } - } - if (callback) { - callback = lodash.createCallback(callback, thisArg, 4); - (isArr ? baseEach : baseForOwn)(object, function(value, index, object) { - return callback(accumulator, value, index, object); - }); - } - return accumulator; + function padRight(string, length, chars) { + string = string == null ? '' : String(string); + return string + createPad(string, length, chars); } /** - * Creates an array composed of the own enumerable property values of `object`. + * Repeats the given string `n` times. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property values. + * @category Strings + * @param {string} [string=''] The string to repeat. + * @param {number} [n=0] The number of times to repeat the string. + * @returns {string} Returns the repeated string. * @example * - * _.values({ 'one': 1, 'two': 2, 'three': 3 }); - * // => [1, 2, 3] (property order is not guaranteed across environments) + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' */ - function values(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); + function repeat(string, n) { + var result = ''; + n = +n; - while (++index < length) { - result[index] = object[props[index]]; + if (n < 1 || string == null || !nativeIsFinite(n)) { + return result; } + string = String(string); + do { + if (n % 2) { + result += string; + } + n = floor(n / 2); + string += string; + } while (n); return result; } - /*--------------------------------------------------------------------------*/ - /** - * Converts the first character of `string` to upper case. + * Converts `string` to snake case. + * See [Wikipedia](http://en.wikipedia.org/wiki/Snake_case) for more details. * * @static * @memberOf _ * @category Strings - * @param {string} string The string to capitalize. - * @returns {string} Returns the capitalized string. + * @param {string} [string=''] The string to snake case. + * @returns {string} Returns the snake cased string. * @example * - * _.capitalize('fred'); - * // => 'Fred' + * _.snakeCase('Hello world'); + * // => 'hello_world' + * + * _.snakeCase('--hello-world'); + * // => 'hello_world' + * + * _.snakeCase('helloWorld'); + * // => 'hello_world' */ - function capitalize(string) { - if (string == null) { - return ''; - } - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to - * their corresponding HTML entities. - * - * Note: No other characters are escaped. To escape additional characters - * use a third-party library like [_he_](http://mths.be/he). - * - * When working with HTML you should always quote attribute values to reduce - * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) - * for more details. + * Checks if `string` starts with a given target string. * * @static * @memberOf _ * @category Strings - * @param {string} string The string to escape. - * @returns {string} Returns the escaped string. + * @param {string} [string=''] The string to search. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if the given string starts with the + * target string, else `false`. * @example * - * _.escape('fred, barney, & pebbles'); - * // => 'fred, barney, & pebbles' + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true */ - function escape(string) { - return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); + function startsWith(string, target, position) { + string = string == null ? '' : String(string); + position = typeof position == 'undefined' ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length); + return string.lastIndexOf(target, position) == position; } /** @@ -6815,8 +7395,8 @@ * settings object is provided it will override `_.templateSettings` for the * template. * - * Note: In the development build, `_.template` utilizes sourceURLs for easier - * debugging. See [HTML5 Rocks' article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * Note: In the development build, `_.template` utilizes `sourceURL`s for easier debugging. + * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * * For more information on precompiling templates see @@ -6828,17 +7408,17 @@ * @static * @memberOf _ * @category Strings - * @param {string} text The template text. - * @param {Object} [data] The data object used to populate the text. + * @param {string} [string=''] The template string. + * @param {Object} [data] The data object used to populate the template string. * @param {Object} [options] The options object. * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. * @param {Object} [options.imports] An object to import into the template as local variables. * @param {RegExp} [options.interpolate] The "interpolate" delimiter. - * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. + * @param {string} [options.sourceURL] The `sourceURL` of the template's compiled source. * @param {string} [options.variable] The data object variable name. * @returns {Function|string} Returns the interpolated string if a data object - * is provided, else it returns a template function. + * is provided, else the compiled template function. * @example * * // using the "interpolate" delimiter to create a compiled template @@ -6873,7 +7453,7 @@ * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } }); * // => '
  • fred
  • barney
  • ' * - * // using the `sourceURL` option to specify a custom sourceURL for the template + * // using the `sourceURL` option to specify a custom `sourceURL` for the template * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' }); * compiled(data); * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector @@ -6895,20 +7475,18 @@ * };\ * '); */ - function template(text, data, options) { + function template(string, data, options) { // based on John Resig's `tmpl` implementation // http://ejohn.org/blog/javascript-micro-templating/ // and Laura Doktorova's doT.js // https://github.com/olado/doT var settings = lodash.templateSettings; - text = String(text || ''); + options = defaults({}, options, settings); + string = String(string == null ? '' : string); - // avoid missing dependencies when `iteratorTemplate` is not defined - options = iteratorTemplate ? defaults({}, options, settings) : settings; - - var imports = iteratorTemplate && defaults({}, options.imports, settings.imports), - importsKeys = iteratorTemplate ? keys(imports) : ['_'], - importsValues = iteratorTemplate ? values(imports) : [lodash]; + var imports = defaults({}, options.imports, settings.imports), + importsKeys = keys(imports), + importsValues = values(imports); var isEscaping, isEvaluating, @@ -6924,11 +7502,11 @@ (options.evaluate || reNoMatch).source + '|$' , 'g'); - text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); // escape characters that cannot be included in string literals - source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // replace delimiters with snippets if (escapeValue) { @@ -6981,7 +7559,7 @@ source + 'return __p\n}'; - // Use a sourceURL for easier debugging. + // Use a `sourceURL` for easier debugging. // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/'; @@ -7007,7 +7585,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} string The string to trim. + * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example @@ -7018,12 +7596,17 @@ * _.trim('-_-fred-_-', '_-'); * // => 'fred' */ - var trim = !nativeTrim ? shimTrim : function(string, chars) { - if (string == null) { - return ''; + function trim(string, chars) { + string = string == null ? '' : String(string); + if (!string) { + return string; } - return chars == null ? nativeTrim.call(string) : shimTrim(string, chars); - }; + if (chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = String(chars); + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } /** * Removes leading whitespace or specified characters from `string`. @@ -7031,7 +7614,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} string The string to trim. + * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example @@ -7042,12 +7625,17 @@ * _.trimLeft('-_-fred-_-', '_-'); * // => 'fred-_-' */ - var trimLeft = !nativeTrimLeft ? shimTrimLeft : function(string, chars) { - if (string == null) { - return ''; + function trimLeft(string, chars) { + string = string == null ? '' : String(string); + if (!string) { + return string; } - return chars == null ? nativeTrimLeft.call(string) : shimTrimLeft(string, chars); - }; + if (chars == null) { + return string.slice(trimmedLeftIndex(string)) + } + chars = String(chars); + return string.slice(charsLeftIndex(string, chars)); + } /** * Removes trailing whitespace or specified characters from `string`. @@ -7055,7 +7643,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} string The string to trim. + * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example @@ -7066,12 +7654,96 @@ * _.trimRight('-_-fred-_-', '_-'); * // => '-_-fred' */ - var trimRight = !nativeTrimRight ? shimTrimRight : function(string, chars) { - if (string == null) { - return ''; + function trimRight(string, chars) { + string = string == null ? '' : String(string); + if (!string) { + return string; } - return chars == null ? nativeTrimRight.call(string) : shimTrimRight(string, chars); - }; + if (chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1) + } + chars = String(chars); + return string.slice(0, charsRightIndex(string, chars) + 1); + } + + /** + * Truncates `string` if it is longer than the given maximum string length. + * The last characters of the truncated string will be replaced with the + * omission string which defaults to "...". + * + * @static + * @memberOf _ + * @category Strings + * @param {string} [string=''] The string to truncate. + * @param {Object|number} [options] The options object or maximum string length. + * @param {number} [options.length=30] The maximum string length. + * @param {string} [options.omission='...'] The string used to indicate text is omitted. + * @param {RegExp|string} [options.separator] The separator pattern to truncate to. + * @returns {string} Returns the truncated string. + * @example + * + * _.truncate('hi-diddly-ho there, neighborino'); + * // => 'hi-diddly-ho there, neighbo...' + * + * _.truncate('hi-diddly-ho there, neighborino', 24); + * // => 'hi-diddly-ho there, n...' + * + * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); + * // => 'hi-diddly-ho there,...' + * + * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); + * //=> 'hi-diddly-ho there...' + * + * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); + * // => 'hi-diddly-ho there, neig [...]' + */ + function truncate(string, options) { + var length = 30, + omission = '...'; + + if (options && isObject(options)) { + var separator = 'separator' in options ? options.separator : separator; + length = 'length' in options ? +options.length || 0 : length; + omission = 'omission' in options ? String(options.omission) : omission; + } + else if (options != null) { + length = +options || 0; + } + string = string == null ? '' : String(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, + newEnd, + substring = string.slice(0, end); + + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g'); + } + separator.lastIndex = 0; + while ((match = separator.exec(substring))) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } /** * The inverse of `_.escape`; this method converts the HTML entities @@ -7084,7 +7756,7 @@ * @static * @memberOf _ * @category Strings - * @param {string} string The string to unescape. + * @param {string} [string=''] The string to unescape. * @returns {string} Returns the unescaped string. * @example * @@ -7123,7 +7795,7 @@ } /** - * Produces a callback bound to an optional `thisArg`. If `func` is a property + * Creates a function bound to an optional `thisArg`. If `func` is a property * name the created callback will return the property value for a given element. * If `func` is an object the created callback will return `true` for elements * that contain the equivalent object properties, otherwise it will return `false`. @@ -7135,7 +7807,7 @@ * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. + * @returns {Function} Returns the new function. * @example * * var characters = [ @@ -7157,11 +7829,11 @@ function createCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function' || func == null) { - return (typeof thisArg == 'undefined' || !('prototype' in func)) && + return (typeof thisArg == 'undefined' || !(func && 'prototype' in func)) && func || baseCreateCallback(func, thisArg, argCount); } // handle "_.pluck" and "_.where" style callback shorthands - return type != 'object' ? property(func) : matches(func); + return type == 'object' ? matches(func) : property(func); } /** @@ -7183,9 +7855,9 @@ } /** - * Creates a "_.where" style function, which performs a deep comparison - * between a given object and the `source` object, returning `true` if the - * given object has equivalent property values, else `false`. + * Creates a "_.where" style predicate function which performs a deep comparison + * between a given object and the `source` object, returning `true` if the given + * object has equivalent property values, else `false`. * * @static * @memberOf _ @@ -7208,32 +7880,33 @@ * // => { 'name': 'barney', 'age': 36 } */ function matches(source) { - source || (source = {}); - var props = keys(source), + propsLength = props.length, key = props[0], - a = source[key]; + value = propsLength && source[key]; // fast path the common case of providing an object with a single // property containing a primitive value - if (props.length == 1 && a === a && !isObject(a)) { + if (propsLength == 1 && value === value && !isObject(value)) { return function(object) { - if (!hasOwnProperty.call(object, key)) { + if (!(object && hasOwnProperty.call(object, key))) { return false; } // treat `-0` vs. `+0` as not equal - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); + var other = object[key]; + return value === other && (value !== 0 || (1 / value == 1 / other)); }; } return function(object) { - var length = props.length, - result = false; - + var length = propsLength; + if (length && !object) { + return false; + } + var result = true; while (length--) { var key = props[length]; if (!(result = hasOwnProperty.call(object, key) && - baseIsEqual(object[key], source[key], null, true))) { + baseIsEqual(object[key], source[key], null, true))) { break; } } @@ -7248,10 +7921,12 @@ * @static * @memberOf _ * @category Utilities - * @param {Function|Object} [object=lodash] object The destination object. + * @param {Function|Object} [object=this] object The destination object. * @param {Object} source The object of functions to add. * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added are chainable. + * @param {boolean} [options.chain=true] Specify whether the functions added + * are chainable. + * @returns {Function|Object} Returns `object`. * @example * * function vowels(string) { @@ -7280,7 +7955,7 @@ options = source; } source = object; - object = lodash; + object = this; methodNames = functions(source); } if (options === false) { @@ -7317,10 +7992,11 @@ }(func)); } } + return object; } /** - * Reverts the '_' variable to its previous value and returns a reference to + * Reverts the `_` variable to its previous value and returns a reference to * the `lodash` function. * * @static @@ -7371,8 +8047,8 @@ /** * Converts `value` to an integer of the specified radix. If `radix` is - * `undefined` or `0` a `radix` of `10` is used unless the `value` is a - * hexadecimal, in which case a `radix` of `16` is used. + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, + * in which case a `radix` of `16` is used. * * Note: This method avoids differences in native ES3 and ES5 `parseInt` * implementations. See the [ES5 spec](http://es5.github.io/#E) @@ -7383,7 +8059,7 @@ * @category Utilities * @param {string} value The value to parse. * @param {number} [radix] The radix used to interpret the value to parse. - * @returns {number} Returns the new integer value. + * @returns {number} Returns the converted integer. * @example * * _.parseInt('08'); @@ -7398,7 +8074,7 @@ }; /** - * Creates a "_.pluck" style function, which returns the `key` value of a + * Creates a "_.pluck" style function which returns the `key` value of a * given object. * * @static @@ -7423,14 +8099,14 @@ */ function property(key) { return function(object) { - return object[key]; + return object == null ? undefined : object[key]; }; } /** * Produces a random number between `min` and `max` (inclusive). If only one * argument is provided a number between `0` and the given number will be - * returned. If `floating` is truey or either `min` or `max` are floats a + * returned. If `floating` is truthy or either `min` or `max` are floats a * floating-point number will be returned instead of an integer. * * @static @@ -7439,7 +8115,7 @@ * @param {number} [min=0] The minimum possible value. * @param {number} [max=1] The maximum possible value. * @param {boolean} [floating=false] Specify returning a floating-point number. - * @returns {number} Returns a random number. + * @returns {number} Returns the random number. * @example * * _.random(0, 5); @@ -7486,6 +8162,61 @@ return baseRandom(min, max); } + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `end`. If `start` is less than `stop` a + * zero-length range is created unless a negative `step` is specified. + * + * @static + * @memberOf _ + * @category Utilities + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the new array of numbers. + * @example + * + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + start = +start || 0; + step = step == null ? 1 : (+step || 0); + + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + // use `Array(length)` so engines like Chakra and V8 avoid slower modes + // http://youtu.be/XAqIpGU8ZZk#t=17m25s + var index = -1, + length = nativeMax(ceil((end - start) / (step || 1)), 0), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + /** * Resolves the value of property `key` on `object`. If `key` is a function * it will be invoked with the `this` binding of `object` and its result @@ -7536,9 +8267,9 @@ * @memberOf _ * @category Utilities * @param {number} n The number of times to execute the callback. - * @param {Function} callback The function called per iteration. + * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns an array of the results of each `callback` execution. + * @returns {Array} Returns the array of results. * @example * * var diceRolls = _.times(3, _.partial(_.random, 1, 6)); @@ -7551,11 +8282,12 @@ * // => also calls `mage.castSpell(n)` three times */ function times(n, callback, thisArg) { - n = (n = +n) > -1 ? n : 0; + n = n < 0 ? 0 : n >>> 0; + callback = baseCreateCallback(callback, thisArg, 1); + var index = -1, result = Array(n); - callback = baseCreateCallback(callback, thisArg, 1); while (++index < n) { result[index] = callback(index); } @@ -7605,6 +8337,10 @@ lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; lodash.filter = filter; lodash.flatten = flatten; lodash.forEach = forEach; @@ -7621,6 +8357,7 @@ lodash.invert = invert; lodash.invoke = invoke; lodash.keys = keys; + lodash.keysIn = keysIn; lodash.map = map; lodash.mapValues = mapValues; lodash.matches = matches; @@ -7628,6 +8365,8 @@ lodash.memoize = memoize; lodash.merge = merge; lodash.min = min; + lodash.mixin = mixin; + lodash.negate = negate; lodash.omit = omit; lodash.once = once; lodash.pairs = pairs; @@ -7638,10 +8377,10 @@ lodash.pluck = pluck; lodash.property = property; lodash.pull = pull; + lodash.pullAt = pullAt; lodash.range = range; lodash.reject = reject; lodash.remove = remove; - lodash.removeAt = removeAt; lodash.rest = rest; lodash.shuffle = shuffle; lodash.slice = slice; @@ -7654,6 +8393,7 @@ lodash.union = union; lodash.uniq = uniq; lodash.values = values; + lodash.valuesIn = valuesIn; lodash.where = where; lodash.without = without; lodash.wrap = wrap; @@ -7664,7 +8404,6 @@ // add aliases lodash.callback = createCallback; lodash.collect = map; - lodash.drop = rest; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; @@ -7676,16 +8415,19 @@ lodash.unzip = zip; // add functions to `lodash.prototype` - mixin(assign({}, lodash)); + mixin(lodash, assign({}, lodash)); /*--------------------------------------------------------------------------*/ // add functions that return unwrapped values when chaining + lodash.camelCase = camelCase; lodash.capitalize = capitalize; lodash.clone = clone; lodash.cloneDeep = cloneDeep; lodash.contains = contains; + lodash.endsWith = endsWith; lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; lodash.every = every; lodash.find = find; lodash.findIndex = findIndex; @@ -7693,6 +8435,7 @@ lodash.findLast = findLast; lodash.findLastIndex = findLastIndex; lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; lodash.has = has; lodash.identity = identity; lodash.indexOf = indexOf; @@ -7703,6 +8446,7 @@ lodash.isElement = isElement; lodash.isEmpty = isEmpty; lodash.isEqual = isEqual; + lodash.isError = isError; lodash.isFinite = isFinite; lodash.isFunction = isFunction; lodash.isNaN = isNaN; @@ -7713,24 +8457,31 @@ lodash.isRegExp = isRegExp; lodash.isString = isString; lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; lodash.lastIndexOf = lastIndexOf; - lodash.mixin = mixin; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; lodash.parseInt = parseInt; lodash.random = random; lodash.reduce = reduce; lodash.reduceRight = reduceRight; + lodash.repeat = repeat; lodash.result = result; lodash.runInContext = runInContext; lodash.size = size; lodash.some = some; lodash.sortedIndex = sortedIndex; + lodash.snakeCase = snakeCase; + lodash.startsWith = startsWith; lodash.template = template; lodash.trim = trim; lodash.trimLeft = trimLeft; lodash.trimRight = trimRight; + lodash.truncate = truncate; lodash.unescape = unescape; lodash.uniqueId = uniqueId; @@ -7738,13 +8489,12 @@ lodash.all = every; lodash.any = some; lodash.detect = find; - lodash.findWhere = find; lodash.foldl = reduce; lodash.foldr = reduceRight; lodash.include = contains; lodash.inject = reduce; - mixin(function() { + mixin(lodash, function() { var source = {} baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { @@ -7760,9 +8510,12 @@ lodash.first = first; lodash.last = last; lodash.sample = sample; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; // add aliases - lodash.take = first; lodash.head = first; baseForOwn(lodash, function(func, methodName) { @@ -7792,12 +8545,13 @@ // add "Chaining" functions to the wrapper lodash.prototype.chain = wrapperChain; + lodash.prototype.toJSON = wrapperValueOf; lodash.prototype.toString = wrapperToString; lodash.prototype.value = wrapperValueOf; lodash.prototype.valueOf = wrapperValueOf; // add `Array` functions that return unwrapped values - baseEach(['join', 'pop', 'shift'], function(methodName) { + arrayEach(['join', 'pop', 'shift'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { var chainAll = this.__chain__, @@ -7810,7 +8564,7 @@ }); // add `Array` functions that return the existing wrapped value - baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) { + arrayEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { func.apply(this.__wrapped__, arguments); @@ -7819,7 +8573,7 @@ }); // add `Array` functions that return new wrapped values - baseEach(['concat', 'splice'], function(methodName) { + arrayEach(['concat', 'splice'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__); @@ -7829,7 +8583,7 @@ // avoid array-like object bugs with `Array#shift` and `Array#splice` // in IE < 9, Firefox < 10, Narwhal, and RingoJS if (!support.spliceObjects) { - baseEach(['pop', 'shift', 'splice'], function(methodName) { + arrayEach(['pop', 'shift', 'splice'], function(methodName) { var func = arrayRef[methodName], isSplice = methodName == 'splice'; @@ -7847,12 +8601,6 @@ }; }); } - - // add pseudo private property to be used and removed during the build process - lodash._baseForIn = baseForIn; - lodash._iteratorTemplate = iteratorTemplate; - lodash._shimKeys = shimKeys; - return lodash; } diff --git a/test/test.js b/test/test.js index 69e153d3e0..f60bd7a107 100644 --- a/test/test.js +++ b/test/test.js @@ -4,7 +4,10 @@ var undefined; /** Used as the size to cover large array optimizations */ - var LARGE_ARRAY_SIZE = 200; + var largeArraySize = 200; + + /** Used as the maximum length an array-like object */ + var maxSafeInteger = Math.pow(2, 53) - 1; /** Used as a reference to the global object */ var root = typeof global == 'object' && global || this; @@ -25,7 +28,9 @@ push = Array.prototype.push, slice = Array.prototype.slice, system = root.system, - toString = Object.prototype.toString, + toString = Object.prototype.toString; + + var JSON = root.JSON, Worker = document && root.Worker; /** The file path of the Lo-Dash file to test */ @@ -78,8 +83,8 @@ /** Detect if testing `npm` modules */ var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]); - /** Detects if running in a PhantomJS web page */ - var isPhantomPage = typeof callPhantom == 'function'; + /** Detects if running in PhantomJS */ + var isPhantom = phantom || typeof callPhantom == 'function'; /** Detect if running in Rhino */ var isRhino = isJava && typeof global == 'function' && global().Array === root.Array; @@ -180,7 +185,7 @@ return result; }()); - /** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */ + /** Used to check problem JScript properties (a.k.a. the `[[DontEnum]]` bug) */ var shadowedProps = [ 'constructor', 'hasOwnProperty', @@ -262,6 +267,7 @@ "'_array': [1, 2, 3],", "'_boolean': new Boolean(false),", "'_date': new Date,", + "'_errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],", "'_function': function() {},", "'_nan': NaN,", "'_null': null,", @@ -269,7 +275,7 @@ "'_object': { 'a': 1, 'b': 2, 'c': 3 },", "'_regexp': /x/,", "'_string': new String('a'),", - "'_undefined': undefined,", + "'_undefined': undefined", '})' ].join('\n'))); } @@ -288,15 +294,12 @@ } // allow bypassing native checks var _fnToString = Function.prototype.toString; - setProperty(Function.prototype, 'toString', (function() { - function fnToString() { - setProperty(Function.prototype, 'toString', _fnToString); - var result = this === Set ? this.toString() : _fnToString.call(this); - setProperty(Function.prototype, 'toString', fnToString); - return result; - } - return fnToString; - }())); + setProperty(Function.prototype, 'toString', function wrapper() { + setProperty(Function.prototype, 'toString', _fnToString); + var result = this === Set ? this.toString() : _fnToString.call(this); + setProperty(Function.prototype, 'toString', wrapper); + return result; + }); // fake DOM setProperty(global, 'window', {}); @@ -318,7 +321,7 @@ var _now = Date.now; setProperty(Date, 'now', function() {}); - var _create = Object.create; + var _create = create; setProperty(Object, 'create', function() {}); var _defineProperty = Object.defineProperty; @@ -330,18 +333,17 @@ var _keys = Object.keys; setProperty(Object, 'keys', function() {}); + var _hasOwnProperty = Object.prototype.hasOwnProperty; + setProperty(Object.prototype, 'hasOwnProperty', function(key) { + if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0])) { + throw new Error; + } + return _hasOwnProperty.call(this, key); + }); + var _contains = String.prototype.contains; setProperty(String.prototype, 'contains', _contains ? function() {} : Boolean); - var _trim = String.prototype.trim; - setProperty(String.prototype, 'trim', _trim ? function() {} : String); - - var _trimLeft = String.prototype.trimLeft; - setProperty(String.prototype, 'trimLeft', _trimLeft ? function() {} : String); - - var _trimRight = String.prototype.trimRight; - setProperty(String.prototype, 'trimRight', _trimRight ? function() {} : String); - // clear cache so Lo-Dash can be reloaded emptyObject(require.cache); @@ -355,22 +357,14 @@ setProperty(Object, 'defineProperty', _defineProperty); setProperty(Object, 'getPrototypeOf', _getPrototypeOf); setProperty(Object, 'keys', _keys); + setProperty(Object.prototype, 'hasOwnProperty', _hasOwnProperty); setProperty(Function.prototype, 'toString', _fnToString); - _.forOwn({ - 'contains': _contains, - 'trim': _trim, - 'trimLeft': _trimLeft, - 'trimRight': _trimRight - }, - function(func, key) { - if (func) { - setProperty(String.prototype, key, func); - } else { - delete String.prototype[key]; - } - }); - + if (_contains) { + setProperty(String.prototype, 'contains', _contains); + } else { + delete String.prototype.contains; + } delete global.window; delete global.WinRTError; delete Function.prototype._method; @@ -393,6 +387,7 @@ 'parent._._boolean = new Boolean(false);', 'parent._._date = new Date;', "parent._._element = document.createElement('div');", + 'parent._._errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError];', 'parent._._function = function() {};', 'parent._._nan = NaN;', 'parent._._null = null;', @@ -428,7 +423,7 @@ (function() { test('supports loading ' + basename + ' as the "lodash" module', 1, function() { if (amd) { - equal((lodashModule || {}).moduleName, 'lodash'); + strictEqual((lodashModule || {}).moduleName, 'lodash'); } else { skipTest(); @@ -437,7 +432,7 @@ test('supports loading ' + basename + ' with the Require.js "shim" configuration option', 1, function() { if (amd && /requirejs/.test(ui.loaderPath)) { - equal((shimmedModule || {}).moduleName, 'shimmed'); + strictEqual((shimmedModule || {}).moduleName, 'shimmed'); } else { skipTest(); } @@ -445,7 +440,7 @@ test('supports loading ' + basename + ' as the "underscore" module', 1, function() { if (amd && !/dojo/.test(ui.loaderPath)) { - equal((underscoreModule || {}).moduleName, 'underscore'); + strictEqual((underscoreModule || {}).moduleName, 'underscore'); } else { skipTest(); @@ -463,7 +458,7 @@ setTimeout(attempt, 16); return; } - equal(actual, _.VERSION); + strictEqual(actual, _.VERSION); QUnit.start(); }; @@ -477,28 +472,27 @@ test('should not add `Function.prototype` extensions to lodash', 1, function() { if (lodashBizarro) { - equal('_method' in lodashBizarro, false); + ok(!('_method' in lodashBizarro)); } else { skipTest(); } }); - test('should avoid overwritten native methods', 12, function() { + test('should avoid overwritten native methods', 9, function() { function Foo() {} function message(methodName) { return '`_.' + methodName + '` should avoid overwritten native methods'; } - var object = { 'a': true }; - var largeArray = _.times(LARGE_ARRAY_SIZE, function() { - return object; - }); + var object = { 'a': 1 }, + otherObject = { 'b': 2 }, + largeArray = _.times(largeArraySize, _.constant(object)); if (lodashBizarro) { try { - actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'length': 0 })]; + var actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'length': 0 })]; } catch(e) { actual = null; } @@ -520,11 +514,11 @@ deepEqual(actual[1], {}, message('Object.create')); try { - var actual = lodashBizarro.bind(function() { return this.a; }, object); + actual = lodashBizarro.bind(function() { return this.a; }, object); } catch(e) { actual = null; } - equal(expando in actual, false, message('Object.defineProperty')); + ok(!(expando in actual), message('Object.defineProperty')); try { actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; @@ -542,14 +536,14 @@ try { actual = [ - lodashBizarro.difference([object], largeArray), + lodashBizarro.difference([object, otherObject], largeArray), lodashBizarro.intersection(largeArray, [object]), lodashBizarro.uniq(largeArray) ]; } catch(e) { actual = null; } - deepEqual(actual, [[], [object], [object]], message('Set')); + deepEqual(actual, [[otherObject], [object], [object]], message('Set')); try { actual = lodashBizarro.contains('abc', 'c'); @@ -557,23 +551,9 @@ actual = null; } strictEqual(actual, true, message('String#contains')); - - _.forEach(['trim', 'trimLeft', 'trimRight'], function(methodName) { - try { - var actual = [ - lodashBizarro[methodName](whitespace + 'a b c' + whitespace), - lodashBizarro[methodName](''), - lodashBizarro[methodName]('-_-a-b-c-_-', '_-'), - lodashBizarro[methodName]('', '_-') - ]; - } catch(e) { - actual = null; - } - ok(_.every(actual, _.isString), message('String#' + methodName)); - }); } else { - skipTest(12); + skipTest(9); } }); }()); @@ -589,7 +569,7 @@ test('should return provided `lodash` instances', 1,function() { var wrapped = _(false); - equal(_(wrapped), wrapped); + strictEqual(_(wrapped), wrapped); }); }()); @@ -598,18 +578,23 @@ QUnit.module('lodash.after'); (function() { + function after(n, times) { + var count = 0; + _.times(times, _.after(n, function() { count++; })); + return count; + } test('should create a function that executes `func` after `n` calls', 4, function() { - function after(n, times) { - var count = 0; - _.times(times, _.after(n, function() { count++; })); - return count; - } - strictEqual(after(5, 5), 1, 'after(n) should execute `func` after being called `n` times'); strictEqual(after(5, 4), 0, 'after(n) should not execute `func` unless called `n` times'); strictEqual(after(0, 0), 0, 'after(0) should not execute `func` immediately'); strictEqual(after(0, 1), 1, 'after(0) should execute `func` when called once'); }); + + test('should coerce non-finite `n` values to `0`', 3, function() { + _.each([-Infinity, NaN, Infinity], function(n) { + strictEqual(after(n, 1), 1); + }); + }); }()); /*--------------------------------------------------------------------------*/ @@ -626,7 +611,6 @@ this.a = 1; this.c = 3; } - Foo.prototype.b = 2; deepEqual(_.assign({}, new Foo), { 'a': 1, 'c': 3 }); }); @@ -647,14 +631,6 @@ deepEqual(_.assign({ 'a': 1, 'b': 2 }, expected), expected); }); - test('should not error on `null` or `undefined` sources (test in IE < 9)', 1, function() { - try { - deepEqual(_.assign({}, null, undefined, { 'a': 1 }), { 'a': 1 }); - } catch(e) { - ok(false); - } - }); - test('should work with a callback', 1, function() { var actual = _.assign({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) { return typeof a == 'undefined' ? b : a; @@ -694,8 +670,8 @@ var args = arguments; test('should return `undefined` for nonexistent keys', 1, function() { - var actual = _.at(['a', 'b', 'c'], [0, 2, 4]); - deepEqual(actual, ['a', 'c', undefined]); + var actual = _.at(['a', 'b', 'c'], [2, 4, 0]); + deepEqual(actual, ['c', undefined, 'a']); }); test('should return an empty array when no keys are provided', 1, function() { @@ -703,34 +679,27 @@ }); test('should accept multiple key arguments', 1, function() { - var actual = _.at(['a', 'b', 'c', 'd'], 0, 2, 3); - deepEqual(actual, ['a', 'c', 'd']); + var actual = _.at(['a', 'b', 'c', 'd'], 3, 0, 2); + deepEqual(actual, ['d', 'a', 'c']); }); test('should work with an `arguments` object for `collection`', 1, function() { - var actual = _.at(args, [0, 2]); - deepEqual(actual, ['a', 'c']); + var actual = _.at(args, [2, 0]); + deepEqual(actual, ['c', 'a']); }); test('should work with an object for `collection`', 1, function() { - var actual = _.at({ 'a': 1, 'b': 2, 'c': 3 }, ['a', 'c']); - deepEqual(actual, [1, 3]); - }); - - test('should work when used as a callback for `_.map`', 1, function() { - var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], - actual = _.map(array, _.at); - - deepEqual(actual, [[1], [5], [9]]); + var actual = _.at({ 'a': 1, 'b': 2, 'c': 3 }, ['c', 'a']); + deepEqual(actual, [3, 1]); }); - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, function(collection, key) { test('should work with a string ' + key + ' for `collection`', 1, function() { - deepEqual(_.at(collection, [0, 2]), ['a', 'c']); + deepEqual(_.at(collection, [2, 0]), ['c', 'a']); }); }); }('a', 'b', 'c')); @@ -757,7 +726,7 @@ var values = _.reject(falsey.slice(1), function(value) { return value == null; }), expected = _.map(values, function(value) { return [value]; }); - var actual = _.map(values, function(value, index) { + var actual = _.map(values, function(value) { try { var bound = _.bind(fn, value); return bound(); @@ -774,14 +743,14 @@ actual = bound('a'); ok(actual[0] === null || actual[0] && actual[0].Array); - equal(actual[1], 'a'); + strictEqual(actual[1], 'a'); _.times(2, function(index) { bound = index ? _.bind(fn, undefined) : _.bind(fn); actual = bound('b'); ok(actual[0] === undefined || actual[0] && actual[0].Array); - equal(actual[1], 'b'); + strictEqual(actual[1], 'b'); }); }); @@ -800,7 +769,7 @@ }); test('should support placeholders', 4, function() { - if (_._iteratorTemplate) { + if (!isModularize) { var object = {}, bound = _.bind(fn, object, _, 'b', _); @@ -815,7 +784,7 @@ }); test('should create a function with a `length` of `0`', 2, function() { - var func = function(a, b, c) {}, + var fn = function(a, b, c) {}, bound = _.bind(fn, {}); strictEqual(bound.length, 0); @@ -828,6 +797,7 @@ function Foo() { return this; } + var bound = _.bind(Foo, { 'a': 1 }), newBound = new bound; @@ -840,6 +810,7 @@ function Foo(value) { return value && object; } + var bound = _.bind(Foo), object = {}; @@ -854,10 +825,6 @@ deepEqual(bound(['b'], 'c'), [object, 'a', ['b'], 'c']); }); - test('should throw a TypeError if `func` is not a function', 1, function() { - raises(function() { _.bind(); }, TypeError); - }); - test('should return a wrapped value when chaining', 2, function() { if (!isNpm) { var object = {}, @@ -901,7 +868,6 @@ this._b = 2; this.a = function() { return this._a; }; } - Foo.prototype.b = function() { return this._b; }; var object = new Foo; @@ -985,35 +951,134 @@ var object = { 'name': 'fred', 'greet': function(greeting) { - return greeting + ' ' + this.name; + return this.name + ' says: ' + greeting; } }; - var func = _.bindKey(object, 'greet', 'hi'); - equal(func(), 'hi fred'); + var bound = _.bindKey(object, 'greet', 'hi'); + strictEqual(bound(), 'fred says: hi'); object.greet = function(greeting) { - return greeting + ' ' + this.name + '!'; + return this.name + ' says: ' + greeting + '!'; + }; + strictEqual(bound(), 'fred says: hi!'); + }); + + test('should support placeholders', 4, function() { + var object = { + 'fn': function fn(a, b, c, d) { + return slice.call(arguments); + } }; - equal(func(), 'hi fred!'); + + if (!isModularize) { + var bound = _.bindKey(object, 'fn', _, 'b', _); + deepEqual(bound('a', 'c'), ['a', 'b', 'c']); + deepEqual(bound('a'), ['a', 'b', undefined]); + deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']); + deepEqual(bound(), [undefined, 'b', undefined]); + } + else { + skipTest(4); + } }); }()); /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.capitalize'); + QUnit.module('case methods'); + + _.each(['camel', 'kebab', 'snake'], function(caseName) { + var methodName = caseName + 'Case', + func = _[methodName]; + + var expected = (function() { + switch (caseName) { + case 'camel': return 'helloWorld'; + case 'kebab': return 'hello-world'; + case 'snake': return 'hello_world'; + } + }()); + + var burredLetters = [ + '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', + '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', + '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', + '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF' + ]; + + var deburredLetters = [ + 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', + 'D', 'N', 'O', 'O', 'O', 'O', 'O', '', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th', 'ss', + 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', + 'd', 'n', 'o', 'o', 'o', 'o', 'o', '', 'o', 'u', 'u', 'u', 'u', 'y', 'th', 'y' + ]; + + test('`_.' + methodName + '` should convert `string` to ' + caseName + ' case', 4, function() { + _.each(['Hello world', 'helloWorld', '--hello-world', '__hello_world__'], function(string) { + strictEqual(func(string), expected); + }); + }); + + test('`_.' + methodName + '` should handle double-converting strings', 4, function() { + _.each(['Hello world', 'helloWorld', '--hello-world', '__hello_world__'], function(string) { + strictEqual(func(func(string)), expected); + }); + }); + + test('`_.' + methodName + '` should deburr letters', 1, function() { + var actual = _.map(burredLetters, function(burred, index) { + var isCamel = caseName == 'camel', + deburrLetter = deburredLetters[index]; + + var string = isCamel + ? func('z' + burred) + : func(burred); + + var deburredString = isCamel + ? 'z' + deburrLetter + : deburrLetter.toLowerCase(); + + return string == deburredString; + }); + + ok(_.every(actual, _.identity)); + }); + + test('`_.' + methodName + '` should coerce `string` to a string', 2, function() { + var string = 'Hello world'; + strictEqual(func(Object(string)), expected); + strictEqual(func({ 'toString': _.constant(string) }), expected); + }); + }); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.camelCase'); (function() { - test('should capitalize the first character of a string', 3, function() { - equal(_.capitalize('fred'), 'Fred'); - equal(_.capitalize('Fred'), 'Fred'); - equal(_.capitalize(' fred'), ' fred'); + test('should work with numbers', 3, function() { + strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit'); + strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles'); + strictEqual(_.camelCase('xhr2 request'), 'xhr2Request'); + }); + + test('should handle acronyms', 3, function() { + strictEqual(_.camelCase('safe HTML'), 'safeHTML'); + strictEqual(_.camelCase('escape HTML entities'), 'escapeHTMLEntities'); + strictEqual(_.camelCase('XMLHttpRequest'), 'xmlHttpRequest'); }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.capitalize'); - test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() { - strictEqual(_.capitalize(null), ''); - strictEqual(_.capitalize(undefined), ''); - strictEqual(_.capitalize(''), ''); + (function() { + test('should capitalize the first character of a string', 3, function() { + strictEqual(_.capitalize('fred'), 'Fred'); + strictEqual(_.capitalize('Fred'), 'Fred'); + strictEqual(_.capitalize(' fred'), ' fred'); }); }()); @@ -1035,7 +1100,7 @@ test('should return the existing wrapper when chaining', 1, function() { if (!isNpm) { var wrapper = _({ 'a': 0 }); - equal(wrapper.chain(), wrapper); + strictEqual(wrapper.chain(), wrapper); } else { skipTest(); @@ -1119,7 +1184,7 @@ Klass.prototype = { 'b': 1 }; var nonCloneable = { - 'an element': body, + 'a DOM element': body, 'a function': Klass }; @@ -1149,14 +1214,14 @@ actual = _.clone(expected); deepEqual(actual, expected); - ok(actual != expected && actual[0] === expected[0]); + ok(actual !== expected && actual[0] === expected[0]); }); test('`_.clone` should perform a shallow clone when used as a callback for `_.map`', 1, function() { var expected = [{ 'a': [0] }, { 'b': [1] }], actual = _.map(expected, _.clone); - ok(actual[0] != expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b); + ok(actual[0] !== expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b); }); test('`_.cloneDeep` should deep clone objects with circular references', 1, function() { @@ -1172,7 +1237,7 @@ ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object); }); - _.forEach([ + _.each([ 'clone', 'cloneDeep' ], @@ -1219,7 +1284,7 @@ return this[value]; }, { 'a': 'A' }); - equal(actual, 'A'); + strictEqual(actual, 'A'); }); test('`_.' + methodName + '` should handle cloning if `callback` returns `undefined`', 1, function() { @@ -1232,7 +1297,7 @@ actual = func(array); strictEqual(actual.index, 2); - equal(actual.input, 'vwxyz'); + strictEqual(actual.input, 'vwxyz'); }); test('`_.' + methodName + '` should deep clone `lastIndex` regexp property', 1, function() { @@ -1241,7 +1306,21 @@ regexp.exec('vwxyz'); var actual = func(regexp); - equal(actual.lastIndex, 3); + strictEqual(actual.lastIndex, 3); + }); + + test('`_.' + methodName + '` should not error on DOM elements', 1, function() { + if (document) { + var element = document.createElement('div'); + try { + strictEqual(func(element), element); + } catch(e) { + ok(false); + } + } + else { + skipTest(); + } }); }); }(1, 2, 3)); @@ -1277,7 +1356,7 @@ }; var welcome = _.compose(greet, format); - equal(welcome('pebbles'), 'Hiya Penelope!'); + strictEqual(welcome('pebbles'), 'Hiya Penelope!'); }); test('should return a new function', 1, function() { @@ -1327,40 +1406,59 @@ QUnit.module('lodash.contains'); (function() { - _.forEach({ + _.each({ 'an `arguments` object': arguments, - 'an array': [1, 2, 3, 1, 2, 3], - 'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3 }, - 'a string': '123123' + 'an array': [1, 2, 3, 4], + 'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, + 'a string': '1234' }, function(collection, key) { + var values = _.toArray(collection); + test('should work with ' + key + ' and return `true` for matched values', 1, function() { strictEqual(_.contains(collection, 3), true); }); test('should work with ' + key + ' and return `false` for unmatched values', 1, function() { - strictEqual(_.contains(collection, 4), false); + strictEqual(_.contains(collection, 5), false); }); - test('should work with ' + key + ' and a positive `fromIndex`', 1, function() { - strictEqual(_.contains(collection, 1, 2), true); + test('should work with ' + key + ' and a positive `fromIndex`', 2, function() { + strictEqual(_.contains(collection, values[2], 2), true); + strictEqual(_.contains(collection, values[1], 2), false); }); - test('should work with ' + key + ' and a `fromIndex` >= `collection.length`', 6, function() { - _.forEach([6, 8], function(fromIndex) { + test('should work with ' + key + ' and a `fromIndex` >= `collection.length`', 12, function() { + _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { strictEqual(_.contains(collection, 1, fromIndex), false); strictEqual(_.contains(collection, undefined, fromIndex), false); strictEqual(_.contains(collection, '', fromIndex), false); }); }); - test('should work with ' + key + ' and a negative `fromIndex`', 1, function() { - strictEqual(_.contains(collection, 2, -3), true); + test('should work with ' + key + ' and treat falsey `fromIndex` values as `0`', 1, function() { + var expected = _.map(falsey, _.constant(true)); + + var actual = _.map(falsey, function(fromIndex) { + return _.contains(collection, values[0], fromIndex); + }); + + deepEqual(actual, expected); + }); + + test('should work with ' + key + ' and treat non-number `fromIndex` values as `0`', 1, function() { + strictEqual(_.contains(collection, values[0], '1'), true); + }); + + test('should work with ' + key + ' and a negative `fromIndex`', 2, function() { + strictEqual(_.contains(collection, values[2], -2), true); + strictEqual(_.contains(collection, values[1], -2), false); }); - test('should work with ' + key + ' and a negative `fromIndex` <= negative `collection.length`', 2, function() { - strictEqual(_.contains(collection, 1, -6), true); - strictEqual(_.contains(collection, 2, -8), true); + test('should work with ' + key + ' and a negative `fromIndex` <= negative `collection.length`', 3, function() { + _.each([-4, -6, -Infinity], function(fromIndex) { + strictEqual(_.contains(collection, values[0], fromIndex), true); + }); }); test('should work with ' + key + ' and return an unwrapped value when chaining', 1, function() { @@ -1373,7 +1471,7 @@ }); }); - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -1391,7 +1489,7 @@ test('should be aliased', 1, function() { strictEqual(_.include, _.contains); }); - }(1, 2, 3, 1, 2, 3)); + }(1, 2, 3, 4)); /*--------------------------------------------------------------------------*/ @@ -1522,7 +1620,7 @@ test('should ignore primitive `prototype` arguments and use an empty object instead', 1, function() { var primitives = [true, null, 1, 'a', undefined], - expected = _.map(primitives, function() { return true; }); + expected = _.map(primitives, _.constant(true)); var actual = _.map(primitives, function(value, index) { return _.isPlainObject(index ? _.create(value) : _.create()); @@ -1537,28 +1635,60 @@ QUnit.module('lodash.callback'); (function() { - test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() { - var fn = function() { - var result = [this.a]; - push.apply(result, arguments); - return result; - }; + test('should create a callback with a falsey `thisArg`', 1, function() { + var values = _.map(falsey, function(value) { + return Object(value == null ? root : value); + }); - var expected = [1, 2, 3], - object = { 'a': 1 }, - callback = _.createCallback(_.partial(fn, 2), object); + var actual = _.map(values, function(value) { + var callback = _.callback(function() { return this; }, value); + return callback(); + }); - deepEqual(callback(3), expected); + deepEqual(actual, values); + }); - callback = _.createCallback(_.partialRight(fn, 3), object); - deepEqual(callback(2), expected); + test('should return `_.identity` when `func` is nullish', 2, function() { + var object = {}; + _.each([null, undefined], function(value) { + var callback = _.callback(value); + strictEqual(callback(object), object); + }); + }); + + test('should not error when `func` is nullish and a `thisArg` is provided', 2, function() { + var object = {}; + _.each([null, undefined], function(value) { + try { + var callback = _.callback(value, {}); + strictEqual(callback(object), object); + } catch(e) { + ok(false); + } + }); + }); + + test('should return a callback created by `_.matches` when `func` is an object', 2, function() { + var callback = _.callback({ 'a': 1 }); + strictEqual(callback({ 'a': 1, 'b': 2 }), true); + strictEqual(callback({}), false); + }); + + test('should return a callback created by `_.property` when `func` is a number or string', 2, function() { + var array = ['a'], + callback = _.callback(0); + + strictEqual(callback(array), 'a'); + + callback = _.callback('0'); + strictEqual(callback(array), 'a'); }); test('should work without an `argCount`', 1, function() { var args, expected = ['a', 'b', 'c', 'd', 'e']; - var callback = _.createCallback(function() { + var callback = _.callback(function() { args = slice.call(arguments); }); @@ -1566,6 +1696,23 @@ deepEqual(args, expected); }); + test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() { + function fn() { + var result = [this.a]; + push.apply(result, arguments); + return result; + } + + var expected = [1, 2, 3], + object = { 'a': 1 }, + callback = _.callback(_.partial(fn, 2), object); + + deepEqual(callback(3), expected); + + callback = _.callback(_.partialRight(fn, 3), object); + deepEqual(callback(2), expected); + }); + test('should return the function provided if already bound with `Function#bind`', 1, function() { function a() {} @@ -1574,7 +1721,7 @@ if (bound && !('prototype' in bound)) { var bound = a.bind(object); - strictEqual(_.createCallback(bound, object), bound); + strictEqual(_.callback(bound, object), bound); } else { skipTest(); @@ -1588,8 +1735,8 @@ var object = {}; if (_.support.funcDecomp) { - strictEqual(_.createCallback(a, object), a); - notStrictEqual(_.createCallback(b, object), b); + strictEqual(_.callback(a, object), a); + notStrictEqual(_.callback(b, object), b); } else { skipTest(2); @@ -1598,21 +1745,21 @@ test('should only write metadata to named functions', 3, function() { function a() {}; + var b = function() {}; function c() {}; - var b = function() {}, - object = {}; + var object = {}; if (defineProperty && _.support.funcDecomp) { - _.createCallback(a, object); + _.callback(a, object); ok(expando in a); - _.createCallback(b, object); - equal(expando in b, false); + _.callback(b, object); + ok(!(expando in b)); if (_.support.funcNames) { _.support.funcNames = false; - _.createCallback(c, object); + _.callback(c, object); ok(expando in c); _.support.funcNames = true; @@ -1630,8 +1777,8 @@ function a() {}; if (defineProperty && lodashBizarro) { - lodashBizarro.createCallback(a, {}); - equal(expando in a, false); + lodashBizarro.callback(a, {}); + ok(!(expando in a)); } else { skipTest(); @@ -1645,25 +1792,42 @@ (function() { function fn(a, b, c, d) { - return a + b + c + d; + return slice.call(arguments); } test('should curry based on the number of arguments provided', 3, function() { - var curried = _.curry(fn); - equal(curried(1)(2)(3)(4), 10); - equal(curried(1, 2)(3, 4), 10); - equal(curried(1, 2, 3, 4), 10); + var curried = _.curry(fn), + expected = [1, 2, 3, 4]; + + deepEqual(curried(1)(2)(3)(4), expected); + deepEqual(curried(1, 2)(3, 4), expected); + deepEqual(curried(1, 2, 3, 4), expected); }); test('should work with partialed methods', 2, function() { var curried = _.curry(fn), - a = _.partial(curried, 1), + expected = [1, 2, 3, 4]; + + var a = _.partial(curried, 1), b = _.bind(a, null, 2), c = _.partialRight(b, 4), d = _.partialRight(b(3), 4); - equal(c(3), 10); - equal(d(), 10); + deepEqual(c(3), expected); + deepEqual(d(), expected); + }); + + test('should support placeholders', 4, function() { + if (!isModularize) { + var curried = _.curry(fn); + deepEqual(curried(1)(_, 3)(_, 4)(2), [1, 2, 3, 4]); + deepEqual(curried(_, 2)(1)(_, 4)(3), [1, 2, 3, 4]); + deepEqual(curried(_, _, 3)(_, 2)(_, 4)(1), [1, 2, 3, 4]); + deepEqual(curried(_, _, _, 4)(_, _, 3)(_, 2)(1), [1, 2, 3, 4]); + } + else { + skipTest(4); + } }); test('should return a function with a `length` of `0`', 6, function() { @@ -1679,6 +1843,7 @@ function Foo(value) { return value && object; } + var curried = _.curry(Foo), object = {}; @@ -1687,24 +1852,26 @@ }); test('should not alter the `this` binding', 9, function() { - var fn = function(a, b, c) { + function fn(a, b, c) { var value = this || {}; - return value[a] + value[b] + value[c]; - }; + return [value[a], value[b], value[c]]; + } - var object = { 'a': 1, 'b': 2, 'c': 3 }; - equal(_.curry(_.bind(fn, object), 3)('a')('b')('c'), 6); - equal(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), 6); - equal(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), 6); + var object = { 'a': 1, 'b': 2, 'c': 3 }, + expected = [1, 2, 3]; - ok(_.isEqual(_.bind(_.curry(fn), object)('a')('b')('c'), NaN)); - ok(_.isEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), NaN)); - equal(_.bind(_.curry(fn), object)('a', 'b', 'c'), 6); + deepEqual(_.curry(_.bind(fn, object), 3)('a')('b')('c'), expected); + deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), expected); + deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), expected); + + deepEqual(_.bind(_.curry(fn), object)('a')('b')('c'), Array(3)); + deepEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), Array(3)); + deepEqual(_.bind(_.curry(fn), object)('a', 'b', 'c'), expected); object.curried = _.curry(fn); - ok(_.isEqual(object.curried('a')('b')('c'), NaN)); - ok(_.isEqual(object.curried('a', 'b')('c'), NaN)); - equal(object.curried('a', 'b', 'c'), 6); + deepEqual(object.curried('a')('b')('c'), Array(3)); + deepEqual(object.curried('a', 'b')('c'), Array(3)); + deepEqual(object.curried('a', 'b', 'c'), expected); }); }()); @@ -1722,10 +1889,10 @@ debounced(); debounced(); - equal(count, 0); + strictEqual(count, 0); setTimeout(function() { - equal(count, 1); + strictEqual(count, 1); QUnit.start(); }, 96); } @@ -1796,12 +1963,12 @@ } }); - asyncTest('should work with `leading` option', 7, function() { + asyncTest('should support a `leading` option', 7, function() { if (!(isRhino && isModularize)) { var withLeading, counts = [0, 0, 0]; - _.forEach([true, { 'leading': true }], function(options, index) { + _.each([true, { 'leading': true }], function(options, index) { var debounced = _.debounce(function(value) { counts[index]++; return value; @@ -1810,10 +1977,10 @@ if (index == 1) { withLeading = debounced; } - equal(debounced('x'), 'x'); + strictEqual(debounced('x'), 'x'); }); - _.forEach([false, { 'leading': false }], function(options) { + _.each([false, { 'leading': false }], function(options) { var withoutLeading = _.debounce(_.identity, 32, options); strictEqual(withoutLeading('x'), undefined); }); @@ -1831,7 +1998,7 @@ deepEqual(counts, [1, 1, 2]); withLeading('x'); - equal(counts[1], 2); + strictEqual(counts[1], 2); QUnit.start(); }, 64); @@ -1842,7 +2009,7 @@ } }); - asyncTest('should work with `trailing` option', 4, function() { + asyncTest('should support a `trailing` option', 4, function() { if (!(isRhino && isModularize)) { var withCount = 0, withoutCount = 0; @@ -1872,9 +2039,9 @@ } }); - test('should work with `maxWait` option', 2, function() { + test('should support a `maxWait` option', 2, function() { if (!(isRhino && isModularize)) { - var limit = (argv || isPhantomPage) ? 1000 : 256, + var limit = (argv || isPhantom) ? 1000 : 256, withCount = 0, withoutCount = 0; @@ -1938,7 +2105,7 @@ } } setTimeout(function() { - equal(count, 2); + strictEqual(count, 2); deepEqual(args, [object, 'a']); QUnit.start(); }, 64); @@ -1964,7 +2131,6 @@ this.a = 1; this.c = 3; } - Foo.prototype.b = 2; deepEqual(_.defaults({ 'c': 2 }, new Foo), { 'a': 1, 'c': 2 }); }); @@ -1984,14 +2150,6 @@ var actual = _.defaults({ 'a': undefined }, { 'a': 1 }); strictEqual(actual.a, 1); }); - - test('should not error on `null` or `undefined` sources (test in IE < 9)', 1, function() { - try { - deepEqual(_.defaults({ 'a': 1 }, null, undefined, { 'a': 2, 'b': 2 }), { 'a': 1, 'b': 2 }); - } catch(e) { - ok(false); - } - }); }()); /*--------------------------------------------------------------------------*/ @@ -2127,6 +2285,8 @@ QUnit.module('lodash.difference'); (function() { + var args = arguments; + test('should return the difference of the given arrays', 2, function() { var actual = _.difference([1, 2, 3, 4, 5], [5, 2, 10]); deepEqual(actual, [1, 3, 4]); @@ -2136,8 +2296,8 @@ }); test('should work with large arrays', 1, function() { - var array1 = _.range(LARGE_ARRAY_SIZE), - array2 = array1.slice(), + var array1 = _.range(largeArraySize + 1), + array2 = _.range(largeArraySize), a = {}, b = {}, c = {}; @@ -2145,22 +2305,73 @@ array1.push(a, b, c); array2.push(b, c, a); - deepEqual(_.difference(array1, array2), []); + deepEqual(_.difference(array1, array2), [largeArraySize]); }); test('should work with large arrays of objects', 1, function() { - var object = {}; + var object1 = {}, + object2 = {}, + largeArray = _.times(largeArraySize, _.constant(object1)); + + deepEqual(_.difference([object1, object2], largeArray), [object2]); + }); + + test('should ignore values that are not arrays or `arguments` objects', 3, function() { + var array = [0, 1, null, 3]; + deepEqual(_.difference(array, 3, null, { '0': 1 }), array); + deepEqual(_.difference(null, array, null, [2, 1]), [0, null, 3]); + deepEqual(_.difference(null, array, null, args), [0, null]); + }); + }(1, 2, 3)); - var largeArray = _.times(LARGE_ARRAY_SIZE, function() { - return object; + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.endsWith'); + + (function() { + var string = 'abc'; + + test('should return `true` if a string ends with `target`', 1, function() { + strictEqual(_.endsWith(string, 'c'), true); + }); + + test('should return `false` if a string does not end with `target`', 1, function() { + strictEqual(_.endsWith(string, 'b'), false); + }); + + test('should work with a `position` argument', 1, function() { + strictEqual(_.endsWith(string, 'b', 2), true); + }); + + test('should work with `position` >= `string.length`', 4, function() { + _.each([3, 5, maxSafeInteger, Infinity], function(position) { + strictEqual(_.endsWith(string, 'c', position), true); + }); + }); + + test('should treat falsey `position` values, except `undefined`, as `0`', 1, function() { + var expected = _.map(falsey, _.constant(true)); + + var actual = _.map(falsey, function(position) { + return _.endsWith(string, position === undefined ? 'c' : '', position); }); - deepEqual(_.difference(largeArray, [object]), []); + deepEqual(actual, expected); + }); + + test('should treat a negative `position` as `0`', 6, function() { + _.each([-1, -3, -Infinity], function(position) { + ok(_.every(string, function(chr) { + return _.endsWith(string, chr, position) === false; + })); + strictEqual(_.endsWith(string, '', position), true); + }); }); - test('should ignore individual secondary values', 1, function() { - var array = [1, null, 3]; - deepEqual(_.difference(array, null, 3), array); + test('should always return `true` when `target` is an empty string regardless of `position`', 1, function() { + ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, maxSafeInteger, Infinity], function(position) { + return _.endsWith(string, '', position, true); + })); }); }()); @@ -2173,21 +2384,36 @@ unescaped = '&<>"\'\/'; test('should escape values', 1, function() { - equal(_.escape(unescaped), escaped); + strictEqual(_.escape(unescaped), escaped); }); test('should not escape the "/" character', 1, function() { - equal(_.escape('/'), '/'); + strictEqual(_.escape('/'), '/'); }); test('should handle strings with nothing to escape', 1, function() { - equal(_.escape('abc'), 'abc'); + strictEqual(_.escape('abc'), 'abc'); + }); + + test('should escape the same characters unescaped by `_.unescape`', 1, function() { + strictEqual(_.escape(_.unescape(escaped)), escaped); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.escapeRegExp'); + + (function() { + test('should escape values', 1, function() { + var escaped = '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\/\\\\', + unescaped = '.*+?^${}()|[\]\/\\'; + + strictEqual(_.escapeRegExp(unescaped), escaped); }); - test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() { - strictEqual(_.escape(null), ''); - strictEqual(_.escape(undefined), ''); - strictEqual(_.escape(''), ''); + test('should handle strings with nothing to escape', 1, function() { + strictEqual(_.escapeRegExp('abc'), 'abc'); }); }()); @@ -2197,7 +2423,7 @@ (function() { test('should return `true` for empty or falsey collections', 1, function() { - var expected = _.map(empties, function() { return true; }); + var expected = _.map(empties, _.constant(true)); var actual = _.map(empties, function(value) { try { @@ -2208,7 +2434,7 @@ deepEqual(actual, expected); }); - test('should return `true` if the callback returns truey for all elements in the collection', 1, function() { + test('should return `true` if the callback returns truthy for all elements in the collection', 1, function() { strictEqual(_.every([true, 1, 'x'], _.identity), true); }); @@ -2234,12 +2460,13 @@ QUnit.module('source property checks'); - _.forEach(['assign', 'defaults', 'merge'], function(methodName) { + _.each(['assign', 'defaults', 'merge'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should not assign inherited `source` properties', 1, function() { function Foo() {} Foo.prototype = { 'a': 1 }; + deepEqual(func({}, new Foo), {}); }); @@ -2261,7 +2488,7 @@ expected[1] = undefined; - ok(1 in actual); + ok('1' in actual); deepEqual(actual, expected); }); } @@ -2271,7 +2498,7 @@ QUnit.module('strict mode checks'); - _.forEach(['assign', 'bindAll', 'defaults'], function(methodName) { + _.each(['assign', 'bindAll', 'defaults'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should not throw strict mode errors', 1, function() { @@ -2302,7 +2529,7 @@ QUnit.module('lodash.filter'); (function() { - test('should return elements the `callback` returns truey for', 1, function() { + test('should return elements the `callback` returns truthy for', 1, function() { var actual = _.filter([1, 2, 3], function(num) { return num % 2; }); @@ -2338,25 +2565,26 @@ /*--------------------------------------------------------------------------*/ - (function() { - var objects = [ - { 'a': 0, 'b': 0 }, - { 'a': 1, 'b': 1 }, - { 'a': 2, 'b': 2 } - ]; + _.each(['find', 'findLast', 'findIndex', 'findLastIndex', 'findKey', 'findLastKey'], function(methodName) { + QUnit.module('lodash.' + methodName); - _.forEach({ - 'find': [objects[1], undefined, objects[2], objects[1]], - 'findLast': [objects[2], undefined, objects[2], objects[2]], - 'findIndex': [1, -1, 2, 1], - 'findLastIndex': [2, -1, 2, 2], - 'findKey': ['1', undefined, '2', '1'], - 'findLastKey': ['2', undefined, '2', '2'] - }, - function(expected, methodName) { - QUnit.module('lodash.' + methodName); + var func = _[methodName]; - var func = _[methodName]; + (function() { + var objects = [ + { 'a': 0, 'b': 0 }, + { 'a': 1, 'b': 1 }, + { 'a': 2, 'b': 2 } + ]; + + var expected = ({ + 'find': [objects[1], undefined, objects[2], objects[1]], + 'findLast': [objects[2], undefined, objects[2], objects[2]], + 'findIndex': [1, -1, 2, 1], + 'findLastIndex': [2, -1, 2, 2], + 'findKey': ['1', undefined, '2', '1'], + 'findLastKey': ['2', undefined, '2', '2'] + })[methodName]; test('should return the correct value', 1, function() { strictEqual(func(objects, function(object) { return object.a; }), expected[0]); @@ -2367,15 +2595,7 @@ }); test('should return `' + expected[1] + '` if value is not found', 1, function() { - strictEqual(func(objects, function(object) { return object.a == 3; }), expected[1]); - }); - - test('should work with an object for `collection`', 1, function() { - var actual = _.find({ 'a': 1, 'b': 2, 'c': 3 }, function(num) { - return num > 2; - }); - - equal(actual, 3); + strictEqual(func(objects, function(object) { return object.a === 3; }), expected[1]); }); test('should work with an object for `callback`', 1, function() { @@ -2391,7 +2611,7 @@ emptyValues = /Index/.test(methodName) ? _.reject(empties, _.isPlainObject) : empties, expecting = _.map(emptyValues, function() { return expected[1]; }); - _.forEach(emptyValues, function(value) { + _.each(emptyValues, function(value) { try { actual.push(func(value, { 'a': 3 })); } catch(e) { } @@ -2399,13 +2619,89 @@ deepEqual(actual, expecting); }); + }()); + + (function() { + var expected = ({ + 'find': 1, + 'findLast': 2, + 'findKey': 'a', + 'findLastKey': 'b' + })[methodName]; + + if (expected != null) { + test('should work with an object for `collection`', 1, function() { + var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(num) { + return num < 3; + }); + + strictEqual(actual, expected); + }); + } + }()); + (function() { + var expected = ({ + 'find': 'a', + 'findLast': 'b', + 'findIndex': 0, + 'findLastIndex': 1 + })[methodName]; + + if (expected != null) { + test('should work with a string for `collection`', 1, function() { + var actual = func('abc', function(chr, index) { + return index < 2; + }); + + strictEqual(actual, expected); + }); + } if (methodName == 'find') { - test('should be aliased', 2, function() { + test('should be aliased', 1, function() { strictEqual(_.detect, func); - strictEqual(_.findWhere, func); }); } + }()); + }); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.findWhere'); + + (function() { + var objects = [ + { 'a': 1 }, + { 'a': 1 }, + { 'a': 1, 'b': 2 }, + { 'a': 2, 'b': 2 }, + { 'a': 3 } + ]; + + test('should filter by `source` properties', 6, function() { + strictEqual(_.findWhere(objects, { 'a': 1 }), objects[0]); + strictEqual(_.findWhere(objects, { 'a': 2 }), objects[3]); + strictEqual(_.findWhere(objects, { 'a': 3 }), objects[4]); + strictEqual(_.findWhere(objects, { 'b': 1 }), undefined); + strictEqual(_.findWhere(objects, { 'b': 2 }), objects[2]); + strictEqual(_.findWhere(objects, { 'a': 1, 'b': 2 }), objects[2]); + }); + + test('should work with a function for `source`', 1, function() { + function source() {} + source.a = 2; + + strictEqual(_.findWhere(objects, source), objects[3]); + }); + + test('should match all elements when provided an empty `source`', 1, function() { + var expected = _.map(empties, _.constant(true)); + + var actual = _.map(empties, function(value) { + return _.findWhere(objects, value) === objects[0]; + }); + + deepEqual(actual, expected); }); }()); @@ -2430,14 +2726,26 @@ deepEqual(_.first(array, 2), [1, 2]); }); + test('should treat falsey `n` values, except nullish, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value == null ? 1 : []; + }); + + var actual = _.map(falsey, function(n) { + return _.first(array, n); + }); + + deepEqual(actual, expected); + }); + test('should return an empty array when `n` < `1`', 3, function() { - _.forEach([0, -1, -2], function(n) { + _.each([0, -1, -Infinity], function(n) { deepEqual(_.first(array, n), []); }); }); - test('should return all elements when `n` >= `array.length`', 2, function() { - _.forEach([3, 4], function(n) { + test('should return all elements when `n` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { deepEqual(_.first(array, n), array); }); }); @@ -2593,26 +2901,22 @@ expected.push(undefined, undefined, undefined); deepEqual(actual1, expected); - ok(4 in actual1); + ok('4' in actual1); deepEqual(actual2, expected); - ok(4 in actual2); + ok('4' in actual2); }); test('should work with extremely large arrays', 1, function() { - var expected = Array(5e5), - pass = true; - + // test in modern browsers if (freeze) { try { - var actual = _.flatten([expected]); + var expected = Array(5e5), + actual = _.flatten([expected]); + + deepEqual(actual, expected) } catch(e) { - pass = false; - } - if (pass) { - deepEqual(actual, expected); - } else { - ok(pass); + ok(false); } } else { skipTest(); @@ -2655,10 +2959,11 @@ QUnit.module('forEach methods'); - _.forEach(['forEach', 'forEachRight'], function(methodName) { - var func = _[methodName]; + _.each(['forEach', 'forEachRight'], function(methodName) { + var func = _[methodName], + isForEach = methodName == 'forEach'; - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -2672,7 +2977,7 @@ values.push(value); }); - if (methodName == 'forEach') { + if (isForEach) { deepEqual(args, ['a', 0, collection]); deepEqual(values, ['a', 'b', 'c']); } else { @@ -2683,7 +2988,7 @@ }); test('`_.' + methodName + '` should be aliased', 1, function() { - if (methodName == 'forEach') { + if (isForEach) { strictEqual(_.each, _.forEach); } else { strictEqual(_.eachRight, _.forEachRight); @@ -2695,7 +3000,7 @@ QUnit.module('forIn methods'); - _.forEach(['forIn', 'forInRight'], function(methodName) { + _.each(['forIn', 'forInRight'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` iterates over inherited properties', 1, function() { @@ -2712,7 +3017,7 @@ QUnit.module('forOwn methods'); - _.forEach(['forOwn', 'forOwnRight'], function(methodName) { + _.each(['forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; test('iterates over the `length` property', 1, function() { @@ -2730,15 +3035,20 @@ (function() { var methods = [ + 'countBy', 'every', 'filter', - 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', + 'groupBy', + 'indexBy', 'map', + 'max', + 'min', + 'partition', 'reject', 'some' ]; @@ -2748,6 +3058,26 @@ 'some' ]; + var collectionMethods = [ + 'countBy', + 'every', + 'filter', + 'find', + 'findLast', + 'forEach', + 'forEachRight', + 'groupBy', + 'indexBy', + 'map', + 'max', + 'min', + 'partition', + 'reduce', + 'reduceRight', + 'reject', + 'some' + ]; + var forInMethods = [ 'forIn', 'forInRight' @@ -2775,7 +3105,7 @@ 'forOwnRight' ]; - _.forEach(methods, function(methodName) { + _.each(methods, function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -2803,22 +3133,21 @@ function callback(num, index) { actual = this[index]; } - func([1], callback, [2]); - equal(actual, 2); + strictEqual(actual, 2); func({ 'a': 1 }, callback, { 'a': 2 }); - equal(actual, 2); + strictEqual(actual, 2); }); }); - _.forEach(_.difference(methods, boolMethods), function(methodName) { + _.each(_.difference(methods, boolMethods), function(methodName) { var array = [1, 2, 3], func = _[methodName]; test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() { if (!isNpm) { - var actual = _(array)[methodName](noop); + var actual = _(array)[methodName](_.noop); ok(actual instanceof _); } else { @@ -2827,7 +3156,7 @@ }); }); - _.forEach(_.difference(methods, forInMethods), function(methodName) { + _.each(_.difference(methods, forInMethods), function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -2841,34 +3170,56 @@ }); }); - _.forEach(iterationMethods, function(methodName) { + _.each(iterationMethods, function(methodName) { var array = [1, 2, 3], func = _[methodName]; test('`_.' + methodName + '` should return the collection', 1, function() { - equal(func(array, Boolean), array); + strictEqual(func(array, Boolean), array); }); test('`_.' + methodName + '` should return the existing wrapper when chaining', 1, function() { if (!isNpm) { var wrapper = _(array); - equal(wrapper[methodName](noop), wrapper); + strictEqual(wrapper[methodName](_.noop), wrapper); } else { skipTest(); } }); }); + + _.each(collectionMethods, function(methodName) { + var func = _[methodName]; + + test('`_.' + methodName + '` should treat objects with lengths of `0` as array-like', 1, function() { + var pass = true; + func({ 'length': 0 }, function() { pass = false; }, 0); + ok(pass); + }); + + test('`_.' + methodName + '` should not treat objects with negative lengths as array-like', 1, function() { + var pass = false; + func({ 'length': -1 }, function() { pass = true; }, 0); + ok(pass); + }); + + test('`_.' + methodName + '` should not treat objects with non-number lengths as array-like', 1, function() { + var pass = false; + func({ 'length': '0' }, function() { pass = true; }, 0); + ok(pass); + }); + }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('collection iteration bugs'); - _.forEach(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { + _.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; - test('`_.' + methodName + '` fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { + test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { var props = []; func(shadowedObject, function(value, prop) { props.push(prop); }); deepEqual(props.sort(), shadowedProps); @@ -2925,13 +3276,17 @@ QUnit.module('object assignments'); - _.forEach(['assign', 'defaults', 'merge'], function(methodName) { + _.each(['assign', 'defaults', 'merge'], function(methodName) { var func = _[methodName]; + test('`_.' + methodName + '` should return `undefined` when no destination object is provided', 1, function() { + strictEqual(func(), undefined); + }); + test('`_.' + methodName + '` should return the existing wrapper when chaining', 1, function() { if (!isNpm) { var wrapper = _({ 'a': 1 }); - equal(wrapper[methodName]({ 'b': 2 }), wrapper); + strictEqual(wrapper[methodName]({ 'b': 2 }), wrapper); } else { skipTest(); @@ -2961,10 +3316,9 @@ test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { function Foo() {} - Foo.prototype.c = 3; - Foo.a = 1; Foo.b = 2; + Foo.prototype.c = 3; var expected = { 'a': 1, 'b': 2 }; deepEqual(func({}, Foo), expected); @@ -2977,9 +3331,31 @@ var array = [{ 'b': 2 }, { 'c': 3 }]; deepEqual(_.reduce(array, func, { 'a': 1}), { 'a': 1, 'b': 2, 'c': 3 }); }); + + test('`_.' + methodName + '` should not error on nullish sources (test in IE < 9)', 1, function() { + try { + deepEqual(func({ 'a': 1 }, undefined, { 'b': 2 }, null), { 'a': 1, 'b': 2 }); + } catch(e) { + ok(false); + } + }); + + test('`_.' + methodName + '` should not error when `object` is nullish and source objects are provided', 1, function() { + var expected = _.times(2, _.constant(true)); + + var actual = _.map([null, undefined], function(value) { + try { + return _.isEqual(func(value, { 'a': 1 }), value); + } catch(e) { + return false; + } + }); + + deepEqual(actual, expected); + }); }); - _.forEach(['assign', 'merge'], function(methodName) { + _.each(['assign', 'merge'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should pass the correct `callback` arguments', 2, function() { @@ -3026,7 +3402,7 @@ QUnit.module('exit early'); - _.forEach(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { + _.each(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; if (!func) { return; @@ -3044,7 +3420,7 @@ values = []; func(object, function(value) { values.push(value); return false; }); - equal(values.length, 1); + strictEqual(values.length, 1); }); }); @@ -3058,7 +3434,7 @@ stringObject = Object(stringLiteral), expected = [stringLiteral, stringObject]; - var largeArray = _.times(LARGE_ARRAY_SIZE, function(count) { + var largeArray = _.times(largeArraySize, function(count) { return count % 2 ? stringObject : stringLiteral; }); @@ -3068,7 +3444,7 @@ deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []); }); - test('lodash.memoize should memoize values resolved to the `__proto__` key', 1, function() { + test('lodash.memoize should support values that resolve to the `__proto__` key', 1, function() { var count = 0, memoized = _.memoize(function() { return ++count; }); @@ -3084,7 +3460,7 @@ (function() { test('should return the function names of an object', 1, function() { - var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.forEach }; + var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.each }; deepEqual(_.functions(object), ['b', 'd']); }); @@ -3093,8 +3469,7 @@ this.a = _.identity; this.b = 'b' } - - Foo.prototype.c = noop; + Foo.prototype.c = _.noop; deepEqual(_.functions(new Foo), ['a', 'c']); }); @@ -3196,7 +3571,7 @@ test('should return `false` for primitives', 1, function() { var values = falsey.concat(1, 'a'), - expected = _.map(values, function() { return false; }); + expected = _.map(values, _.constant(false)); var actual = _.map(values, function(value) { return _.has(value, 'valueOf'); @@ -3272,43 +3647,54 @@ var array = [1, 2, 3, 1, 2, 3]; test('should return the index of the first matched value', 1, function() { - equal(_.indexOf(array, 3), 2); + strictEqual(_.indexOf(array, 3), 2); }); test('should return `-1` for an unmatched value', 4, function() { - equal(_.indexOf(array, 4), -1); - equal(_.indexOf(array, 4, true), -1); + strictEqual(_.indexOf(array, 4), -1); + strictEqual(_.indexOf(array, 4, true), -1); var empty = []; - equal(_.indexOf(empty, undefined), -1); - equal(_.indexOf(empty, undefined, true), -1); + strictEqual(_.indexOf(empty, undefined), -1); + strictEqual(_.indexOf(empty, undefined, true), -1); }); test('should work with a positive `fromIndex`', 1, function() { - equal(_.indexOf(array, 1, 2), 3); + strictEqual(_.indexOf(array, 1, 2), 3); }); - test('should work with `fromIndex` >= `array.length`', 6, function() { - _.forEach([6, 8], function(fromIndex) { - equal(_.indexOf(array, 1, fromIndex), -1); - equal(_.indexOf(array, undefined, fromIndex), -1); - equal(_.indexOf(array, '', fromIndex), -1); + test('should work with `fromIndex` >= `array.length`', 12, function() { + _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { + strictEqual(_.indexOf(array, 1, fromIndex), -1); + strictEqual(_.indexOf(array, undefined, fromIndex), -1); + strictEqual(_.indexOf(array, '', fromIndex), -1); }); }); - test('should work with a negative `fromIndex`', 1, function() { - equal(_.indexOf(array, 2, -3), 4); - }); + test('should treat falsey `fromIndex` values as `0`', 1, function() { + var expected = _.map(falsey, _.constant(0)); + + var actual = _.map(falsey, function(fromIndex) { + return _.indexOf(array, 1, fromIndex); + }); - test('should work with a negative `fromIndex` <= `-array.length`', 2, function() { - strictEqual(_.indexOf(array, 1, -6), 0); - strictEqual(_.indexOf(array, 2, -8), 1); + deepEqual(actual, expected); }); - test('should ignore non-number `fromIndex` values', 1, function() { + test('should treat non-number `fromIndex` values as `0`', 1, function() { strictEqual(_.indexOf([1, 2, 3], 1, '1'), 0); }); + test('should work with a negative `fromIndex`', 1, function() { + strictEqual(_.indexOf(array, 2, -3), 4); + }); + + test('should work with a negative `fromIndex` <= `-array.length`', 3, function() { + _.each([-6, -8, -Infinity], function(fromIndex) { + strictEqual(_.indexOf(array, 1, fromIndex), 0); + }); + }); + test('should work with `isSorted`', 1, function() { strictEqual(_.indexOf([1, 2, 3], 1, true), 0); }); @@ -3319,6 +3705,8 @@ QUnit.module('custom `_.indexOf` methods'); (function() { + function Foo() {} + function custom(array, value, fromIndex) { var index = (fromIndex || 0) - 1, length = array.length; @@ -3332,23 +3720,22 @@ return -1; } - function Foo() {} - var array = [1, new Foo, 3, new Foo], indexOf = _.indexOf; - var largeArray = _.times(LARGE_ARRAY_SIZE, function() { + var largeArray = _.times(largeArraySize, function() { return new Foo; }); - test('`_.contains` should work with a custom `_.indexOf` method', 1, function() { + test('`_.contains` should work with a custom `_.indexOf` method', 2, function() { if (!isModularize) { _.indexOf = custom; ok(_.contains(array, new Foo)); + ok(_.contains({ 'a': 1, 'b': new Foo, 'c': 3 }, new Foo)); _.indexOf = indexOf; } else { - skipTest(); + skipTest(2); } }); @@ -3403,7 +3790,7 @@ ]; test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, function() { return []; }); + var expected = _.map(falsey, _.constant([])); var actual = _.map(falsey, function(value, index) { try { @@ -3426,14 +3813,26 @@ deepEqual(_.initial([]), []); }); + test('should treat falsey `n` values, except nullish, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value == null ? [1, 2] : array; + }); + + var actual = _.map(falsey, function(n) { + return _.initial(array, n); + }); + + deepEqual(actual, expected); + }); + test('should return all elements when `n` < `1`', 3, function() { - _.forEach([0, -1, -2], function(n) { + _.each([0, -1, -Infinity], function(n) { deepEqual(_.initial(array, n), array); }); }); - test('should return an empty array when `n` >= `array.length`', 2, function() { - _.forEach([3, 4], function(n) { + test('should return an empty array when `n` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { deepEqual(_.initial(array, n), []); }); }); @@ -3485,25 +3884,32 @@ QUnit.module('lodash.intersection'); (function() { + var args = arguments; + test('should return the intersection of the given arrays', 1, function() { var actual = _.intersection([1, 3, 2], [5, 2, 1, 4], [2, 1]); deepEqual(actual, [1, 2]); }); - test('should return an array of unique values', 1, function() { - var actual = _.intersection([1, 1, 3, 2, 2], [5, 2, 2, 1, 4], [2, 1, 1]); - deepEqual(actual, [1, 2]); + test('should return an array of unique values', 2, function() { + var array = [1, 1, 3, 2, 2]; + deepEqual(_.intersection(array, [5, 2, 2, 1, 4], [2, 1, 1]), [1, 2]); + deepEqual(_.intersection(array), [1, 3, 2]); }); test('should work with large arrays of objects', 1, function() { var object = {}, - expected = [object]; + largeArray = _.times(largeArraySize, _.constant(object)); - var largeArray = _.times(LARGE_ARRAY_SIZE, function() { - return object; - }); + deepEqual(_.intersection([object], largeArray), [object]); + }); + + test('should work with large arrays of objects', 2, function() { + var object = {}, + largeArray = _.times(largeArraySize, _.constant(object)); - deepEqual(_.intersection(expected, largeArray), expected); + deepEqual(_.intersection([object], largeArray), [object]); + deepEqual(_.intersection(_.range(largeArraySize), null, [1]), [1]); }); test('should return a wrapped value when chaining', 2, function() { @@ -3517,10 +3923,13 @@ } }); - test('should ignore individual secondary values', 1, function() { - deepEqual(_.intersection([1, null, 3], 3, null), []); + test('should ignore values that are not arrays or `arguments` objects', 3, function() { + var array = [0, 1, null, 3]; + deepEqual(_.intersection(array, 3, null, { '0': 1 }), array); + deepEqual(_.intersection(null, array, null, [2, 1]), [1]); + deepEqual(_.intersection(null, array, null, args), [1, 3]); }); - }()); + }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -3558,8 +3967,8 @@ (function() { test('should invoke a methods on each element of a collection', 1, function() { - var actual = _.invoke(['a', 'b', 'c'], 'toUpperCase'); - deepEqual(actual, ['A', 'B', 'C']); + var array = ['a', 'b', 'c']; + deepEqual( _.invoke(array, 'toUpperCase'), ['A', 'B', 'C']); }); test('should work with a function `methodName` argument', 1, function() { @@ -3574,6 +3983,15 @@ var object = { 'a': 1, 'b': 2, 'c': 3 }; deepEqual(_.invoke(object, 'toFixed', 1), ['1.0', '2.0', '3.0']); }); + + test('should treat number values for `collection` as empty', 1, function() { + deepEqual(_.invoke(1), []); + }); + + test('should work with nullish elements', 1, function() { + var array = ['a', null, undefined, 'd']; + deepEqual(_.invoke(array, 'toUpperCase'), ['A', undefined, undefined, 'D']); + }); }()); /*--------------------------------------------------------------------------*/ @@ -3587,8 +4005,8 @@ strictEqual(_.isArguments(args), true); }); - test('should return `false` for non `arguments` objects', 9, function() { - var expected = _.map(falsey, function() { return false; }); + test('should return `false` for non `arguments` objects', 10, function() { + var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isArguments(value) : _.isArguments(); @@ -3597,9 +4015,10 @@ strictEqual(_.isArguments([1, 2, 3]), false); strictEqual(_.isArguments(true), false); strictEqual(_.isArguments(new Date), false); + strictEqual(_.isArguments(new Error), false); strictEqual(_.isArguments(_), false); - strictEqual(_.isArguments({ '0': 1, 'callee': noop, 'length': 1 }), false); - strictEqual(_.isArguments(0), false); + strictEqual(_.isArguments({ '0': 1, 'callee': _.noop, 'length': 1 }), false); + strictEqual(_.isArguments(1), false); strictEqual(_.isArguments(/x/), false); strictEqual(_.isArguments('a'), false); @@ -3627,8 +4046,8 @@ strictEqual(_.isArray([1, 2, 3]), true); }); - test('should return `false` for non arrays', 9, function() { - var expected = _.map(falsey, function() { return false; }); + test('should return `false` for non arrays', 10, function() { + var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isArray(value) : _.isArray(); @@ -3637,9 +4056,10 @@ strictEqual(_.isArray(args), false); strictEqual(_.isArray(true), false); strictEqual(_.isArray(new Date), false); + strictEqual(_.isArray(new Error), false); strictEqual(_.isArray(_), false); strictEqual(_.isArray({ '0': 1, 'length': 1 }), false); - strictEqual(_.isArray(0), false); + strictEqual(_.isArray(1), false); strictEqual(_.isArray(/x/), false); strictEqual(_.isArray('a'), false); @@ -3670,7 +4090,7 @@ strictEqual(_.isBoolean(new Boolean(false)), true); }); - test('should return `false` for non booleans', 9, function() { + test('should return `false` for non booleans', 10, function() { var expected = _.map(falsey, function(value) { return value === false; }); var actual = _.map(falsey, function(value, index) { @@ -3680,9 +4100,10 @@ strictEqual(_.isBoolean(args), false); strictEqual(_.isBoolean([1, 2, 3]), false); strictEqual(_.isBoolean(new Date), false); + strictEqual(_.isBoolean(new Error), false); strictEqual(_.isBoolean(_), false); strictEqual(_.isBoolean({ 'a': 1 }), false); - strictEqual(_.isBoolean(0), false); + strictEqual(_.isBoolean(1), false); strictEqual(_.isBoolean(/x/), false); strictEqual(_.isBoolean('a'), false); @@ -3710,8 +4131,8 @@ strictEqual(_.isDate(new Date), true); }); - test('should return `false` for non dates', 9, function() { - var expected = _.map(falsey, function() { return false; }); + test('should return `false` for non dates', 10, function() { + var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isDate(value) : _.isDate(); @@ -3720,9 +4141,10 @@ strictEqual(_.isDate(args), false); strictEqual(_.isDate([1, 2, 3]), false); strictEqual(_.isDate(true), false); + strictEqual(_.isDate(new Error), false); strictEqual(_.isDate(_), false); strictEqual(_.isDate({ 'a': 1 }), false); - strictEqual(_.isDate(0), false); + strictEqual(_.isDate(1), false); strictEqual(_.isDate(/x/), false); strictEqual(_.isDate('a'), false); @@ -3744,6 +4166,8 @@ QUnit.module('lodash.isElement'); (function() { + var args = arguments; + function Element() { this.nodeType = 1; } @@ -3772,7 +4196,28 @@ } }); - test('should work with elements from another realm', 1, function() { + test('should return `false` for non DOM elements', 11, function() { + var expected = _.map(falsey, _.constant(false)); + + var actual = _.map(falsey, function(value, index) { + return index ? _.isElement(value) : _.isElement(); + }); + + strictEqual(_.isElement(args), false); + strictEqual(_.isElement([1, 2, 3]), false); + strictEqual(_.isElement(true), false); + strictEqual(_.isElement(new Date), false); + strictEqual(_.isElement(new Error), false); + strictEqual(_.isElement(_), false); + strictEqual(_.isElement({ 'a': 1 }), false); + strictEqual(_.isElement(1), false); + strictEqual(_.isElement(/x/), false); + strictEqual(_.isElement('a'), false); + + deepEqual(actual, expected); + }); + + test('should work with DOM elements from another realm', 1, function() { if (_._element) { strictEqual(_.isElement(_._element), true); } @@ -3780,7 +4225,7 @@ skipTest(); } }); - }()); + }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -3790,7 +4235,7 @@ var args = arguments; test('should return `true` for empty or falsey values', 3, function() { - var expected = _.map(empties, function() { return true; }); + var expected = _.map(empties, _.constant(true)); var actual = _.map(empties, function(value) { return _.isEmpty(value); @@ -3807,23 +4252,14 @@ strictEqual(_.isEmpty('a'), false); }); - test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { - equal(_.isEmpty(shadowedObject), false); - }); - - test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { - function Foo() {} - Foo.prototype.a = 1; - strictEqual(_.isEmpty(Foo), true); - - Foo.prototype = { 'a': 1 }; - strictEqual(_.isEmpty(Foo), true); - }); - test('should work with an object that has a `length` property', 1, function() { strictEqual(_.isEmpty({ 'length': 0 }), false); }); + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + strictEqual(_.isEmpty(args), false); + }); + test('should work with jQuery/MooTools DOM query collections', 1, function() { function Foo(elements) { push.apply(this, elements); } Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; @@ -3831,12 +4267,36 @@ strictEqual(_.isEmpty(new Foo([])), true); }); - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantomPage) { - strictEqual(_.isEmpty(args), false); - } else { - skipTest(); - } + test('should not treat objects with negative lengths as array-like', 1, function() { + function Foo() {} + Foo.prototype.length = -1; + + strictEqual(_.isEmpty(new Foo), true); + }); + + test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() { + function Foo() {} + Foo.prototype.length = maxSafeInteger + 1; + + strictEqual(_.isEmpty(new Foo), true); + }); + + test('should not treat objects with non-number lengths as array-like', 1, function() { + strictEqual(_.isEmpty({ 'length': '0' }), false); + }); + + test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + strictEqual(_.isEmpty(shadowedObject), false); + }); + + test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { + function Foo() {} + Foo.prototype.a = 1; + + strictEqual(_.isEmpty(Foo), true); + + Foo.prototype = { 'a': 1 }; + strictEqual(_.isEmpty(Foo), true); }); test('should return an unwrapped value when intuitively chaining', 1, function() { @@ -3890,14 +4350,14 @@ var primitive, object = { 'toString': function() { return primitive; } }, values = [true, null, 1, 'a', undefined], - expected = _.map(values, function() { return false; }); + expected = _.map(values, _.constant(false)); var actual = _.map(values, function(value) { primitive = value; return _.isEqual(object, value); }); - ok(actual, expected); + deepEqual(actual, expected); }); test('should perform comparisons between arrays', 6, function() { @@ -4011,7 +4471,7 @@ 'f': ['a', new String('b'), 'c'], 'g': new Boolean(false), 'h': new Date(2012, 4, 23), - 'i': noop, + 'i': _.noop, 'j': 'a' } }; @@ -4025,7 +4485,7 @@ 'f': ['a', 'b', 'c'], 'g': false, 'h': new Date(2012, 4, 23), - 'i': noop, + 'i': _.noop, 'j': 'a' } }; @@ -4034,9 +4494,7 @@ }); test('should perform comparisons between object instances', 4, function() { - function Foo() { - this.value = 1; - } + function Foo() { this.value = 1; } Foo.prototype.value = 1; function Bar() { @@ -4082,7 +4540,7 @@ strictEqual(_.isEqual(args1, args2), true); - if (!isPhantomPage) { + if (!isPhantom) { strictEqual(_.isEqual(args1, args3), false); } else { @@ -4090,7 +4548,24 @@ } }); - test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { + test('should treat `arguments` objects like `Object` objects', 2, function() { + var args = (function() { return arguments; }(1, 2, 3)), + object = { '0': 1, '1': 2, '2': 3, 'length': 3 }; + + function Foo() {} + Foo.prototype = object; + + strictEqual(_.isEqual(args, object), true); + + if (!isPhantom) { + strictEqual(_.isEqual(args, new Foo), false); + } + else { + skipTest(); + } + }); + + test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { strictEqual(_.isEqual(shadowedObject, {}), false); }); @@ -4236,11 +4711,11 @@ var actual = _.isEqual('a', 'a', function() { return 'a'; }); strictEqual(actual, true); - var expected = _.map(falsey, function() { return false; }); + var expected = _.map(falsey, _.constant(false)); actual = []; - _.forEach(falsey, function(value) { - actual.push(_.isEqual('a', 'b', function() { return value; })); + _.each(falsey, function(value) { + actual.push(_.isEqual('a', 'b', _.constant(value))); }); deepEqual(actual, expected); @@ -4263,13 +4738,13 @@ function Foo() { this.a = 1; } Foo.prototype.constructor = null; - var other = { 'a': 1 }; - strictEqual(_.isEqual(new Foo, other), false); + var otherObject = { 'a': 1 }; + strictEqual(_.isEqual(new Foo, otherObject), false); if (create) { - var object = Object.create(null); + var object = create(null); object.a = 1; - strictEqual(_.isEqual(object, other), true); + strictEqual(_.isEqual(object, otherObject), true); } else { skipTest(); @@ -4344,10 +4819,80 @@ skipTest(); } }); + + test('should not error on DOM elements', 1, function() { + if (document) { + var element1 = document.createElement('div'), + element2 = element1.cloneNode(true); + + try { + strictEqual(_.isEqual(element1, element2), false); + } catch(e) { + ok(false); + } + } + else { + skipTest(); + } + }); }()); /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.isError'); + + (function() { + var args = arguments; + + test('should return `true` for error objects', 1, function() { + var errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError], + expected = _.map(errors, _.constant(true)); + + var actual = _.map(errors, function(error) { + return _.isError(error) === true; + }); + + deepEqual(actual, expected); + }); + + test('should return `false` for non-error objects', 10, function() { + var expected = _.map(falsey, _.constant(false)); + + var actual = _.map(falsey, function(value, index) { + return index ? _.isError(value) : _.isError(); + }); + + strictEqual(_.isError(args), false); + strictEqual(_.isError([1, 2, 3]), false); + strictEqual(_.isError(true), false); + strictEqual(_.isError(new Date), false); + strictEqual(_.isError(_), false); + strictEqual(_.isError({ 'a': 1 }), false); + strictEqual(_.isError(1), false); + strictEqual(_.isError(/x/), false); + strictEqual(_.isError('a'), false); + + deepEqual(actual, expected); + }); + + test('should work with an error object from another realm', 1, function() { + if (_._object) { + var expected = _.map(_._errors, _.constant(true)); + + var actual = _.map(_._errors, function(error) { + return _.isError(error) === true; + }); + + deepEqual(actual, expected); + } + else { + skipTest(); + } + }); + }(1, 2, 3)); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.isFinite'); (function() { @@ -4365,12 +4910,13 @@ strictEqual(_.isFinite(-Infinity), false); }); - test('should return `false` for non-numeric values', 8, function() { + test('should return `false` for non-numeric values', 9, function() { strictEqual(_.isFinite(null), false); strictEqual(_.isFinite(undefined), false); strictEqual(_.isFinite([]), false); strictEqual(_.isFinite(true), false); strictEqual(_.isFinite(new Date), false); + strictEqual(_.isFinite(new Error), false); strictEqual(_.isFinite(''), false); strictEqual(_.isFinite(' '), false); strictEqual(_.isFinite('2px'), false); @@ -4403,8 +4949,8 @@ strictEqual(_.isFunction(_), true); }); - test('should return `false` for non functions', 9, function() { - var expected = _.map(falsey, function() { return false; }); + test('should return `false` for non functions', 10, function() { + var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isFunction(value) : _.isFunction(); @@ -4414,8 +4960,9 @@ strictEqual(_.isFunction([1, 2, 3]), false); strictEqual(_.isFunction(true), false); strictEqual(_.isFunction(new Date), false); + strictEqual(_.isFunction(new Error), false); strictEqual(_.isFunction({ 'a': 1 }), false); - strictEqual(_.isFunction(0), false); + strictEqual(_.isFunction(1), false); strictEqual(_.isFunction(/x/), false); strictEqual(_.isFunction('a'), false); @@ -4444,7 +4991,7 @@ strictEqual(_.isNaN(new Number(NaN)), true); }); - test('should return `false` for non NaNs', 10, function() { + test('should return `false` for non NaNs', 11, function() { var expected = _.map(falsey, function(value) { return value !== value; }); var actual = _.map(falsey, function(value, index) { @@ -4455,9 +5002,10 @@ strictEqual(_.isNaN([1, 2, 3]), false); strictEqual(_.isNaN(true), false); strictEqual(_.isNaN(new Date), false); + strictEqual(_.isNaN(new Error), false); strictEqual(_.isNaN(_), false); strictEqual(_.isNaN({ 'a': 1 }), false); - strictEqual(_.isNaN(0), false); + strictEqual(_.isNaN(1), false); strictEqual(_.isNaN(/x/), false); strictEqual(_.isNaN('a'), false); @@ -4485,7 +5033,7 @@ strictEqual(_.isNull(null), true); }); - test('should return `false` for non nulls', 10, function() { + test('should return `false` for non nulls', 11, function() { var expected = _.map(falsey, function(value) { return value === null; }); var actual = _.map(falsey, function(value, index) { @@ -4496,9 +5044,10 @@ strictEqual(_.isNull([1, 2, 3]), false); strictEqual(_.isNull(true), false); strictEqual(_.isNull(new Date), false); + strictEqual(_.isNull(new Error), false); strictEqual(_.isNull(_), false); strictEqual(_.isNull({ 'a': 1 }), false); - strictEqual(_.isNull(0), false); + strictEqual(_.isNull(1), false); strictEqual(_.isNull(/x/), false); strictEqual(_.isNull('a'), false); @@ -4527,7 +5076,7 @@ strictEqual(_.isNumber(new Number(0)), true); }); - test('should return `false` for non numbers', 9, function() { + test('should return `false` for non numbers', 10, function() { var expected = _.map(falsey, function(value) { return typeof value == 'number'; }); var actual = _.map(falsey, function(value, index) { @@ -4538,6 +5087,7 @@ strictEqual(_.isNumber([1, 2, 3]), false); strictEqual(_.isNumber(true), false); strictEqual(_.isNumber(new Date), false); + strictEqual(_.isNumber(new Error), false); strictEqual(_.isNumber(_), false); strictEqual(_.isNumber({ 'a': 1 }), false); strictEqual(_.isNumber(/x/), false); @@ -4567,11 +5117,12 @@ (function() { var args = arguments; - test('should return `true` for objects', 10, function() { + test('should return `true` for objects', 11, function() { strictEqual(_.isObject(args), true); strictEqual(_.isObject([1, 2, 3]), true); strictEqual(_.isObject(new Boolean(false)), true); strictEqual(_.isObject(new Date), true); + strictEqual(_.isObject(new Error), true); strictEqual(_.isObject(_), true); strictEqual(_.isObject({ 'a': 1 }), true); strictEqual(_.isObject(new Number(0)), true); @@ -4587,7 +5138,7 @@ test('should return `false` for non objects', 1, function() { var values = falsey.concat('a', true), - expected = _.map(values, function() { return false; }); + expected = _.map(values, _.constant(false)); var actual = _.map(values, function(value, index) { return index ? _.isObject(value) : _.isObject(); @@ -4628,7 +5179,7 @@ // 2: Initial check with object, this is the other half of the trigger _.isObject(obj); - equal(_.isObject(str), false); + strictEqual(_.isObject(str), false); }); }(1, 2, 3)); @@ -4651,7 +5202,7 @@ strictEqual(_.isPlainObject(new Foo(1)), false); }); - test('should return `true` for objects a [[Prototype]] of `null`', 1, function() { + test('should return `true` for objects with a `[[Prototype]]` of `null`', 1, function() { if (create) { strictEqual(_.isPlainObject(create(null)), true); } else { @@ -4681,14 +5232,14 @@ } }); - test('should return `false` for Object objects without a [[Class]] of "Object"', 3, function() { + test('should return `false` for Object objects without a `[[Class]]` of "Object"', 3, function() { strictEqual(_.isPlainObject(arguments), false); strictEqual(_.isPlainObject(Error), false); strictEqual(_.isPlainObject(Math), false); }); test('should return `false` for non objects', 3, function() { - var expected = _.map(falsey, function() { return false; }); + var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isPlainObject(value) : _.isPlainObject(); @@ -4721,8 +5272,8 @@ strictEqual(_.isRegExp(RegExp('x')), true); }); - test('should return `false` for non regexes', 9, function() { - var expected = _.map(falsey, function(value) { return false; }); + test('should return `false` for non regexes', 10, function() { + var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isRegExp(value) : _.isRegExp(); @@ -4732,9 +5283,10 @@ strictEqual(_.isRegExp([1, 2, 3]), false); strictEqual(_.isRegExp(true), false); strictEqual(_.isRegExp(new Date), false); + strictEqual(_.isRegExp(new Error), false); strictEqual(_.isRegExp(_), false); strictEqual(_.isRegExp({ 'a': 1 }), false); - strictEqual(_.isRegExp(0), false); + strictEqual(_.isRegExp(1), false); strictEqual(_.isRegExp('a'), false); deepEqual(actual, expected); @@ -4762,7 +5314,7 @@ strictEqual(_.isString(new String('a')), true); }); - test('should return `false` for non strings', 9, function() { + test('should return `false` for non strings', 10, function() { var expected = _.map(falsey, function(value) { return value === ''; }); var actual = _.map(falsey, function(value, index) { @@ -4773,9 +5325,10 @@ strictEqual(_.isString([1, 2, 3]), false); strictEqual(_.isString(true), false); strictEqual(_.isString(new Date), false); + strictEqual(_.isString(new Error), false); strictEqual(_.isString(_), false); strictEqual(_.isString({ '0': 1, 'length': 1 }), false); - strictEqual(_.isString(0), false); + strictEqual(_.isString(1), false); strictEqual(_.isString(/x/), false); deepEqual(actual, expected); @@ -4803,20 +5356,21 @@ strictEqual(_.isUndefined(undefined), true); }); - test('should return `false` for non `undefined` values', 10, function() { + test('should return `false` for non `undefined` values', 11, function() { var expected = _.map(falsey, function(value) { return value === undefined; }); var actual = _.map(falsey, function(value, index) { - return _.isUndefined(value); + return index ? _.isUndefined(value) : _.isUndefined(); }); strictEqual(_.isUndefined(args), false); strictEqual(_.isUndefined([1, 2, 3]), false); strictEqual(_.isUndefined(true), false); strictEqual(_.isUndefined(new Date), false); + strictEqual(_.isUndefined(new Error), false); strictEqual(_.isUndefined(_), false); strictEqual(_.isUndefined({ 'a': 1 }), false); - strictEqual(_.isUndefined(0), false); + strictEqual(_.isUndefined(1), false); strictEqual(_.isUndefined(/x/), false); strictEqual(_.isUndefined('a'), false); @@ -4838,13 +5392,13 @@ QUnit.module('isType checks'); (function() { - test('should return `false` for subclassed values', 7, function() { + test('should return `false` for subclassed values', 8, function() { var funcs = [ - 'isArray', 'isBoolean', 'isDate', 'isFunction', - 'isNumber', 'isRegExp', 'isString' + 'isArray', 'isBoolean', 'isDate', 'isError', + 'isFunction', 'isNumber', 'isRegExp', 'isString' ]; - _.forEach(funcs, function(methodName) { + _.each(funcs, function(methodName) { function Foo() {} Foo.prototype = root[methodName.slice(2)].prototype; @@ -4868,7 +5422,7 @@ 'isObject', 'isNull', 'isNumber', 'isRegExp', 'isString', 'isUndefined' ]; - _.forEach(funcs, function(methodName) { + _.each(funcs, function(methodName) { var pass = true; try { _[methodName](xml); @@ -4886,52 +5440,146 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.keys'); + QUnit.module('keys methods'); - (function() { - var args = arguments; + _.each(['keys', 'keysIn'], function(methodName) { + var args = arguments, + func = _[methodName], + isKeys = methodName == 'keys'; + + test('`_.' + methodName + '` should return the keys of an object', 1, function() { + var object = { 'a': 1, 'b': 1 }, + actual = func(object); - test('should return the keys of an object', 1, function() { - var object = { 'a': 1, 'b': 1 }; - deepEqual(_.keys(object), ['a', 'b']); + deepEqual(actual.sort(), ['a', 'b']); }); - test('should work with sparse arrays', 1, function() { + test('`_.' + methodName + '` should treat sparse arrays as dense', 1, function() { var array = [1]; array[2] = 3; - deepEqual(_.keys(array), ['0', '2']); + + var actual = func(array); + deepEqual(actual.sort(), ['0', '1', '2']); }); - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantomPage) { - deepEqual(_.keys(args), ['0', '1', '2']); + test('`_.' + methodName + '` should custom properties on arrays', 1, function() { + var array = [1]; + array.a = 1; + + var actual = func(array); + deepEqual(actual.sort(), ['0', 'a']); + }); + + test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of arrays', 1, function() { + Array.prototype.a = 1; + var expected = isKeys ? ['0'] : ['0', 'a'], + actual = func([1]); + + deepEqual(actual.sort(), expected); + delete Array.prototype.a; + }); + + test('`_.' + methodName + '` should work with `arguments` objects (test in IE < 9)', 1, function() { + if (!isPhantom) { + var actual = func(args); + deepEqual(actual.sort(), ['0', '1', '2']); } else { skipTest(); } }); - test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 2, function() { - function Foo() {} - Foo.prototype.a = 1; + test('`_.' + methodName + '` should custom properties on `arguments` objects', 1, function() { + if (!isPhantom) { + args.a = 1; + var actual = func(args); - deepEqual(_.keys(Foo.prototype), ['a']); - deepEqual(_.keys(shadowedObject).sort(), shadowedProps); + deepEqual(actual.sort(), ['0', '1', '2', 'a']); + delete args.a; + } else { + skipTest(); + } }); - test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { - function Foo() {} - Foo.prototype.c = 3; + test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of `arguments` objects', 1, function() { + if (!isPhantom) { + Object.prototype.a = 1; + var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a'], + actual = func(args); + deepEqual(actual.sort(), expected); + delete Object.prototype.a; + } else { + skipTest(); + } + }); + + test('`_.' + methodName + '` should work with string objects (test in IE < 9)', 1, function() { + var actual = func(Object('abc')); + deepEqual(actual.sort(), ['0', '1', '2']); + }); + + test('`_.' + methodName + '` should custom properties on string objects', 1, function() { + var object = Object('a'); + object.a = 1; + + var actual = func(object); + deepEqual(actual.sort(), ['0', 'a']); + }); + + test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of string objects', 1, function() { + String.prototype.a = 1; + var expected = isKeys ? ['0'] : ['0', 'a'], + actual = func(Object('a')); + + deepEqual(actual.sort(), expected); + delete String.prototype.a; + }); + + test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + var actual = func(shadowedObject); + deepEqual(actual.sort(), shadowedProps); + }); + + test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() { + function Foo() {} Foo.a = 1; Foo.b = 2; + Foo.prototype.c = 3; - var expected = ['a', 'b']; - deepEqual(_.keys(Foo), expected); + var expected = ['a', 'b'], + actual = func(Foo); + + deepEqual(actual.sort(), expected); Foo.prototype = { 'c': 3 }; - deepEqual(_.keys(Foo), expected); + actual = func(Foo); + deepEqual(actual.sort(), expected); }); - }(1, 2, 3)); + + test('`_.' + methodName + '` skips the `constructor` property on prototype objects', 2, function() { + function Foo() {} + Foo.prototype.a = 1; + + var expected = ['a']; + deepEqual(func(Foo.prototype), ['a']); + + Foo.prototype = { 'constructor': Foo, 'a': 1 }; + deepEqual(func(Foo.prototype), ['a']); + }); + + test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties', 1, function() { + function Foo() { + this.a = 1; + this.b = 2; + } + Foo.prototype.c = 3; + + var expected = isKeys ? ['a', 'b'] : ['a', 'b', 'c'], + actual = func(new Foo); + + deepEqual(actual.sort(), expected); + }); + }); /*--------------------------------------------------------------------------*/ @@ -4947,21 +5595,33 @@ ]; test('should return the last element', 1, function() { - equal(_.last(array), 3); + strictEqual(_.last(array), 3); }); test('should return the last two elements', 1, function() { deepEqual(_.last(array, 2), [2, 3]); }); + test('should treat falsey `n` values, except nullish, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value == null ? 3 : []; + }); + + var actual = _.map(falsey, function(n) { + return _.last(array, n); + }); + + deepEqual(actual, expected); + }); + test('should return an empty array when `n` < `1`', 3, function() { - _.forEach([0, -1, -2], function(n) { + _.each([0, -1, -Infinity], function(n) { deepEqual(_.last(array, n), []); }); }); - test('should return all elements when `n` >= `array.length`', 2, function() { - _.forEach([3, 4], function(n) { + test('should return all elements when `n` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { deepEqual(_.last(array, n), array); }); }); @@ -5029,7 +5689,7 @@ test('should not chain when arguments are not provided', 1, function() { if (!isNpm) { var actual = _(array).last(); - equal(actual, 3); + strictEqual(actual, 3); } else { skipTest(); @@ -5053,37 +5713,50 @@ var array = [1, 2, 3, 1, 2, 3]; test('should return the index of the last matched value', 1, function() { - equal(_.lastIndexOf(array, 3), 5); + strictEqual(_.lastIndexOf(array, 3), 5); }); test('should return `-1` for an unmatched value', 1, function() { - equal(_.lastIndexOf(array, 4), -1); + strictEqual(_.lastIndexOf(array, 4), -1); }); test('should work with a positive `fromIndex`', 1, function() { strictEqual(_.lastIndexOf(array, 1, 2), 0); }); - test('should work with `fromIndex` >= `array.length`', 6, function() { - _.forEach([6, 8], function(fromIndex) { - equal(_.lastIndexOf(array, undefined, fromIndex), -1); - equal(_.lastIndexOf(array, 1, fromIndex), 3); - equal(_.lastIndexOf(array, '', fromIndex), -1); + test('should work with `fromIndex` >= `array.length`', 12, function() { + _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { + strictEqual(_.lastIndexOf(array, undefined, fromIndex), -1); + strictEqual(_.lastIndexOf(array, 1, fromIndex), 3); + strictEqual(_.lastIndexOf(array, '', fromIndex), -1); }); }); - test('should work with a negative `fromIndex`', 1, function() { - strictEqual(_.lastIndexOf(array, 2, -3), 1); + test('should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`', 1, function() { + var expected = _.map(falsey, function(value) { + return typeof value == 'number' ? -1 : 5; + }); + + var actual = _.map(falsey, function(fromIndex) { + return _.lastIndexOf(array, 3, fromIndex); + }); + + deepEqual(actual, expected); }); - test('should work with a negative `fromIndex` <= `-array.length`', 2, function() { - strictEqual(_.lastIndexOf(array, 1, -6), 0); - equal(_.lastIndexOf(array, 2, -8), -1); + test('should treat non-number `fromIndex` values as `array.length`', 2, function() { + strictEqual(_.lastIndexOf(array, 3, '1'), 5); + strictEqual(_.lastIndexOf(array, 3, true), 5); }); - test('should ignore non-number `fromIndex` values', 2, function() { - equal(_.lastIndexOf([1, 2, 3], 3, '1'), 2); - equal(_.lastIndexOf([1, 2, 3], 3, true), 2); + test('should work with a negative `fromIndex`', 1, function() { + strictEqual(_.lastIndexOf(array, 2, -3), 1); + }); + + test('should work with a negative `fromIndex` <= `-array.length`', 3, function() { + _.each([-6, -8, -Infinity], function(fromIndex) { + strictEqual(_.lastIndexOf(array, 1, fromIndex), 0); + }); }); }()); @@ -5092,11 +5765,11 @@ QUnit.module('indexOf methods'); (function() { - _.forEach(['indexOf', 'lastIndexOf'], function(methodName) { + _.each(['indexOf', 'lastIndexOf'], function(methodName) { var func = _[methodName]; test('`_.' + methodName + '` should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, function() { return -1; }); + var expected = _.map(falsey, _.constant(-1)); var actual = _.map(falsey, function(value, index) { try { @@ -5163,7 +5836,7 @@ test('should return a wrapped value when chaining', 1, function() { if (!isNpm) { - ok(_(array).map(noop) instanceof _); + ok(_(array).map(_.noop) instanceof _); } else { skipTest(); @@ -5183,8 +5856,8 @@ } }); - test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, function() { return []; }); + test('should accept a falsey `collection` argument', 1, function() { + var expected = _.map(falsey, _.constant([])); var actual = _.map(falsey, function(value, index) { try { @@ -5195,6 +5868,10 @@ deepEqual(actual, expected); }); + test('should treat number values for `collection` as empty', 1, function() { + deepEqual(_.map(1), []); + }); + test('should be aliased', 1, function() { strictEqual(_.collect, _.map); }); @@ -5244,7 +5921,7 @@ test('should return a wrapped value when chaining', 1, function() { if (!isNpm) { - ok(_(object).mapValues(noop) instanceof _); + ok(_(object).mapValues(_.noop) instanceof _); } else { skipTest(); @@ -5252,7 +5929,7 @@ }); test('should accept a falsey `object` argument', 1, function() { - var expected = _.map(falsey, function() { return {}; }); + var expected = _.map(falsey, _.constant({})); var actual = _.map(falsey, function(value, index) { try { @@ -5269,21 +5946,60 @@ QUnit.module('lodash.matches'); (function() { - var object = { 'a': 1, 'b': 2 }; + var object = { 'a': 1, 'b': 2, 'c': 3 }, + sources = [{ 'a': 1 }, { 'a': 1, 'c': 3 }]; - test('should create a function that performs a deep comparison between a given object and the `source` object', 3, function() { - var matches = _.matches({ 'a': 1 }); + test('should create a function that performs a deep comparison between a given object and the `source` object', 6, function() { + _.each(sources, function(source, index) { + var matches = _.matches(source); + strictEqual(matches.length, 1); + strictEqual(matches(object), true); - equal(matches.length, 1); - strictEqual(matches(object), true); + matches = _.matches(index ? { 'c': 3, 'd': 4 } : { 'b': 1 }); + strictEqual(matches(object), false); + }); + }); + + test('should return `true` when comparing an empty `source`', 1, function() { + var expected = _.map(empties, _.constant(true)); + + var actual = _.map(empties, function(value) { + var matches = _.matches(value); + return matches(object) === true; + }); - matches = _.matches({ 'b': 1 }); - strictEqual(matches(object), false); + deepEqual(actual, expected); }); - test('should return `false` when comparing an empty `source`', 1, function() { - var matches = _.matches({}); - strictEqual(matches(object), false); + test('should not error error for falsey `object` values', 2, function() { + var expected = _.map(falsey, _.constant(true)); + + _.each(sources, function(source) { + var matches = _.matches(source); + + var actual = _.map(falsey, function(value, index) { + try { + var result = index ? matches(value) : matches(); + return result === false; + } catch(e) { } + }); + + deepEqual(actual, expected); + }); + }); + + test('should return `true` when comparing an empty `source` to a falsey `object`', 1, function() { + var expected = _.map(falsey, _.constant(true)), + matches = _.matches({}); + + var actual = _.map(falsey, function(value, index) { + try { + var result = index ? matches(value) : matches(); + return result === true; + } catch(e) { } + }); + + deepEqual(actual, expected); }); }()); @@ -5293,7 +6009,7 @@ (function() { test('should return the largest value from a collection', 1, function() { - equal(3, _.max([1, 2, 3])); + strictEqual(3, _.max([1, 2, 3])); }); test('should return `-Infinity` for empty collections', 1, function() { @@ -5332,16 +6048,16 @@ return a + b + c; }); - equal(memoized(1, 2, 3), 6); - equal(memoized(1, 3, 5), 6); + strictEqual(memoized(1, 2, 3), 6); + strictEqual(memoized(1, 3, 5), 6); }); test('should support a `resolver` argument', 2, function() { var fn = function(a, b, c) { return a + b + c; }, memoized = _.memoize(fn, fn); - equal(memoized(1, 2, 3), 6); - equal(memoized(1, 3, 5), 9); + strictEqual(memoized(1, 2, 3), 6); + strictEqual(memoized(1, 3, 5), 9); }); test('should not set a `this` binding', 2, function() { @@ -5350,15 +6066,31 @@ }); var object = { 'b': 2, 'c': 3, 'memoized': memoized }; - equal(object.memoized(1), 6); - equal(object.memoized(2), 7); + strictEqual(object.memoized(1), 6); + strictEqual(object.memoized(2), 7); + }); + + test('should throw a TypeError if `resolve` is truthy and not a function', function() { + raises(function() { _.memoize(_.noop, {}); }, TypeError); + }); + + test('should not throw a TypeError if `resolve` is falsey', function() { + var expected = _.map(falsey, _.constant(true)); + + var actual = _.map(falsey, function(value, index) { + try { + return _.isFunction(index ? _.memoize(_.noop, value) : _.memoize(_.noop)); + } catch(e) { } + }); + + deepEqual(actual, expected); }); test('should check cache for own properties', 1, function() { var actual = [], memoized = _.memoize(_.identity); - _.forEach(shadowedProps, function(value) { + _.each(shadowedProps, function(value) { actual.push(memoized(value)); }); @@ -5366,14 +6098,14 @@ }); test('should expose a `cache` object on the `memoized` function', 4, function() { - _.forEach(['_a', 'a'], function(key, index) { + _.each(['_a', 'a'], function(key, index) { var memoized = _.memoize(_.identity, index && _.identity); memoized('a'); - equal(memoized.cache[key], 'a'); + strictEqual(memoized.cache[key], 'a'); memoized.cache[key] = 'b'; - equal(memoized('a'), 'b'); + strictEqual(memoized('a'), 'b'); }); }); }()); @@ -5445,7 +6177,7 @@ }; var actual = _.merge(object, source); - equal(_.isArguments(actual.args), false); + strictEqual(_.isArguments(actual.args), false); }); test('should work with four arguments', 1, function() { @@ -5494,7 +6226,7 @@ (function() { test('should return the smallest value from a collection', 1, function() { - equal(1, _.min([1, 2, 3])); + strictEqual(1, _.min([1, 2, 3])); }); test('should return `Infinity` for empty collections', 1, function() { @@ -5527,15 +6259,16 @@ QUnit.module('lodash.max and lodash.min'); - _.forEach(['max', 'min'], function(methodName) { + _.each(['max', 'min'], function(methodName) { var array = [1, 2, 3], - func = _[methodName]; + func = _[methodName], + isMax = methodName == 'max'; test('`_.' + methodName + '` should work with Date objects', 1, function() { var now = new Date, past = new Date(0); - equal(func([now, past]), methodName == 'max' ? now : past); + strictEqual(func([now, past]), isMax ? now : past); }); test('`_.' + methodName + '` should work with a callback argument', 1, function() { @@ -5543,7 +6276,7 @@ return -num; }); - equal(actual, methodName == 'max' ? 1 : 3); + strictEqual(actual, isMax ? 1 : 3); }); test('`_.' + methodName + '` should pass the correct `callback` arguments when iterating an array', 1, function() { @@ -5577,29 +6310,39 @@ return -this[index]; }, array); - equal(actual, methodName == 'max' ? 1 : 3); + strictEqual(actual, isMax ? 1 : 3); }); test('`_.' + methodName + '` should work when used as a callback for `_.map`', 1, function() { var array = [[2, 3, 1], [5, 6, 4], [8, 9, 7]], actual = _.map(array, func); - deepEqual(actual, methodName == 'max' ? [3, 6, 9] : [1, 4, 7]); + deepEqual(actual, isMax ? [3, 6, 9] : [1, 4, 7]); }); test('`_.' + methodName + '` should iterate an object', 1, function() { var actual = func({ 'a': 1, 'b': 2, 'c': 3 }); - equal(actual, methodName == 'max' ? 3 : 1); + strictEqual(actual, isMax ? 3 : 1); }); test('`_.' + methodName + '` should iterate a string', 2, function() { - _.forEach(['abc', Object('abc')], function(value) { + _.each(['abc', Object('abc')], function(value) { var actual = func(value); - equal(actual, methodName == 'max' ? 'c' : 'a'); + strictEqual(actual, isMax ? 'c' : 'a'); }); }); - test('`_.' + methodName + '` should resolve the correct value when provided an array containing only one value', 1, function() { + test('`_.' + methodName + '` should work when `callback` returns +/-Infinity', 1, function() { + var object = { 'a': (isMax ? -Infinity : Infinity) }; + + var actual = func([object, { 'a': object.a }], function(object) { + return object.a; + }); + + strictEqual(actual, object); + }); + + test('`_.' + methodName + '` should work when chaining on an array with only one value', 1, function() { if (!isNpm) { var actual = _([40])[methodName]().value(); strictEqual(actual, 40); @@ -5611,7 +6354,7 @@ test('`_.' + methodName + '` should work with extremely large arrays', 1, function() { var array = _.range(0, 5e5); - equal(func(array), methodName == 'max' ? 499999 : 0); + strictEqual(func(array), isMax ? 499999 : 0); }); }); @@ -5628,15 +6371,36 @@ } var value = ['a'], - source = { 'a': function(array) { return array[0]; } }; + source = { 'a': function(array) { return array[0]; }, 'b': 'B' }; + + test('should use `this` as the default `object` value', 3, function() { + var object = _.create(_); + object.mixin(source); + + strictEqual(object.a(value), 'a'); + + ok(!('a' in _)); + ok(!('a' in _.prototype)); + + delete wrapper.a; + delete wrapper.prototype.a; + delete wrapper.b; + delete wrapper.prototype.b; + }); test('should accept an `object` argument', 1, function() { - var lodash = {}; - _.mixin(lodash, source); - strictEqual(lodash.a(value), 'a'); + var object = {}; + _.mixin(object, source); + strictEqual(object.a(value), 'a'); + }); + + test('should return `object`', 2, function() { + var object = {}; + strictEqual(_.mixin(object, source), object); + strictEqual(_.mixin(), _); }); - test('should accept a function `object` argument', 2, function() { + test('should work with a function for `object`', 2, function() { _.mixin(wrapper, source); var wrapped = wrapper(value), @@ -5647,30 +6411,24 @@ delete wrapper.a; delete wrapper.prototype.a; + delete wrapper.b; + delete wrapper.prototype.b; }); test('should mixin `source` methods into lodash', 4, function() { - if (!isNpm) { - _.mixin({ - 'a': 'a', - 'A': function(string) { return string.toUpperCase(); } - }); + _.mixin(source); - equal('a' in _, false); - equal('a' in _.prototype, false); + strictEqual(_.a(value), 'a'); + strictEqual(_(value).a().__wrapped__, 'a'); - delete _.a; - delete _.prototype.a; + delete _.a; + delete _.prototype.a; - equal(_.A('a'), 'A'); - equal(_('a').A().value(), 'A'); + ok(!('b' in _)); + ok(!('b' in _.prototype)); - delete _.A; - delete _.prototype.A; - } - else { - skipTest(4); - } + delete _.b; + delete _.prototype.b; }); test('should accept an `options` argument', 16, function() { @@ -5678,8 +6436,8 @@ return (func === _ ? 'lodash' : 'provided') + ' function should ' + (chain ? '' : 'not ') + 'chain'; } - _.forEach([_, wrapper], function(func) { - _.forEach([false, true, { 'chain': false }, { 'chain': true }], function(options) { + _.each([_, wrapper], function(func) { + _.each([false, true, { 'chain': false }, { 'chain': true }], function(options) { if (func === _) { _.mixin(source, options); } else { @@ -5688,15 +6446,17 @@ var wrapped = func(value), actual = wrapped.a(); - if (options && (options === true || options.chain)) { + if (options === true || (options && options.chain)) { strictEqual(actual.__wrapped__, 'a', message(func, true)); ok(actual instanceof func, message(func, true)); } else { strictEqual(actual, 'a', message(func, false)); - equal(actual instanceof func, false, message(func, false)); + ok(!(actual instanceof func), message(func, false)); } delete func.a; delete func.prototype.a; + delete func.b; + delete func.prototype.b; }); }); }); @@ -5720,9 +6480,36 @@ } delete _.a; delete _.prototype.a; + delete _.b; + delete _.prototype.b; ok(pass); }); + + test('should return the existing wrapper when chaining', 2, function() { + if (!isNpm) { + _.each([_, wrapper], function(func) { + if (func === _) { + var wrapper = _(source), + actual = wrapper.mixin(); + + strictEqual(actual.value(), _); + } + else { + wrapper = _(func); + actual = wrapper.mixin(source); + strictEqual(actual, wrapper); + } + delete func.a; + delete func.prototype.a; + delete func.b; + delete func.prototype.b; + }); + } + else { + skipTest(2); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -5732,7 +6519,7 @@ (function() { test('should always return `undefined`', 1, function() { var values = falsey.concat([], true, new Date, _, {}, /x/, 'a'), - expected = _.map(values, function() { return undefined; }); + expected = _.map(values, _.constant()); var actual = _.map(values, function(value, index) { return index ? _.noop(value) : _.noop(); @@ -5847,16 +6634,16 @@ (function() { test('should execute `func` once', 1, function() { var count = 0, - func = _.once(function() { count++; }); + once = _.once(function() { count++; }); - func(); - func(); + once(); + once(); strictEqual(count, 1); }); test('should not set a `this` binding', 1, function() { - var func = _.once(function() { this.count++; }), - object = { 'count': 0, 'once': func }; + var once = _.once(function() { this.count++; }), + object = { 'count': 0, 'once': once }; object.once(); object.once(); @@ -5866,26 +6653,26 @@ test('should ignore recursive calls', 1, function() { var count = 0; - var func = _.once(function() { + var once = _.once(function() { count++; - func(); + once(); }); - func(); + once(); strictEqual(count, 1); }); test('should not throw more than once', 2, function() { - var pass = true; - - var func = _.once(function() { + var once = _.once(function() { throw new Error; }); - raises(function() { func(); }, Error); + raises(function() { once(); }, Error); + + var pass = true; try { - func(); + once(); } catch(e) { pass = false; } @@ -5895,6 +6682,104 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.pad'); + + (function() { + test('should pad a string to a given length', 1, function() { + strictEqual(_.pad('abc', 9), ' abc '); + }); + + test('should truncate pad characters to fit the pad length', 2, function() { + strictEqual(_.pad('abc', 8), ' abc '); + strictEqual(_.pad('abc', 8, '_-'), '_-abc_-_'); + }); + + test('should coerce `string` to a string', 2, function() { + strictEqual(_.pad(Object('abc'), 4), 'abc '); + strictEqual(_.pad({ 'toString': _.constant('abc') }, 5), ' abc '); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.padLeft'); + + (function() { + test('should pad a string to a given length', 1, function() { + strictEqual(_.padLeft('abc', 6), ' abc'); + }); + + test('should truncate pad characters to fit the pad length', 1, function() { + strictEqual(_.padLeft('abc', 6, '_-'), '_-_abc'); + }); + + test('should coerce `string` to a string', 2, function() { + strictEqual(_.padLeft(Object('abc'), 4), ' abc'); + strictEqual(_.padLeft({ 'toString': _.constant('abc') }, 5), ' abc'); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.padRight'); + + (function() { + test('should pad a string to a given length', 1, function() { + strictEqual(_.padRight('abc', 6), 'abc '); + }); + + test('should truncate pad characters to fit the pad length', 1, function() { + strictEqual(_.padRight('abc', 6, '_-'), 'abc_-_'); + }); + + test('should coerce `string` to a string', 2, function() { + strictEqual(_.padRight(Object('abc'), 4), 'abc '); + strictEqual(_.padRight({ 'toString': _.constant('abc') }, 5), 'abc '); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('pad methods'); + + _.each(['pad', 'padLeft', 'padRight'], function(methodName, index) { + var func = _[methodName]; + + test('`_.' + methodName + '` should not pad is string is >= `length`', 2, function() { + strictEqual(func('abc', 2), 'abc'); + strictEqual(func('abc', 3), 'abc'); + }); + + test('`_.' + methodName + '` should treat negative `length` as `0`', 2, function() { + _.each([0, -2], function(length) { + strictEqual(func('abc', length), 'abc'); + }); + }); + + test('`_.' + methodName + '` should coerce `length` to a number', 2, function() { + _.each(['', '4'], function(length) { + var actual = length ? (index == 1 ? ' abc' : 'abc ') : 'abc'; + strictEqual(func('abc', length), actual); + }); + }); + + test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string and `chars`', 6, function() { + _.each([null, '_-'], function(chars) { + strictEqual(func(null, 0, chars), ''); + strictEqual(func(undefined, 0, chars), ''); + strictEqual(func('', 0, chars), ''); + }); + }); + + test('`_.' + methodName + '` should work with `null`, `undefined`, or empty string for `chars`', 3, function() { + notStrictEqual(func('abc', 6, null), 'abc'); + notStrictEqual(func('abc', 6, undefined), 'abc'); + strictEqual(func('abc', 6, ''), 'abc'); + }); + }); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.pairs'); (function() { @@ -5932,7 +6817,7 @@ }); test('should use a radix of `16`, for hexadecimals, if `radix` is `undefined` or `0`', 8, function() { - _.forEach(['0x20', '0X20'], function(string) { + _.each(['0x20', '0X20'], function(string) { strictEqual(_.parseInt(string), 32); strictEqual(_.parseInt(string, 0), 32); strictEqual(_.parseInt(string, 16), 32); @@ -5952,7 +6837,7 @@ strictEqual(_.parseInt(whitespace + '08'), 8); strictEqual(_.parseInt(whitespace + '08', 10), 8); - _.forEach(['0x20', '0X20'], function(string) { + _.each(['0x20', '0X20'], function(string) { strictEqual(_.parseInt(whitespace + string), 32); strictEqual(_.parseInt(whitespace + string, 16), 32); }); @@ -5969,15 +6854,13 @@ QUnit.module('partial methods'); - _.forEach(['partial', 'partialRight'], function(methodName) { + _.each(['partial', 'partialRight'], function(methodName) { var func = _[methodName], isPartial = methodName == 'partial'; test('`_.' + methodName + '` partially applies arguments', 1, function() { - var fn = function(a) { return a; }, - par = func(fn, 'a'); - - equal(par(), 'a'); + var par = func(_.identity, 'a'); + strictEqual(par(), 'a'); }); test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() { @@ -5996,10 +6879,29 @@ }); test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked with additional arguments', 1, function() { - var fn = function(a) { return a; }, - par = func(fn); + var par = func(_.identity); + strictEqual(par('a'), 'a'); + }); - equal(par('a'), 'a'); + test('`_.' + methodName + '` should support placeholders', 4, function() { + if (!isModularize) { + var fn = function() { return slice.call(arguments); }, + par = func(fn, _, 'b', _); + + deepEqual(par('a', 'c'), ['a', 'b', 'c']); + deepEqual(par('a'), ['a', 'b', undefined]); + deepEqual(par(), [undefined, 'b', undefined]); + + if (isPartial) { + deepEqual(par('a', 'c', 'd'), ['a', 'b', 'c', 'd']); + } else { + par = func(fn, _, 'c', _); + deepEqual(par('a', 'b', 'd'), ['a', 'b', 'c', 'd']); + } + } + else { + skipTest(4); + } }); test('`_.' + methodName + '` should not alter the `this` binding', 3, function() { @@ -6027,36 +6929,14 @@ function Foo(value) { return value && object; } - var par = func(Foo), - object = {}; + + var object = {}, + par = func(Foo); ok(new par instanceof Foo); strictEqual(new par(true), object); }); - test('`_.' + methodName + '` should support placeholders', 4, function() { - if (_._iteratorTemplate) { - var fn = function() { - return slice.call(arguments); - }; - - var par = func(fn, _, 'b', _); - deepEqual(par('a', 'c'), ['a', 'b', 'c']); - deepEqual(par('a'), ['a', 'b', undefined]); - deepEqual(par(), [undefined, 'b', undefined]); - - if (isPartial) { - deepEqual(par('a', 'c', 'd'), ['a', 'b', 'c', 'd']); - } else { - par = func(fn, _, 'c', _); - deepEqual(par('a', 'b', 'd'), ['a', 'b', 'c', 'd']); - } - } - else { - skipTest(4); - } - }); - test('`_.' + methodName + '` should clone metadata for created functions', 3, function() { var greet = function(greeting, name) { return greeting + ' ' + name; @@ -6066,17 +6946,17 @@ par2 = func(par1, 'barney'), par3 = func(par1, 'pebbles'); - equal(par1('fred'), isPartial ? 'hi fred' : 'fred hi') - equal(par2(), isPartial ? 'hi barney' : 'barney hi'); - equal(par3(), isPartial ? 'hi pebbles' : 'pebbles hi'); + strictEqual(par1('fred'), isPartial ? 'hi fred' : 'fred hi') + strictEqual(par2(), isPartial ? 'hi barney' : 'barney hi'); + strictEqual(par3(), isPartial ? 'hi pebbles' : 'pebbles hi'); }); test('`_.' + methodName + '` should work with curried methods', 2, function() { var fn = function(a, b, c) { return a + b + c; }, curried = _.curry(func(fn, 1), 2); - equal(curried(2, 3), 6); - equal(curried(2)(3), 6); + strictEqual(curried(2, 3), 6); + strictEqual(curried(2)(3), 6); }); }); @@ -6101,9 +6981,9 @@ (function() { test('combinations of partial functions should work', 1, function() { - var fn = function() { + function fn() { return slice.call(arguments); - }; + } var a = _.partial(fn), b = _.partialRight(a, 3), @@ -6113,11 +6993,11 @@ }); test('combinations of bound and partial functions should work', 3, function() { - var fn = function() { + function fn() { var result = [this.a]; push.apply(result, arguments); return result; - }; + } var expected = [1, 2, 3, 4], object = { 'a': 1, 'fn': fn }; @@ -6142,9 +7022,9 @@ }); test('recursively bound functions should work', 1, function() { - var fn = function() { + function fn() { return this.a; - }; + } var a = _.bind(fn, { 'a': 1 }), b = _.bind(a, { 'a': 2 }), @@ -6162,9 +7042,9 @@ var array = [1, 0, 1]; test('should always return two groups of elements', 3, function() { - deepEqual(_.partition([], function(value) { return value; }), [[], []]); - deepEqual(_.partition(array, function(value) { return true; }), [array, []]); - deepEqual(_.partition(array, function(value) { return false; }), [[], array]); + deepEqual(_.partition([], _.identity), [[], []]); + deepEqual(_.partition(array, _.constant(true)), [array, []]); + deepEqual(_.partition(array, _.constant(false)), [[], array]); }); test('should use `_.identity` when no `callback` is provided', 1, function() { @@ -6307,6 +7187,25 @@ var object = { 'a': [1], 'b': [1, 2], 'c': [1, 2, 3] }; deepEqual(_.pluck(object, 'length'), [1, 2, 3]); }); + + test('should work with nullish elements', 1, function() { + var objects = [{ 'a': 1 }, null, undefined, { 'a': 4 }]; + deepEqual(_.pluck(objects, 'a'), [1, undefined, undefined, 4]); + }); + + test('should coerce `key` to a string', 1, function() { + function fn() {} + fn.toString = _.constant('fn'); + + var objects = [{ 'null': 1 }, { 'undefined': 2 }, { 'fn': 3 }, { '[object Object]': 4 }], + values = [null, undefined, fn, {}] + + var actual = _.map(objects, function(object, index) { + return _.pluck([object], values[index]); + }); + + deepEqual(actual, [[1], [2], [3], [4]]); + }); }()); /*--------------------------------------------------------------------------*/ @@ -6318,10 +7217,10 @@ var object = { 'a': 1, 'b': 2 }, property = _.property('a'); - equal(property.length, 1); + strictEqual(property.length, 1); strictEqual(property(object), 1); - property = _.property('b'); + property = _.property('b'); strictEqual(property(object), 2); }); @@ -6329,7 +7228,7 @@ var array = [1, 2, 3], property = _.property(1); - equal(property(array), 2); + strictEqual(property(array), 2); }); }()); @@ -6346,22 +7245,76 @@ ok(actual === array); }); - test('should preserve holes in arrays', 2, function() { - var array = [1, 2, 3, 4]; - delete array[1]; - delete array[3]; + test('should preserve holes in arrays', 2, function() { + var array = [1, 2, 3, 4]; + delete array[1]; + delete array[3]; + + _.pull(array, 1); + ok(!('0' in array)); + ok(!('2' in array)); + }); + + test('should treat holes as `undefined`', 1, function() { + var array = [1, 2, 3]; + delete array[1]; + + _.pull(array, undefined); + deepEqual(array, [1, 3]); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.pullAt'); + + (function() { + test('should modify the array and return removed elements', 2, function() { + var array = [1, 2, 3], + actual = _.pullAt(array, [0, 1]); + + deepEqual(array, [3]); + deepEqual(actual, [1, 2]); + }); + + test('should work with unsorted indexes', 2, function() { + var array = [1, 2, 3, 4, 5], + actual = _.pullAt(array, [4, 1, 0, 3]); + + deepEqual(array, [3]); + deepEqual(actual, [5, 2, 1, 4]); + }); + + test('should work with repeated indexes', 2, function() { + var array = [1, 2, 3, 4], + actual = _.pullAt(array, [0, 2, 0, 1, 0, 2]); + + deepEqual(array, [4]); + deepEqual(actual, [1, 3, 1, 2, 1, 3]); + }); + + test('should return `undefined` for nonexistent keys', 2, function() { + var array = ['a', 'b', 'c'], + actual = _.pullAt(array, [2, 4, 0]); + + deepEqual(array, ['b']); + deepEqual(actual, ['c', undefined, 'a']); + }); + + test('should return an empty array when no keys are provided', 2, function() { + var array = ['a', 'b', 'c'], + actual = _.pullAt(array); - _.pull(array, 1); - equal(0 in array, false); - equal(2 in array, false); + deepEqual(array, ['a', 'b', 'c']); + deepEqual(actual, []); }); - test('should treat holes as `undefined`', 1, function() { - var array = [1, 2, 3]; - delete array[1]; + test('should accept multiple index arguments', 2, function() { + var array = ['a', 'b', 'c', 'd'], + actual = _.pullAt(array, 3, 0, 2); - _.pull(array, undefined); - deepEqual(array, [1, 3]); + deepEqual(array, ['b']); + deepEqual(actual, ['d', 'a', 'c']); }); }()); @@ -6382,7 +7335,7 @@ test('supports not passing a `max` argument', 1, function() { ok(_.some(array, function() { - return _.random(5) != 5; + return _.random(5) !== 5; })); }); @@ -6429,8 +7382,6 @@ QUnit.module('lodash.range'); (function() { - var func = _.range; - test('should work when passing a single `end` argument', 1, function() { deepEqual(_.range(4), [0, 1, 2, 3]); }); @@ -6457,7 +7408,7 @@ }); test('should treat falsey `start` arguments as `0`', 13, function() { - _.forEach(falsey, function(value, index) { + _.each(falsey, function(value, index) { if (index) { deepEqual(_.range(value), []); deepEqual(_.range(value, 1), [0]); @@ -6467,9 +7418,9 @@ }); }); - test('should coerce arguments to numbers', 1, function() { - var actual = [func('0',1), func('1'), func(0, 1, '1')]; - deepEqual(actual, [[0], [0], [0]]); + test('should coerce arguments to finite numbers', 1, function() { + var actual = [_.range('0', 1), _.range('1'), _.range(0, 1, '1'), _.range(NaN), _.range(NaN, NaN)]; + deepEqual(actual, [[0], [0], [0], [], []]); }); }()); @@ -6528,7 +7479,7 @@ deepEqual(args, expected); }); - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -6542,7 +7493,7 @@ }); deepEqual(args, ['a', 'b', 1, collection]); - equal(actual, 'abc'); + strictEqual(actual, 'abc'); }); }); @@ -6560,7 +7511,7 @@ var array = [1, 2, 3]; test('should use the last element of a collection as the default `accumulator`', 1, function() { - equal(_.reduceRight(array), 3); + strictEqual(_.reduceRight(array), 3); }); test('should pass the correct `callback` arguments when iterating an array', 2, function() { @@ -6607,7 +7558,7 @@ deepEqual(args, expected); }); - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -6621,7 +7572,7 @@ }); deepEqual(args, ['c', 'b', 1, collection]); - equal(actual, 'cba'); + strictEqual(actual, 'cba'); }); }); @@ -6634,7 +7585,7 @@ QUnit.module('reduce methods'); - _.forEach(['reduce', 'reduceRight'], function(methodName) { + _.each(['reduce', 'reduceRight'], function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -6643,7 +7594,7 @@ return accumulator + value; }, ''); - equal(actual, methodName == 'reduce' ? 'abc' : 'cba'); + strictEqual(actual, methodName == 'reduce' ? 'abc' : 'cba'); }); test('`_.' + methodName + '` should support the `thisArg` argument', 1, function() { @@ -6660,7 +7611,7 @@ return sum + num; }); - equal(actual, 6); + strictEqual(actual, 6); } else { skipTest(); @@ -6669,11 +7620,11 @@ test('`_.' + methodName + '` should support empty or falsey collections without an initial `accumulator` value', 1, function() { var actual = [], - expected = _.map(empties, function() { return undefined; }); + expected = _.map(empties, _.constant()); - _.forEach(empties, function(value) { + _.each(empties, function(value) { try { - actual.push(func(value, noop)); + actual.push(func(value, _.noop)); } catch(e) { } }); @@ -6681,11 +7632,11 @@ }); test('`_.' + methodName + '` should support empty or falsey collections with an initial `accumulator` value', 1, function() { - var expected = _.map(empties, function() { return 'x'; }); + var expected = _.map(empties, _.constant('x')); var actual = _.map(empties, function(value) { try { - return func(value, noop, 'x'); + return func(value, _.noop, 'x'); } catch(e) { } }); @@ -6693,7 +7644,7 @@ }); test('`_.' + methodName + '` should handle an initial `accumulator` value of `undefined`', 1, function() { - var actual = func([], noop, undefined); + var actual = func([], _.noop, undefined); strictEqual(actual, undefined); }); @@ -6703,12 +7654,12 @@ if ('__proto__' in array) { array.__proto__ = object; - strictEqual(_.reduce(array, noop), undefined); + strictEqual(_.reduce(array, _.noop), undefined); } else { skipTest(); } - strictEqual(_.reduce(object, noop), undefined); + strictEqual(_.reduce(object, _.noop), undefined); }); }); @@ -6730,7 +7681,7 @@ QUnit.module('filter methods'); - _.forEach(['filter', 'reject'], function(methodNames) { + _.each(['filter', 'reject'], function(methodNames) { var func = _[methodNames]; test('`_.' + methodNames + '` should not modify the resulting value from within `callback`', 1, function() { @@ -6786,8 +7737,8 @@ delete array[3]; _.remove(array, function(num) { return num === 1; }); - equal(0 in array, false); - equal(2 in array, false); + ok(!('0' in array)); + ok(!('2' in array)); }); test('should treat holes as `undefined`', 1, function() { @@ -6801,63 +7752,28 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.removeAt'); + QUnit.module('lodash.repeat'); (function() { - test('should modify the array and return removed elements', 2, function() { - var array = [1, 2, 3]; - var actual = _.removeAt(array, [0, 1]); - - deepEqual(array, [3]); - deepEqual(actual, [1, 2]); - }); - - test('should work with unsorted indexes', 2, function() { - var array = [1, 2, 3, 4, 5]; - var actual = _.removeAt(array, [4, 1, 0, 3]); - - deepEqual(array, [3]); - deepEqual(actual, [1, 2, 4, 5]); - }); - - test('should work with repeated indexes', 2, function() { - var array = [1, 2, 3, 4, 5]; - var actual = _.removeAt(array, [0, 0, 1, 2, 2, 2]); - - deepEqual(array, [4, 5]); - deepEqual(actual, [1, 1, 2, 3, 3, 3]); - }); - - test('should return `undefined` for nonexistent keys', 2, function() { - var array = ['a', 'b', 'c']; - var actual = _.removeAt(array, [0, 2, 4]); - - deepEqual(array, ['b']); - deepEqual(actual, ['a', 'c', undefined]); + test('should repeat a string `n` times', 2, function() { + strictEqual(_.repeat('*', 3), '***'); + strictEqual(_.repeat('abc', 2), 'abcabc'); }); - test('should return an empty array when no keys are provided', 2, function() { - var array = ['a', 'b', 'c']; - var actual = _.removeAt(array); - - deepEqual(array, ['a', 'b', 'c']); - deepEqual(actual, []); + test('should return an empty string for negative `n` or `n` of `0`', 2, function() { + strictEqual(_.repeat('abc', 0), ''); + strictEqual(_.repeat('abc', -2), ''); }); - test('should accept multiple index arguments', 2, function() { - var array = ['a', 'b', 'c', 'd']; - var actual = _.removeAt(array, 0, 2, 3); - - deepEqual(array, ['b']); - deepEqual(actual, ['a', 'c', 'd']); + test('should coerce `n` to a number', 3, function() { + strictEqual(_.repeat('abc'), ''); + strictEqual(_.repeat('abc', '2'), 'abcabc'); + strictEqual(_.repeat('*', { 'valueOf': _.constant(3) }), '***'); }); - test('should work when used as a callback for `_.map`', 2, function() { - var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; - var actual = _.map(array, _.removeAt); - - deepEqual(array, [[2, 3], [4, 6], [7, 8]]); - deepEqual(actual, [[1], [5], [9]]); + test('should coerce `string` to a string', 2, function() { + strictEqual(_.repeat(Object('abc'), 2), 'abcabc'); + strictEqual(_.repeat({ 'toString': _.constant('*') }, 3), '***'); }); }()); @@ -6879,13 +7795,13 @@ strictEqual(_.result(object, 'd'), undefined); }); - test('should return `undefined` when `object` is `null` or `undefined`', 2, function() { + test('should return `undefined` when `object` is nullish', 2, function() { strictEqual(_.result(null, 'a'), undefined); strictEqual(_.result(undefined, 'a'), undefined); }); test('should return the specified default value for undefined properties', 1, function() { - var values = falsey.concat(1, function() { return 1; }); + var values = falsey.concat(1, _.constant(1)); var expected = _.transform(values, function(result, value) { result.push(value, value); @@ -6916,7 +7832,7 @@ ]; test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, function() { return []; }); + var expected = _.map(falsey, _.constant([])); var actual = _.map(falsey, function(value, index) { try { @@ -6935,14 +7851,26 @@ deepEqual(_.rest(array, 2), [3]); }); + test('should treat falsey `n` values, except nullish, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value == null ? [2, 3] : array; + }); + + var actual = _.map(falsey, function(n) { + return _.rest(array, n); + }); + + deepEqual(actual, expected); + }); + test('should return all elements when `n` < `1`', 3, function() { - _.forEach([0, -1, -2], function(n) { - deepEqual(_.rest(array, n), [1, 2, 3]); + _.each([0, -1, -Infinity], function(n) { + deepEqual(_.rest(array, n), array); }); }); - test('should return an empty array when `n` >= `array.length`', 2, function() { - _.forEach([3, 4], function(n) { + test('should return an empty array when `n` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { deepEqual(_.rest(array, n), []); }); }); @@ -6976,7 +7904,7 @@ deepEqual(args, [1, 0, array]); }); - test('supports the `thisArg` argument', 1, function() { + test('should support the `thisArg` argument', 1, function() { var actual = _.rest(array, function(num, index) { return this[index] < 3; }, array); @@ -7043,14 +7971,26 @@ deepEqual(actual.sort(), array); }); - test('should return an empty array when `n` < `1`', 3, function() { - _.forEach([0, -1, -2], function(n) { + test('should treat falsey `n` values, except nullish, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value == null ? 1 : []; + }); + + var actual = _.map(falsey, function(n) { + return _.sample([1], n); + }); + + deepEqual(actual, expected); + }); + + test('should return an empty array when `n` < `1` or `NaN`', 3, function() { + _.each([0, -1, -Infinity], function(n) { deepEqual(_.sample(array, n), []); }); }); - test('should return all elements when `n` >= `array.length`', 2, function() { - _.forEach([3, 4], function(n) { + test('should return all elements when `n` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(n) { deepEqual(_.sample(array, n).sort(), array); }); }); @@ -7066,7 +8006,7 @@ result.push([], []); }); - _.forEach(empties, function(value) { + _.each(empties, function(value) { try { actual.push(_.shuffle(value), _.shuffle(value, 1)); } catch(e) { } @@ -7114,7 +8054,7 @@ } }); - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -7151,7 +8091,11 @@ deepEqual(actual.sort(), array); }); - _.forEach({ + test('should treat number values for `collection` as empty', 1, function() { + deepEqual(_.shuffle(1), []); + }); + + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -7172,15 +8116,15 @@ array = [1, 2, 3]; test('should return the number of own enumerable properties of an object', 1, function() { - equal(_.size({ 'one': 1, 'two': 2, 'three': 3 }), 3); + strictEqual(_.size({ 'one': 1, 'two': 2, 'three': 3 }), 3); }); test('should return the length of an array', 1, function() { - equal(_.size(array), 3); + strictEqual(_.size(array), 3); }); test('should accept a falsey `object` argument', 1, function() { - var expected = _.map(falsey, function() { return 0; }); + var expected = _.map(falsey, _.constant(0)); var actual = _.map(falsey, function(value, index) { try { @@ -7191,26 +8135,34 @@ deepEqual(actual, expected); }); + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + strictEqual(_.size(args), 3); + }); + test('should work with jQuery/MooTools DOM query collections', 1, function() { function Foo(elements) { push.apply(this, elements); } Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; - equal(_.size(new Foo(array)), 3); + strictEqual(_.size(new Foo(array)), 3); }); - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantomPage) { - equal(_.size(args), 3); - } else { - skipTest(); - } + test('should not treat objects with negative lengths as array-like', 1, function() { + strictEqual(_.size({ 'length': -1 }), 1); + }); + + test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() { + strictEqual(_.size({ 'length': maxSafeInteger + 1 }), 1); + }); + + test('should not treat objects with non-number lengths as array-like', 1, function() { + strictEqual(_.size({ 'length': '0' }), 1); }); - test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { - equal(_.size(shadowedObject), 7); + test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + strictEqual(_.size(shadowedObject), 7); }); - _.forEach({ + _.each({ 'literal': 'abc', 'object': Object('abc') }, @@ -7232,18 +8184,28 @@ deepEqual(_.slice(array, 1), [2, 3]); }); - test('should work with a `start` >= `array.length`', 2, function() { - _.forEach([3, 4], function(start) { + test('should work with a `start` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(start) { deepEqual(_.slice(array, start), []); }); }); + test('should treat falsey `start` values as `0`', 1, function() { + var expected = _.map(falsey, _.constant(array)); + + var actual = _.map(falsey, function(start) { + return _.slice(array, start); + }); + + deepEqual(actual, expected); + }); + test('should work with a negative `start`', 1, function() { deepEqual(_.slice(array, -1), [3]); }); - test('should work with a negative `start` <= negative `array.length`', 2, function() { - _.forEach([-3, -4], function(start) { + test('should work with a negative `start` <= negative `array.length`', 3, function() { + _.each([-3, -4, -Infinity], function(start) { deepEqual(_.slice(array, start), [1, 2, 3]); }); }); @@ -7252,21 +8214,38 @@ deepEqual(_.slice(array, 0, 1), [1]); }); - test('should work with a `end` >= `array.length`', 2, function() { - _.forEach([3, 4], function(end) { + test('should work with a `end` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(end) { deepEqual(_.slice(array, 0, end), [1, 2, 3]); }); }); + test('should treat falsey `end` values, except `undefined`, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value === undefined ? array : []; + }); + + var actual = _.map(falsey, function(end) { + return _.slice(array, 0, end); + }); + + deepEqual(actual, expected); + }); + test('should work with a negative `end`', 1, function() { deepEqual(_.slice(array, 0, -1), [1, 2]); }); - test('should work with a negative `end` <= negative `array.length`', 2, function() { - _.forEach([-3, -4], function(end) { + test('should work with a negative `end` <= negative `array.length`', 3, function() { + _.each([-3, -4, -Infinity], function(end) { deepEqual(_.slice(array, 0, end), []); }); }); + + test('should coerce `start` and `end` to finite numbers', 1, function() { + var actual = [_.slice(array, '0', 1), _.slice(array, 0, '1'), _.slice(array, '1'), _.slice(array, NaN, 1), _.slice(array, 1, NaN)]; + deepEqual(actual, [[1], [1], [2, 3], [1], []]); + }); }()); /*--------------------------------------------------------------------------*/ @@ -7275,7 +8254,7 @@ (function() { test('should return `false` for empty or falsey collections', 1, function() { - var expected = _.map(empties, function() { return false; }); + var expected = _.map(empties, _.constant(false)); var actual = _.map(empties, function(value) { try { @@ -7286,7 +8265,7 @@ deepEqual(actual, expected); }); - test('should return `true` if the callback returns truey for any element in the collection', 2, function() { + test('should return `true` if the callback returns truthy for any element in the collection', 2, function() { strictEqual(_.some([false, 1, ''], _.identity), true); strictEqual(_.some([null, 'x', 0], _.identity), true); }); @@ -7296,7 +8275,7 @@ strictEqual(_.some([null, 0, ''], _.identity), false); }); - test('should return `true` as soon as the `callback` result is truey', 1, function() { + test('should return `true` as soon as the `callback` result is truthy', 1, function() { strictEqual(_.some([null, true, null], _.identity), true); }); @@ -7398,6 +8377,10 @@ deepEqual(actual, [3, 1, 2]); }); + test('should treat number values for `collection` as empty', 1, function() { + deepEqual(_.sortBy(1), []); + }); + test('should support sorting by an array of properties', 1, function() { var actual = _.sortBy(objects, ['a', 'b']); deepEqual(actual, [objects[2], objects[0], objects[3], objects[1]]); @@ -7428,8 +8411,8 @@ objects = [{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }]; test('should return the insert index of a given value', 2, function() { - equal(_.sortedIndex(array, 40), 2); - equal(_.sortedIndex(array, 30), 1); + strictEqual(_.sortedIndex(array, 40), 2); + strictEqual(_.sortedIndex(array, 30), 1); }); test('should pass the correct `callback` arguments', 1, function() { @@ -7452,7 +8435,7 @@ test('should work with a string for `callback`', 1, function() { var actual = _.sortedIndex(objects, { 'x': 40 }, 'x'); - equal(actual, 2); + strictEqual(actual, 2); }); test('supports arrays with lengths larger than `Math.pow(2, 31) - 1`', 1, function() { @@ -7464,7 +8447,7 @@ if (array.length == length) { array[index] = index; _.sortedIndex(array, index, function() { steps++; }); - equal(steps, 33); + strictEqual(steps, 33); } else { skipTest(); @@ -7478,7 +8461,9 @@ (function() { test('should contain properties with boolean values', 1, function() { - ok(_.every(_.values(_.support), _.isBoolean)); + ok(_.every(_.values(_.support), function(value) { + return value === true || value === false; + })); }); test('should not contain minified properties (test production builds)', 1, function() { @@ -7494,17 +8479,94 @@ 'nodeClass', 'nonEnumArgs', 'nonEnumShadows', + 'nonEnumStrings', 'ownLast', 'spliceObjects', 'unindexedChars' ]; - ok(!_.size(_.difference(_.keys(_.support), props))); + ok(_.isEmpty(_.difference(_.keys(_.support), props))); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash.startsWith'); + + (function() { + var string = 'abc'; + + test('should return `true` if a string starts with `target`', 1, function() { + strictEqual(_.startsWith(string, 'a'), true); + }); + + test('should return `false` if a string does not start with `target`', 1, function() { + strictEqual(_.startsWith(string, 'b'), false); + }); + + test('should work with a `position` argument', 1, function() { + strictEqual(_.startsWith(string, 'b', 1), true); + }); + + test('should work with `position` >= `string.length`', 4, function() { + _.each([3, 5, maxSafeInteger, Infinity], function(position) { + strictEqual(_.startsWith(string, 'a', position), false); + }); + }); + + test('should treat falsey `position` values as `0`', 1, function() { + var expected = _.map(falsey, _.constant(true)); + + var actual = _.map(falsey, function(position) { + return _.startsWith(string, 'a', position); + }); + + deepEqual(actual, expected); + }); + + test('should treat a negative `position` as `0`', 6, function() { + _.each([-1, -3, -Infinity], function(position) { + strictEqual(_.startsWith(string, 'a', position), true); + strictEqual(_.startsWith(string, 'b', position), false); + }); + }); + + test('should always return `true` when `target` is an empty string regardless of `position`', 1, function() { + ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, maxSafeInteger, Infinity], function(position) { + return _.startsWith(string, '', position, true); + })); }); }()); /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.startsWith and lodash.endsWith'); + + _.each(['startsWith', 'endsWith'], function(methodName) { + var func = _[methodName], + isEndsWith = methodName == 'endsWith', + chr = isEndsWith ? 'c' : 'a', + string = 'abc'; + + test('`_.' + methodName + '` should coerce `string` to a string', 2, function() { + strictEqual(func(Object(string), chr), true); + strictEqual(func({ 'toString': _.constant(string) }, chr), true); + }); + + test('`_.' + methodName + '` should coerce `target` to a string', 2, function() { + strictEqual(func(string, Object(chr)), true); + strictEqual(func(string, { 'toString': _.constant(chr) }), true); + }); + + test('`_.' + methodName + '` should coerce `position` to a number', 2, function() { + var position = isEndsWith ? 2 : 1; + strictEqual(func(string, 'b', Object(position)), true); + strictEqual(func(string, 'b', { 'toString': _.constant(String(position)) }), true); + }); + }); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.tap'); (function() { @@ -7569,7 +8631,7 @@ unescaped = '&<>"\'\/'; var compiled = _.template('

    <%- value %>

    '); - equal(compiled({ 'value': unescaped }), escaped); + strictEqual(compiled({ 'value': unescaped }), escaped); }); test('should evaluate JavaScript in "evaluate" delimiters', 1, function() { @@ -7581,24 +8643,24 @@ ); var actual = compiled({ 'collection': { 'a': 'A', 'b': 'B' } }); - equal(actual, '
    • A
    • B
    '); + strictEqual(actual, '
    • A
    • B
    '); }); test('should interpolate data object properties', 1, function() { var compiled = _.template('<%= a %>BC'); - equal(compiled({ 'a': 'A' }), 'ABC'); + strictEqual(compiled({ 'a': 'A' }), 'ABC'); }); test('should support escaped values in "interpolation" delimiters', 1, function() { var compiled = _.template('<%= a ? "a=\\"A\\"" : "" %>'); - equal(compiled({ 'a': true }), 'a="A"'); + strictEqual(compiled({ 'a': true }), 'a="A"'); }); test('should work with "interpolate" delimiters containing ternary operators', 1, function() { var compiled = _.template('<%= value ? value : "b" %>'), data = { 'value': 'a' }; - equal(compiled(data), 'a'); + strictEqual(compiled(data), 'a'); }); test('should work with "interpolate" delimiters containing global values', 1, function() { @@ -7608,11 +8670,11 @@ var actual = compiled(); } catch(e) { } - equal(actual, 'function'); + strictEqual(actual, 'function'); }); test('should work with complex "interpolate" delimiters', 22, function() { - _.forEach({ + _.each({ '<%= a + b %>': '3', '<%= b - a %>': '1', '<%= a = b %>': '2', @@ -7640,19 +8702,19 @@ var compiled = _.template(key), data = { 'a': 1, 'b': 2 }; - equal(compiled(data), value, key); + strictEqual(compiled(data), value, key); }); }); test('should parse ES6 template delimiters', 2, function() { var data = { 'value': 2 }; strictEqual(_.template('1${value}3', data), '123'); - equal(_.template('${"{" + value + "\\}"}', data), '{2}'); + strictEqual(_.template('${"{" + value + "\\}"}', data), '{2}'); }); test('should not reference `_.escape` when "escape" delimiters are not used', 1, function() { var compiled = _.template('<%= typeof __e %>'); - equal(compiled({}), 'undefined'); + strictEqual(compiled({}), 'undefined'); }); test('should allow referencing variables declared in "evaluate" delimiters from other delimiters', 1, function() { @@ -7664,7 +8726,7 @@ test('should support single line comments in "evaluate" delimiters (test production builds)', 1, function() { var compiled = _.template('<% // comment %><% if (value) { %>yap<% } else { %>nope<% } %>'); - equal(compiled({ 'value': true }), 'yap'); + strictEqual(compiled({ 'value': true }), 'yap'); }); test('should work with custom `_.templateSettings` delimiters', 1, function() { @@ -7676,10 +8738,10 @@ 'interpolate': /\{\{=([\s\S]+?)\}\}/g }); - var compiled = _.template('
      {{ _.forEach(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    '), + var compiled = _.template('
      {{ _.each(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    '), expected = '
    • 0: a & A
    • 1: b & B
    '; - equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected); + strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected); _.assign(_.templateSettings, settings); }); @@ -7692,16 +8754,16 @@ 'interpolate': /<\?=([\s\S]+?)\?>/g }); - var compiled = _.template('
    • :
    '), + var compiled = _.template('
    • :
    '), expected = '
    • 0: a & A
    • 1: b & B
    '; - equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected); + strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected); _.assign(_.templateSettings, settings); }); test('should work with no delimiters', 1, function() { var expected = 'abc'; - equal(_.template(expected, {}), expected); + strictEqual(_.template(expected, {}), expected); }); test('should support the "imports" option', 1, function() { @@ -7713,7 +8775,7 @@ test('should support the "variable" options', 1, function() { var compiled = _.template( - '<% _.forEach( data.a, function( value ) { %>' + + '<% _.each( data.a, function( value ) { %>' + '<%= value.valueOf() %>' + '<% }) %>', null, { 'variable': 'data' } ); @@ -7727,32 +8789,32 @@ }); test('should use a `with` statement by default', 1, function() { - var compiled = _.template('<%= index %><%= collection[index] %><% _.forEach(collection, function(value, index) { %><%= index %><% }); %>'), + var compiled = _.template('<%= index %><%= collection[index] %><% _.each(collection, function(value, index) { %><%= index %><% }); %>'), actual = compiled({ 'index': 1, 'collection': ['a', 'b', 'c'] }); - equal(actual, '1b012'); + strictEqual(actual, '1b012'); }); test('should work correctly with `this` references', 2, function() { var compiled = _.template('a<%= this.String("b") %>c'); - equal(compiled(), 'abc'); + strictEqual(compiled(), 'abc'); var object = { 'b': 'B' }; object.compiled = _.template('A<%= this.b %>C', null, { 'variable': 'obj' }); - equal(object.compiled(), 'ABC'); + strictEqual(object.compiled(), 'ABC'); }); test('should work with backslashes', 1, function() { var compiled = _.template('<%= a %> \\b'); - equal(compiled({ 'a': 'A' }), 'A \\b'); + strictEqual(compiled({ 'a': 'A' }), 'A \\b'); }); test('should work with escaped characters in string literals', 2, function() { var compiled = _.template('<% print("\'\\n\\r\\t\\u2028\\u2029\\\\") %>'); - equal(compiled(), "'\n\r\t\u2028\u2029\\"); + strictEqual(compiled(), "'\n\r\t\u2028\u2029\\"); compiled = _.template('\'\n\r\t<%= a %>\u2028\u2029\\"'); - equal(compiled({ 'a': 'A' }), '\'\n\r\tA\u2028\u2029\\"'); + strictEqual(compiled({ 'a': 'A' }), '\'\n\r\tA\u2028\u2029\\"'); }); test('should handle \\u2028 & \\u2029 characters', 1, function() { @@ -7767,7 +8829,7 @@ } %>" ); - equal(compiled({ 'a': 'A' }), "'a',\"A\""); + strictEqual(compiled({ 'a': 'A' }), "'a',\"A\""); }); test('should work with templates containing newlines and comments', 1, function() { @@ -7777,7 +8839,7 @@ %>

    <%= value %>

    ' ); - equal(compiled({ 'value': 3 }), '

    6

    '); + strictEqual(compiled({ 'value': 3 }), '

    6

    '); }); test('should not error with IE conditional comments enabled (test with development build)', 1, function() { @@ -7797,7 +8859,7 @@ var compiled = _.template(''), data = { 'type': 1 }; - equal(compiled(data), ''); + strictEqual(compiled(data), ''); }); test('should evaluate delimiters once', 1, function() { @@ -7810,10 +8872,10 @@ test('should match delimiters before escaping text', 1, function() { var compiled = _.template('<<\n a \n>>', null, { 'evaluate': /<<(.*?)>>/g }); - equal(compiled(), '<<\n a \n>>'); + strictEqual(compiled(), '<<\n a \n>>'); }); - test('should resolve `null` and `undefined` values to empty strings', 4, function() { + test('should resolve `null` and `undefined` values to an empty string', 4, function() { var compiled = _.template('<%= a %><%- a %>'); strictEqual(compiled({ 'a': null }), ''); strictEqual(compiled({ 'a': undefined }), ''); @@ -7828,14 +8890,14 @@ compiled = _.template(expected, null, { 'evaluate': /<<(.+?)>>/g }), data = { 'value': true }; - equal(compiled(data), expected); + strictEqual(compiled(data), expected); }); test('should support recursive calls', 1, function() { var compiled = _.template('<%= a %><% a = _.template(c, obj) %><%= a %>'), data = { 'a': 'A', 'b': 'B', 'c': '<%= b %>' }; - equal(compiled(data), 'AB'); + strictEqual(compiled(data), 'AB'); }); test('should coerce `text` argument to a string', 1, function() { @@ -7852,10 +8914,10 @@ }); test('should not modify `_.templateSettings` when `options` are provided', 2, function() { - equal('a' in _.templateSettings, false); + ok(!('a' in _.templateSettings)); _.template('', {}, { 'a': 1 }); - equal('a' in _.templateSettings, false); + ok(!('a' in _.templateSettings)); delete _.templateSettings.a; }); @@ -7892,6 +8954,60 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.truncate'); + + (function() { + var string = 'hi-diddly-ho there, neighborino'; + + test('should truncate to a length of `30` by default', 1, function() { + strictEqual(_.truncate(string), 'hi-diddly-ho there, neighbo...'); + }); + + test('should not truncate if `string` is <= `length`', 2, function() { + strictEqual(_.truncate(string, string.length), string); + strictEqual(_.truncate(string, string.length + 2), string); + }); + + test('should truncate string the given length', 1, function() { + strictEqual(_.truncate(string, 24), 'hi-diddly-ho there, n...'); + }); + + test('should support a `omission` option', 1, function() { + strictEqual(_.truncate(string, { 'omission': ' [...]' }), 'hi-diddly-ho there, neig [...]'); + }); + + test('should support a `length` option', 1, function() { + strictEqual(_.truncate(string, { 'length': 4 }), 'h...'); + }); + + test('should support a `separator` option', 2, function() { + strictEqual(_.truncate(string, { 'length': 24, 'separator': ' ' }), 'hi-diddly-ho there,...'); + strictEqual(_.truncate(string, { 'length': 24, 'separator': /,? +/ }), 'hi-diddly-ho there...'); + }); + + test('should treat negative `length` as `0`', 4, function() { + _.each([0, -2], function(length) { + strictEqual(_.truncate(string, length), '...'); + strictEqual(_.truncate(string, { 'length': length }), '...'); + }); + }); + + test('should coerce `length` to a number', 4, function() { + _.each(['', '4'], function(length, index) { + var actual = index ? 'h...' : '...'; + strictEqual(_.truncate(string, length), actual); + strictEqual(_.truncate(string, { 'length': { 'valueOf': _.constant(length) } }), actual); + }); + }); + + test('should coerce `string` to a string', 2, function() { + strictEqual(_.truncate(Object(string), 4), 'h...'); + strictEqual(_.truncate({ 'toString': _.constant(string) }, 5), 'hi...'); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.throttle'); (function() { @@ -7920,7 +9036,7 @@ asyncTest('subsequent calls should return the result of the first call', 5, function() { if (!(isRhino && isModularize)) { - var throttled = _.throttle(function(value) { return value; }, 32), + var throttled = _.throttle(_.identity, 32), result = [throttled('a'), throttled('b')]; deepEqual(result, ['a', 'a']); @@ -7965,7 +9081,7 @@ throttled(); setTimeout(function() { - equal(callCount, 2); + strictEqual(callCount, 2); QUnit.start(); }, 64); } @@ -7991,7 +9107,7 @@ }, 32); throttled.call(object, 'a'); - equal(count, 1); + strictEqual(count, 1); setTimeout(function() { ok(count < 3); @@ -8011,10 +9127,10 @@ throttled = _.throttle(function() { count++; }, 32); throttled(); - equal(count, 1); + strictEqual(count, 1); setTimeout(function() { - equal(count, 1); + strictEqual(count, 1); QUnit.start(); }, 64); } @@ -8056,8 +9172,8 @@ return value; }, 32, {}); - equal(throttled('a'), 'a'); - equal(throttled('b'), 'a'); + strictEqual(throttled('a'), 'a'); + strictEqual(throttled('b'), 'a'); setTimeout(function() { strictEqual(count, 2); @@ -8070,14 +9186,14 @@ } }); - test('should work with `leading` option', 4, function() { + test('should support a `leading` option', 4, function() { if (!(isRhino && isModularize)) { - _.forEach([true, { 'leading': true }], function(options) { + _.each([true, { 'leading': true }], function(options) { var withLeading = _.throttle(_.identity, 32, options); - equal(withLeading('a'), 'a'); + strictEqual(withLeading('a'), 'a'); }); - _.forEach([false, { 'leading': false }], function(options) { + _.each([false, { 'leading': false }], function(options) { var withoutLeading = _.throttle(_.identity, 32, options); strictEqual(withoutLeading('a'), undefined); }); @@ -8087,7 +9203,7 @@ } }); - asyncTest('should work with `trailing` option', 6, function() { + asyncTest('should support a `trailing` option', 6, function() { if (!(isRhino && isModularize)) { var withCount = 0, withoutCount = 0; @@ -8102,14 +9218,14 @@ return value; }, 64, { 'trailing': false }); - equal(withTrailing('a'), 'a'); - equal(withTrailing('b'), 'a'); + strictEqual(withTrailing('a'), 'a'); + strictEqual(withTrailing('b'), 'a'); - equal(withoutTrailing('a'), 'a'); - equal(withoutTrailing('b'), 'a'); + strictEqual(withoutTrailing('a'), 'a'); + strictEqual(withoutTrailing('b'), 'a'); setTimeout(function() { - equal(withCount, 2); + strictEqual(withCount, 2); strictEqual(withoutCount, 1); QUnit.start(); }, 256); @@ -8152,14 +9268,15 @@ QUnit.module('lodash.debounce and lodash.throttle'); - _.forEach(['debounce', 'throttle'], function(methodName) { - var func = _[methodName]; + _.each(['debounce', 'throttle'], function(methodName) { + var func = _[methodName], + isThrottle = methodName == 'throttle'; test('_.' + methodName + ' should not error for non-object `options` values', 1, function() { var pass = true; try { - func(noop, 32, 1); + func(_.noop, 32, 1); } catch(e) { pass = false; } @@ -8175,11 +9292,11 @@ }; object.funced(); - if (methodName == 'throttle') { + if (isThrottle) { object.funced(); } setTimeout(function() { - deepEqual(actual, methodName == 'throttle' ? [object, object] : [object]); + deepEqual(actual, isThrottle ? [object, object] : [object]); QUnit.start(); }, 64); } @@ -8212,7 +9329,7 @@ setTimeout(function() { funced(); - equal(callCount, methodName == 'throttle' ? 2 : 1); + strictEqual(callCount, isThrottle ? 2 : 1); QUnit.start(); }, 64); } @@ -8245,7 +9362,7 @@ QUnit.module('lodash.slice and lodash.toArray'); - _.forEach(['slice', 'toArray'], function(methodName) { + _.each(['slice', 'toArray'], function(methodName) { var args = (function() { return arguments; }(1, 2, 3)), array = [1, 2, 3], func = _[methodName]; @@ -8256,8 +9373,8 @@ var actual = func(sparse); - ok(0 in actual); - ok(2 in actual); + ok('0' in actual); + ok('2' in actual); deepEqual(actual, sparse); }); @@ -8291,6 +9408,17 @@ QUnit.module('lodash.times'); (function() { + test('should rollover large `n` values', 1, function() { + var actual = _.times(Math.pow(2, 32) + 1); + deepEqual(actual, [0]); + }); + + test('should coerce non-finite `n` values to `0`', 3, function() { + _.each([-Infinity, NaN, Infinity], function(n) { + deepEqual(_.times(n), []); + }); + }); + test('should pass the correct `callback` arguments', 1, function() { var args; @@ -8322,7 +9450,7 @@ test('should return an empty array for falsey and negative `n` arguments', 1, function() { var values = falsey.concat(-1, -Infinity), - expected = _.map(values, function() { return []; }); + expected = _.map(values, _.constant([])); var actual = _.map(values, function(value, index) { return index ? _.times(value) : _.times(); @@ -8376,7 +9504,11 @@ ok(_.transform(new Foo) instanceof Foo); }); - _.forEach({ + test('should check that `object` is an object before using it as the `accumulator` `[[Prototype]]', 1, function() { + ok(!(_.transform(1) instanceof Number)); + }); + + _.each({ 'array': [1, 2, 3], 'object': { 'a': 1, 'b': 2, 'c': 3 } }, @@ -8390,10 +9522,10 @@ var first = args[0]; if (key == 'array') { - ok(first != object && _.isArray(first)); + ok(first !== object && _.isArray(first)); deepEqual(args, [first, 1, 0, object]); } else { - ok(first != object && _.isPlainObject(first)); + ok(first !== object && _.isPlainObject(first)); deepEqual(args, [first, 1, 'a', object]); } }); @@ -8413,7 +9545,7 @@ QUnit.module('trim methods'); - _.forEach(['trim', 'trimLeft', 'trimRight'], function(methodName, index) { + _.each(['trim', 'trimLeft', 'trimRight'], function(methodName, index) { var func = _[methodName]; var parts = []; @@ -8430,6 +9562,13 @@ strictEqual(func(string), (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : '')); }); + test('`_.' + methodName + '` should not remove non-whitespace characters', 1, function() { + var problemChars = '\x85\u200b\ufffe', + string = problemChars + 'a b c' + problemChars; + + strictEqual(func(string), string); + }); + test('`_.' + methodName + '` should coerce `string` to a string', 1, function() { var object = { 'toString': function() { return whitespace + 'a b c' + whitespace; } }; strictEqual(func(object), (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : '')); @@ -8447,13 +9586,22 @@ strictEqual(func(string, object), (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : '')); }); - test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty strings', 6, function() { - _.forEach([null, '_-'], function(arg) { - strictEqual(func.call(_, null, arg), ''); - strictEqual(func.call(_, undefined, arg), ''); - strictEqual(func.call(_, '', arg), ''); + test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string and `chars`', 6, function() { + _.each([null, '_-'], function(chars) { + strictEqual(func(null, chars), ''); + strictEqual(func(undefined, chars), ''); + strictEqual(func('', chars), ''); }); }); + + test('`_.' + methodName + '` should work with `null`, `undefined`, or empty string for `chars`', 3, function() { + var string = whitespace + 'a b c' + whitespace, + expected = (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : ''); + + strictEqual(func(string, null), expected); + strictEqual(func(string, undefined), expected); + strictEqual(func(string, ''), string); + }); }); /*--------------------------------------------------------------------------*/ @@ -8465,29 +9613,23 @@ unescaped = '&<>"\'\/'; test('should unescape entities in the correct order', 1, function() { - equal(_.unescape('&lt;'), '<'); + strictEqual(_.unescape('&lt;'), '<'); }); test('should unescape the proper entities', 1, function() { - equal(_.unescape(escaped), unescaped); + strictEqual(_.unescape(escaped), unescaped); }); test('should not unescape the "/" entity', 1, function() { - equal(_.unescape('/'), '/'); + strictEqual(_.unescape('/'), '/'); }); test('should handle strings with nothing to unescape', 1, function() { - equal(_.unescape('abc'), 'abc'); + strictEqual(_.unescape('abc'), 'abc'); }); test('should unescape the same characters escaped by `_.escape`', 1, function() { - equal(_.unescape(_.escape(unescaped)), unescaped); - }); - - test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() { - strictEqual(_.unescape(null), ''); - strictEqual(_.unescape(undefined), ''); - strictEqual(_.unescape(''), ''); + strictEqual(_.unescape(_.escape(unescaped)), unescaped); }); }()); @@ -8496,28 +9638,25 @@ QUnit.module('lodash.union'); (function() { + var args = arguments; + test('should return the union of the given arrays', 1, function() { - var actual = _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); - deepEqual(actual, [1, 2, 3, 5, 4]); + var actual = _.union([1, 3, 2], [5, 2, 1, 4], [2, 1]); + deepEqual(actual, [1, 3, 2, 5, 4]); }); test('should not flatten nested arrays', 1, function() { - var actual = _.union([1, 2, 3], [1, [5]], [2, [4]]); - deepEqual(actual, [1, 2, 3, [5], [4]]); - }); - - test('should produce correct results when provided a falsey `array` argument', 1, function() { - var expected = [1, 2, 3], - actual = _.union(null, expected); - - deepEqual(actual, expected); + var actual = _.union([1, 3, 2], [1, [5]], [2, [4]]); + deepEqual(actual, [1, 3, 2, [5], [4]]); }); - test('should ignore individual secondary values', 1, function() { - var array = [1]; - deepEqual(_.union(array, 1, 2, 3), array); + test('should ignore values that are not arrays or `arguments` objects', 3, function() { + var array = [0]; + deepEqual(_.union(array, 3, null, { '0': 1 }), array); + deepEqual(_.union(null, array, null, [2, 1]), [0, 2, 1]); + deepEqual(_.union(null, array, null, args), [0, 1, 2, 3]); }); - }()); + }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -8575,7 +9714,7 @@ test('should work with large arrays', 1, function() { var object = {}; - var largeArray = _.times(LARGE_ARRAY_SIZE, function(index) { + var largeArray = _.times(largeArraySize, function(index) { switch (index % 3) { case 0: return 0; case 1: return 'a'; @@ -8589,18 +9728,19 @@ test('should work with large arrays of boolean, `null`, and `undefined` values', 1, function() { var array = [], expected = [true, false, null, undefined], - count = Math.ceil(LARGE_ARRAY_SIZE / expected.length); + count = Math.ceil(largeArraySize / expected.length); _.times(count, function() { push.apply(array, expected); }); + deepEqual(_.uniq(array), expected); }); test('should distinguish between numbers and numeric strings', 1, function() { var array = [], expected = ['2', 2, Object('2'), Object(2)], - count = Math.ceil(LARGE_ARRAY_SIZE / expected.length); + count = Math.ceil(largeArraySize / expected.length); _.times(count, function() { push.apply(array, expected); @@ -8609,7 +9749,7 @@ deepEqual(_.uniq(array), expected); }); - _.forEach({ + _.each({ 'an object': ['a'], 'a number': 0, 'a string': '0' @@ -8637,11 +9777,11 @@ actual.push(_.uniqueId()); }); - equal(_.uniq(actual).length, actual.length); + strictEqual(_.uniq(actual).length, actual.length); }); test('should return a string value when not passing a prefix argument', 1, function() { - equal(typeof _.uniqueId(), 'string'); + strictEqual(typeof _.uniqueId(), 'string'); }); test('should coerce the prefix argument to a string', 1, function() { @@ -8671,7 +9811,7 @@ QUnit.module('lodash.where'); (function() { - var array = [ + var objects = [ { 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }, @@ -8679,22 +9819,27 @@ { 'a': 3 } ]; - test('should filter by properties', 6, function() { - deepEqual(_.where(array, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]); - deepEqual(_.where(array, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]); - deepEqual(_.where(array, { 'a': 3 }), [{ 'a': 3 }]); - deepEqual(_.where(array, { 'b': 1 }), []); - deepEqual(_.where(array, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); - deepEqual(_.where(array, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]); + test('should filter by `source` properties', 6, function() { + deepEqual(_.where(objects, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]); + deepEqual(_.where(objects, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]); + deepEqual(_.where(objects, { 'a': 3 }), [{ 'a': 3 }]); + deepEqual(_.where(objects, { 'b': 1 }), []); + deepEqual(_.where(objects, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); + deepEqual(_.where(objects, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]); }); - test('should not filter by inherited properties', 1, function() { + test('should not filter by inherited `source` properties', 2, function() { function Foo() {} Foo.prototype = { 'a': 2 }; - var properties = new Foo; - properties.b = 2; - deepEqual(_.where(array, properties), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); + var source = new Foo; + source.b = 2; + + var expected = [objects[2], objects[3]], + actual = _.where(objects, source); + + deepEqual(actual, expected); + ok(_.isEmpty(_.difference(actual, objects))); }); test('should filter by problem JScript properties (test in IE < 9)', 1, function() { @@ -8702,47 +9847,83 @@ deepEqual(_.where(collection, shadowedObject), [shadowedObject]); }); - test('should work with an object for `collection`', 1, function() { + test('should work with an object for `collection`', 2, function() { var collection = { 'x': { 'a': 1 }, 'y': { 'a': 3 }, 'z': { 'a': 1, 'b': 2 } }; - deepEqual(_.where(collection, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1, 'b': 2 }]); + var expected = [collection.x, collection.z], + actual = _.where(collection, { 'a': 1 }); + + deepEqual(actual, expected); + ok(_.isEmpty(_.difference(actual, _.values(collection)))); + }); + + test('should work with a function for `source`', 1, function() { + function source() {} + source.a = 2; + + deepEqual(_.where(objects, source), [{ 'a': 2, 'b': 2 }]); }); - test('should return an empty array when provided an empty `properties` object', 1, function() { - deepEqual(_.where(array, {}), []); + test('should match all elements when provided an empty `source`', 1, function() { + var expected = _.map(empties, _.constant(objects)); + + var actual = _.map(empties, function(value) { + var result = _.where(objects, value); + return result !== objects && result; + }); + + deepEqual(actual, expected); }); - test('should deep compare `properties` values', 1, function() { + test('should perform a deep partial comparison of `source`', 2, function() { var collection = [{ 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4 }], - expected = _.cloneDeep(collection); + expected = collection.slice(), + actual = _.where(collection, { 'a': { 'b': { 'c': 1 } } }); - deepEqual(_.where(collection, { 'a': { 'b': { 'c': 1 } } }), expected); + deepEqual(actual, expected); + ok(_.isEmpty(_.difference(actual, collection))); }); test('should search of arrays for values', 2, function() { var collection = [{ 'a': [1, 2] }], - expected = _.cloneDeep(collection); + expected = collection.slice(); deepEqual(_.where(collection, { 'a': [] }), []); deepEqual(_.where(collection, { 'a': [2] }), expected); }); - test('should handle `properties` with `undefined` values', 4, function() { - var properties = { 'b': undefined }; - deepEqual(_.where([{ 'a': 1 }, { 'a': 1, 'b': 1 }], properties), []); + test('should perform a partial comparison of *all* objects within arrays of `source`', 2, function() { + var collection = [ + { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 5, 'd': 6 }] }, + { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 6, 'd': 7 }] } + ]; + + var actual = _.where(collection, { 'a': [{ 'b': 1, 'c': 2 }, { 'b': 4, 'c': 5 }] }); + deepEqual(actual, [collection[0]]); + ok(_.isEmpty(_.difference(actual, collection))); + }); + + test('should handle a `source` with `undefined` values', 4, function() { + var source = { 'b': undefined }, + actual = _.where([{ 'a': 1 }, { 'a': 1, 'b': 1 }], source); + + deepEqual(actual, []); var object = { 'a': 1, 'b': undefined }; - deepEqual(_.where([object], properties), [object]); + actual = _.where([object], source); + deepEqual(actual, [object]); - properties = { 'a': { 'c': undefined } }; - deepEqual(_.where([{ 'a': { 'b': 1 } }, { 'a':{ 'b':1 , 'c': 1 } }], properties), []); + source = { 'a': { 'c': undefined } }; + actual = _.where([{ 'a': { 'b': 1 } }, { 'a':{ 'b':1 , 'c': 1 } }], source); + deepEqual(actual, []); object = { 'a': { 'b': 1, 'c': undefined } }; - deepEqual(_.where([object], properties), [object]); + actual = _.where([object], source); + deepEqual(actual, [object]); }); }()); @@ -8776,18 +9957,18 @@ return '

    ' + func(text) + '

    '; }); - equal(p('fred, barney, & pebbles'), '

    fred, barney, & pebbles

    '); + strictEqual(p('fred, barney, & pebbles'), '

    fred, barney, & pebbles

    '); }); test('should pass the correct `wrapper` arguments', 1, function() { var args; - var wrapped = _.wrap(noop, function() { + var wrapped = _.wrap(_.noop, function() { args || (args = slice.call(arguments)); }); wrapped(1, 2, 3); - deepEqual(args, [noop, 1, 2, 3]); + deepEqual(args, [_.noop, 1, 2, 3]); }); test('should not set a `this` binding', 1, function() { @@ -8796,7 +9977,7 @@ }); var object = { 'p': p, 'text': 'fred, barney, & pebbles' }; - equal(object.p(), '

    fred, barney, & pebbles

    '); + strictEqual(object.p(), '

    fred, barney, & pebbles

    '); }); }()); @@ -8805,6 +9986,8 @@ QUnit.module('lodash.xor'); (function() { + var args = arguments; + test('should return the symmetric difference of the given arrays', 1, function() { var actual = _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); deepEqual(actual, [1, 4, 5]); @@ -8834,11 +10017,18 @@ } }); - test('should ignore individual secondary values', 1, function() { - var array = [1, null, 3]; - deepEqual(_.xor(array, 3, null), array); + test('should ignore individual secondary arguments', 1, function() { + var array = [0]; + deepEqual(_.xor(array, 3, null, { '0': 1 }), array); }); - }()); + + test('should ignore values that are not arrays or `arguments` objects', 3, function() { + var array = [1, 2]; + deepEqual(_.xor(array, 3, null, { '0': 1 }), array); + deepEqual(_.xor(null, array, null, [2, 3]), [1, 3]); + deepEqual(_.xor(null, array, null, args), [3]); + }); + }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -8879,11 +10069,11 @@ ]; var actual = _.zip(pair[0]); - ok(0 in actual[2]); + ok('0' in actual[2]); deepEqual(actual, pair[1]); actual = _.zip.apply(_, actual); - ok(2 in actual[0]); + ok('2' in actual[0]); deepEqual(actual, [['barney', 36, undefined], ['fred', 40, false]]); }); @@ -8930,7 +10120,7 @@ }); test('should accept a falsey `array` argument', 1, function() { - var expected = _.map(falsey, function() { return {}; }); + var expected = _.map(falsey, _.constant({})); var actual = _.map(falsey, function(value, index) { try { @@ -8961,7 +10151,7 @@ wrapped.shift(); deepEqual(wrapped.keys().value(), ['length']); - equal(wrapped.first(), undefined); + strictEqual(wrapped.first(), undefined); } else { skipTest(2); @@ -8980,7 +10170,7 @@ wrapped.splice(0, 1); deepEqual(wrapped.keys().value(), ['length']); - equal(wrapped.first(), undefined); + strictEqual(wrapped.first(), undefined); } else { skipTest(2); @@ -8996,7 +10186,7 @@ test('should return the `toString` result of the wrapped value', 1, function() { if (!isNpm) { var wrapped = _([1, 2, 3]); - equal(String(wrapped), '1,2,3'); + strictEqual(String(wrapped), '1,2,3'); } else { skipTest(); @@ -9012,12 +10202,33 @@ test('should return the `valueOf` result of the wrapped value', 1, function() { if (!isNpm) { var wrapped = _(123); - equal(Number(wrapped), 123); + strictEqual(Number(wrapped), 123); + } + else { + skipTest(); + } + }); + + test('should stringify the wrapped value when passed to `JSON.stringify`', 1, function() { + if (!isNpm && JSON) { + var wrapped = _([1, 2, 3]); + strictEqual(JSON.stringify(wrapped), '[1,2,3]'); } else { skipTest(); } }); + + test('should be aliased', 2, function() { + if (!isNpm) { + var expected = _.prototype.valueOf; + strictEqual(_.prototype.toJSON, expected); + strictEqual(_.prototype.value, expected); + } + else { + skipTest(2); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -9035,7 +10246,7 @@ 'unshift' ]; - _.forEach(funcs, function(methodName) { + _.each(funcs, function(methodName) { test('`_(...).' + methodName + '` should return the existing wrapped value', 1, function() { if (!isNpm) { strictEqual(wrapped[methodName](), wrapped); @@ -9061,7 +10272,7 @@ 'splice' ]; - _.forEach(funcs, function(methodName) { + _.each(funcs, function(methodName) { test('`_(...).' + methodName + '` should return a new wrapped value', 1, function() { if (!isNpm) { ok(wrapped[methodName]() instanceof _); @@ -9114,14 +10325,14 @@ 'some' ]; - _.forEach(funcs, function(methodName) { + _.each(funcs, function(methodName) { test('`_(...).' + methodName + '` should return an unwrapped value', 1, function() { if (!isNpm) { var actual = methodName == 'reduceRight' ? wrapped[methodName](_.identity) : wrapped[methodName](); - equal(actual instanceof _, false); + ok(!(actual instanceof _)); } else { skipTest(); @@ -9144,10 +10355,10 @@ 'sample' ]; - _.forEach(funcs, function(methodName) { + _.each(funcs, function(methodName) { test('`_(...).' + methodName + '` called without an `n` argument should return an unwrapped value', 1, function() { if (!isNpm) { - equal(typeof wrapped[methodName](), 'number'); + strictEqual(typeof wrapped[methodName](), 'number'); } else { skipTest(); @@ -9166,10 +10377,10 @@ test('`_.' + methodName + '` should return `undefined` when querying falsey arguments without an `n` argument', 1, function() { if (!isNpm) { var actual = [], - expected = _.map(falsey, function() { return undefined; }), + expected = _.map(falsey, _.constant()), func = _[methodName]; - _.forEach(falsey, function(value, index) { + _.each(falsey, function(value, index) { try { actual.push(index ? func(value) : func()); } catch(e) { } @@ -9184,7 +10395,7 @@ test('`_.' + methodName + '` should return an empty array when querying falsey arguments with an `n` argument', 1, function() { if (!isNpm) { - var expected = _.map(falsey, function() { return []; }), + var expected = _.map(falsey, _.constant([])), func = _[methodName]; var actual = _.map(falsey, function(value, index) { @@ -9245,21 +10456,22 @@ deepEqual([args[0], args[1], args[2]], [1, [3], 5], message('pull')); _.remove(args, function(value) { return typeof value == 'number'; }); - ok(args.length == 1 && _.isEqual(args[0], [3]), message('remove')); + ok(args.length === 1 && _.isEqual(args[0], [3]), message('remove')); } else { skipTest(2) } }); - test('should accept falsey primary arguments', 3, function() { + test('should accept falsey primary arguments', 4, function() { function message(methodName) { return '`_.' + methodName + '` should accept falsey primary arguments'; } - deepEqual(_.difference(null, array), [], message('difference')); - deepEqual(_.intersection(null, array), [], message('intersection')); + deepEqual(_.difference(null, array), array, message('difference')); + deepEqual(_.intersection(null, array), array, message('intersection')); deepEqual(_.union(null, array), array, message('union')); + deepEqual(_.xor(null, array), array, message('xor')); }); test('should accept falsey secondary arguments', 3, function() { @@ -9268,13 +10480,49 @@ } deepEqual(_.difference(array, null), array, message('difference')); - deepEqual(_.intersection(array, null), [], message('intersection')); + deepEqual(_.intersection(array, null), array, message('intersection')); deepEqual(_.union(array, null), array, message('union')); }); }(1, null, [3], null, 5)); /*--------------------------------------------------------------------------*/ + /*--------------------------------------------------------------------------*/ + + QUnit.module('"Strings" category methods'); + + (function() { + var stringMethods = [ + 'camelCase', + 'capitalize', + 'escape', + 'escapeRegExp', + 'kebabCase', + 'pad', + 'padLeft', + 'padRight', + 'repeat', + 'snakeCase', + 'trim', + 'trimLeft', + 'trimRight', + 'truncate', + 'unescape' + ]; + + _.each(stringMethods, function(methodName) { + var func = _[methodName]; + + test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string', 3, function() { + strictEqual(func(null), ''); + strictEqual(func(undefined), ''); + strictEqual(func(''), ''); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash methods'); (function() { @@ -9299,10 +10547,10 @@ 'pairs', 'pluck', 'pull', + 'pullAt', 'range', 'reject', 'remove', - 'removeAt', 'rest', 'sample', 'shuffle', @@ -9327,6 +10575,7 @@ 'defer', 'delay', 'memoize', + 'negate', 'once', 'partial', 'partialRight', @@ -9337,12 +10586,12 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 167, function() { - var emptyArrays = _.map(falsey, function() { return []; }), + test('should accept falsey arguments', 187, function() { + var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; - _.forEach(acceptFalsey, function(methodName) { + _.each(acceptFalsey, function(methodName) { var expected = emptyArrays, func = _[methodName], pass = true; @@ -9373,7 +10622,7 @@ }); // skip tests for missing methods of modularized builds - _.forEach(['noConflict', 'runInContext', 'tap'], function(methodName) { + _.each(['noConflict', 'runInContext', 'tap'], function(methodName) { if (!_[methodName]) { skipTest(); } @@ -9383,7 +10632,7 @@ test('should return an array', 66, function() { var array = [1, 2, 3]; - _.forEach(returnArrays, function(methodName) { + _.each(returnArrays, function(methodName) { var actual, func = _[methodName]; @@ -9402,13 +10651,13 @@ ok(_.isArray(actual), '_.' + methodName + ' returns an array'); var isPull = methodName == 'pull'; - equal(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array'); + strictEqual(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array'); }); }); - test('should reject falsey arguments', 14, function() { - _.forEach(rejectFalsey, function(methodName) { - var expected = _.map(falsey, function() { return true; }), + test('should throw a TypeError for falsey arguments', 15, function() { + _.each(rejectFalsey, function(methodName) { + var expected = _.map(falsey, _.constant(true)), func = _[methodName]; var actual = _.map(falsey, function(value, index) { @@ -9425,14 +10674,18 @@ }); }); - test('should handle `null` `thisArg` arguments', 30, function() { - var thisArg, - callback = function() { thisArg = this; }, - expected = (function() { return this; }).call(null); + test('should handle `null` `thisArg` arguments', 44, function() { + var expected = (function() { return this; }).call(null); var funcs = [ + 'assign', + 'clone', + 'cloneDeep', 'countBy', + 'dropWhile', + 'dropRightWhile', 'every', + 'flatten', 'filter', 'find', 'findIndex', @@ -9447,10 +10700,14 @@ 'forOwn', 'forOwnRight', 'groupBy', + 'isEqual', 'map', + 'mapValues', 'max', + 'merge', 'min', 'omit', + 'partition', 'pick', 'reduce', 'reduceRight', @@ -9459,38 +10716,46 @@ 'some', 'sortBy', 'sortedIndex', + 'takeWhile', + 'takeRightWhile', + 'tap', 'times', + 'transform', 'uniq' ]; - _.forEach(funcs, function(methodName) { - var array = ['a'], + _.each(funcs, function(methodName) { + var actual, + array = ['a'], func = _[methodName], message = '`_.' + methodName + '` handles `null` `thisArg` arguments'; - thisArg = undefined; - - if (/^reduce/.test(methodName)) { - func(array, callback, 0, null); - } else if (methodName == 'sortedIndex') { - func(array, 'a', callback, null); - } else if (methodName == 'times') { - func(1, callback, null); - } else { - func(array, callback, null); + function callback() { + actual = this; } - - if (expected === null) { - strictEqual(thisArg, null, message); - } else { - equal(thisArg, expected, message); + if (func) { + if (/^reduce/.test(methodName) || methodName == 'transform') { + func(array, callback, 0, null); + } else if (_.contains(['assign', 'merge'], methodName)) { + func(array, array, callback, null); + } else if (_.contains(['isEqual', 'sortedIndex'], methodName)) { + func(array, 'a', callback, null); + } else if (methodName == 'times') { + func(1, callback, null); + } else { + func(array, callback, null); + } + strictEqual(actual, expected, message); + } + else { + skipTest(); } }); }); test('should not contain minified method names (test production builds)', 1, function() { ok(_.every(_.functions(_), function(methodName) { - return methodName.length > 2 || methodName == 'at'; + return methodName.length > 2 || methodName === 'at'; })); }); }()); From 649994464cbd6e5f32bb9b91a474a277fbb870fa Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 02:10:39 -0700 Subject: [PATCH 0616/1608] Tweak docs for `_.pull`, `_.pullAt`, and `_.remove`. [ci skip] --- lodash.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lodash.js b/lodash.js index eae8c26cd2..b64ed8bae9 100644 --- a/lodash.js +++ b/lodash.js @@ -2932,9 +2932,9 @@ } /** - * Removes elements located at the given indexes and returns an array of - * removed elements. Indexes may be specified as an array of indexes or as - * individual arguments. + * Removes elements from `array` corresponding to the specified indexes and + * returns an array of removed elements. Indexes may be specified as an array + * of indexes or as individual arguments. * * Note: Like `_.pull`, this method mutates `array`. * @@ -2999,17 +2999,17 @@ * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the array of removed elements. + * @returns {Array} Returns the new array of removed elements. * @example * - * var array = [1, 2, 3, 4, 5, 6]; + * var array = [1, 2, 3, 4]; * var evens = _.remove(array, function(num) { return num % 2 == 0; }); * * console.log(array); - * // => [1, 3, 5] + * // => [1, 3] * * console.log(evens); - * // => [2, 4, 6] + * // => [2, 4] */ function remove(array, predicate, thisArg) { var index = -1, @@ -3637,9 +3637,9 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array of elements from the specified indexes, or keys, of the - * `collection`. Indexes may be specified as individual arguments or as arrays - * of indexes. + * Creates an array of elements corresponding to the specified keys, or indexes, + * of the collection. Keys may be specified as individual arguments or as arrays + * of keys. * * @static * @memberOf _ From 0631b8f052c4411c66d2ed3a022649dfd09fff98 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 02:10:54 -0700 Subject: [PATCH 0617/1608] Whitespace nit. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index b64ed8bae9..350fd7486a 100644 --- a/lodash.js +++ b/lodash.js @@ -6868,7 +6868,7 @@ while (length--) { omitProps[length] = String(omitProps[length]); } - return pick(object, baseDifference(keysIn(object), omitProps)); + return pick(object, baseDifference(keysIn(object), omitProps)); } /** From 85d8ced2996fafc4d45167c3b88cd608017f66ca Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 09:57:26 -0700 Subject: [PATCH 0618/1608] Add `baseAt` to reduce `_.at` and `_.pullAt`. --- lodash.js | 55 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/lodash.js b/lodash.js index 350fd7486a..88f23070b7 100644 --- a/lodash.js +++ b/lodash.js @@ -248,6 +248,28 @@ return typeof objectValue == 'undefined' ? sourceValue : objectValue; } + /** + * The base implementation of `_.at` without support for strings or individual + * key arguments. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object} collection The collection to iterate over. + * @param {number[]|string[]} [keys] The keys of elements to pick. + * @returns {Array} Returns the new array of picked elements. + */ + function baseAt(collection, props) { + var index = -1, + length = props.length, + result = Array(length); + + while(++index < length) { + result[index] = collection[props[index]]; + } + return result; + } + /** * The base implementation of `compareAscending` used to compare values and * sort them in ascending order without guaranteeing a stable sort. @@ -2936,7 +2958,7 @@ * returns an array of removed elements. Indexes may be specified as an array * of indexes or as individual arguments. * - * Note: Like `_.pull`, this method mutates `array`. + * Note: Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ @@ -2957,21 +2979,16 @@ * // => [10, 20] */ function pullAt(array) { - var previous, - index = -1, - removals = baseFlatten(arguments, true, false, 1), - length = removals.length, - result = Array(length); + var indexes = baseFlatten(arguments, true, false, 1), + length = indexes.length, + result = baseAt(array, indexes); - while (++index < length) { - result[index] = array[removals[index]]; - } - removals.sort(baseCompareAscending); + indexes.sort(baseCompareAscending); while (length--) { - var removal = removals[length]; - if (removal != previous) { - splice.call(array, removal, 1); - previous = removal; + var index = indexes[length]; + if (index != previous) { + var previous = removal; + splice.call(array, index, 1); } } return result; @@ -3657,18 +3674,10 @@ * // => ['fred', 'pebbles'] */ function at(collection) { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = props.length; - if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } - var result = Array(length); - while(++index < length) { - result[index] = collection[props[index]]; - } - return result; + return baseAt(collection, baseFlatten(arguments, true, false, 1)); } /** From 1e324103cc079c56540ec05d90af2411fbfc46a5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 09:58:13 -0700 Subject: [PATCH 0619/1608] Tweak docs for `_.at`, `_.omit`, and `_.pick`. [ci skip] --- lodash.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lodash.js b/lodash.js index 88f23070b7..43d4dc4e81 100644 --- a/lodash.js +++ b/lodash.js @@ -252,9 +252,7 @@ * The base implementation of `_.at` without support for strings or individual * key arguments. * - * @static - * @memberOf _ - * @category Collections + * @private * @param {Array|Object} collection The collection to iterate over. * @param {number[]|string[]} [keys] The keys of elements to pick. * @returns {Array} Returns the new array of picked elements. @@ -3664,7 +3662,7 @@ * @param {Array|Object|string} collection The collection to iterate over. * @param {...(number|number[]|string|string[])} [keys] The keys of elements * to pick, specified as individual keys or arrays of keys. - * @returns {Array} Returns the array of picked elements. + * @returns {Array} Returns the new array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); @@ -6851,7 +6849,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6919,7 +6917,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. From f23a458319d65849c7371cc7f819027efdd6e8d0 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 10:12:58 -0700 Subject: [PATCH 0620/1608] Fix typo in `_.pullAt`. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 43d4dc4e81..2a486a64fe 100644 --- a/lodash.js +++ b/lodash.js @@ -2985,7 +2985,7 @@ while (length--) { var index = indexes[length]; if (index != previous) { - var previous = removal; + var previous = index; splice.call(array, index, 1); } } From 4a0419e5544eabc17251661f819a42facdf58da3 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 10:44:25 -0700 Subject: [PATCH 0621/1608] Rebuild dist. --- dist/lodash.compat.js | 120 ++++++++++++++++++++++++----------- dist/lodash.compat.min.js | 128 +++++++++++++++++++------------------- dist/lodash.js | 120 ++++++++++++++++++++++++----------- dist/lodash.min.js | 122 ++++++++++++++++++------------------ dist/lodash.underscore.js | 18 +++--- 5 files changed, 302 insertions(+), 206 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 171c8782f0..d9d2f478b1 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -249,6 +249,26 @@ return typeof objectValue == 'undefined' ? sourceValue : objectValue; } + /** + * The base implementation of `_.at` without support for strings or individual + * key arguments. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {number[]|string[]} [keys] The keys of elements to pick. + * @returns {Array} Returns the new array of picked elements. + */ + function baseAt(collection, props) { + var index = -1, + length = props.length, + result = Array(length); + + while(++index < length) { + result[index] = collection[props[index]]; + } + return result; + } + /** * The base implementation of `compareAscending` used to compare values and * sort them in ascending order without guaranteeing a stable sort. @@ -669,8 +689,8 @@ * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, - * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, - * `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, + * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, @@ -2932,6 +2952,47 @@ return array; } + /** + * Removes elements from `array` corresponding to the specified indexes and + * returns an array of removed elements. Indexes may be specified as an array + * of indexes or as individual arguments. + * + * Note: Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to modify. + * @param {...(number|number[])} [index] The indexes of values to remove, + * specified as individual indexes or arrays of indexes. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [5, 10, 15, 20]; + * var evens = _.removeAt(array, [1, 3]); + * + * console.log(array); + * // => [5, 15] + * + * console.log(evens); + * // => [10, 20] + */ + function pullAt(array) { + var indexes = baseFlatten(arguments, true, false, 1), + length = indexes.length, + result = baseAt(array, indexes); + + indexes.sort(baseCompareAscending); + while (length--) { + var index = indexes[length]; + if (index != previous) { + var previous = index; + splice.call(array, index, 1); + } + } + return result; + } + /** * Removes all elements from `array` that the predicate returns truthy for * and returns an array of removed elements. The predicate is bound to `thisArg` @@ -2954,17 +3015,17 @@ * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the array of removed elements. + * @returns {Array} Returns the new array of removed elements. * @example * - * var array = [1, 2, 3, 4, 5, 6]; + * var array = [1, 2, 3, 4]; * var evens = _.remove(array, function(num) { return num % 2 == 0; }); * * console.log(array); - * // => [1, 3, 5] + * // => [1, 3] * * console.log(evens); - * // => [2, 4, 6] + * // => [2, 4] */ function remove(array, predicate, thisArg) { var index = -1, @@ -3592,17 +3653,17 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array of elements from the specified indexes, or keys, of the - * `collection`. Indexes may be specified as individual arguments or as arrays - * of indexes. + * Creates an array of elements corresponding to the specified keys, or indexes, + * of the collection. Keys may be specified as individual arguments or as arrays + * of keys. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes to retrieve, - * specified as individual indexes or arrays of indexes. - * @returns {Array} Returns the array of picked elements. + * @param {...(number|number[]|string|string[])} [keys] The keys of elements + * to pick, specified as individual keys or arrays of keys. + * @returns {Array} Returns the new array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); @@ -3611,25 +3672,11 @@ * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ - function at(collection, guard) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), - length = props.length, - type = typeof guard; - - // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) { - length = 1; - } + function at(collection) { if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } - var result = Array(length); - while(++index < length) { - result[index] = collection[props[index]]; - } - return result; + return baseAt(collection, baseFlatten(arguments, true, false, 1)); } /** @@ -4910,8 +4957,8 @@ * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. + * @param {...string} [methodNames] The object method names to bind, specified + * as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * @@ -5526,7 +5573,7 @@ * @alias extend * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -5734,7 +5781,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example @@ -6724,7 +6771,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -6803,7 +6850,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6829,7 +6876,7 @@ while (length--) { omitProps[length] = String(omitProps[length]); } - return pick(object, baseDifference(keysIn(object), omitProps)); + return pick(object, baseDifference(keysIn(object), omitProps)); } /** @@ -6871,7 +6918,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -8338,6 +8385,7 @@ lodash.pluck = pluck; lodash.property = property; lodash.pull = pull; + lodash.pullAt = pullAt; lodash.range = range; lodash.reject = reject; lodash.remove = remove; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 381b63ae1c..0c06c15857 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -3,67 +3,67 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Pr(e);++ri(t,l)&&f.push(l);return f}function bt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1a(s,g)&&((u||f)&&s.push(g),c.push(p))}return c}function Nt(n,t){for(var r=-1,e=t(n),u=e.length,o=Pr(u);++ro?0:o)}function Zt(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?Ce(u+e,0):e||0;else if(e)return e=Xt(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function Kt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=c.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),Jt(n,0,0>o?0:o)}function Mt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; -for(t=c.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:d;return o=e-(o||0),Jt(n,0>o?0:o)}function Vt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=c.createCallback(t,r,3);++et?0:t;return Jt(n,o)}function Jt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=Ce(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=Ce(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Pr(u);++e>>1,r(n[e])r?0:r);++tr?Ce(e+r,0):r||0:0,typeof n=="string"||!$e(n)&&kr(n)?ro&&(o=a)}else t=null==t&&kr(n)?u:c.createCallback(t,r,3),bt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function lr(n,t){return ir(n,$r(t))}function fr(n,t,r,e){var u=3>arguments.length; -if(t=c.createCallback(t,e,4),$e(n)){var o=-1,i=n.length;for(u&&i&&(r=n[++o]);++oarguments.length;return t=c.createCallback(t,e,4),_t(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function sr(n){var t=-1,r=n&&n.length,e=Pr(0>r?0:r>>>0);return bt(n,function(n){var r=It(0,++t);e[t]=e[r],e[r]=n}),e}function pr(n,t,r){var e;if(t=c.createCallback(t,r,3),$e(n)){r=-1;for(var u=n.length;++rarguments.length)return Ft(n,b,null,t);if(n)var r=n[O]?n[O][2]:n.length,e=Jt(arguments,2),r=r-e.length;return Ft(n,b|C,r,t,e)}function hr(n,t,r){var e,u,o,i,a,l,f,c=0,s=false,p=true;if(!wr(n))throw new Jr(E);if(t=0>t?0:t,true===r)var g=true,p=false;else xr(r)&&(g=r.leading,s="maxWait"in r&&Ce(t,+r.maxWait||0),p="trailing"in r?r.trailing:p);var h=function(){var r=t-(Ue()-i);0>=r||r>t?(u&&oe(u),r=f,u=l=f=d,r&&(c=Ue(),o=n.apply(a,e),l||u||(e=a=null))):l=ge(h,r) -},v=function(){l&&oe(l),u=l=f=d,(p||s!==t)&&(c=Ue(),o=n.apply(a,e),l||u||(e=a=null))};return function(){if(e=arguments,i=Ue(),a=this,f=p&&(l||!g),false===s)var r=g&&!l;else{u||g||(c=i);var y=s-(i-c),m=0>=y||y>s;m?(u&&(u=oe(u)),c=i,o=n.apply(a,e)):u||(u=ge(v,y))}return m&&l?l=oe(l):l||t===s||(l=ge(h,t)),r&&(m=true,o=n.apply(a,e)),!m||l||u||(e=a=null),o}}function vr(n){if(!wr(n))throw new Jr(E);return function(){return!n.apply(this,arguments)}}function yr(n,t,r){var e=arguments;if(!n||2>e.length)return n; -var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,i=r-1,e=Pr(r),a=0t||null==n||!_e(t))return r;n=Vr(n);do t%2&&(r+=n),t=ie(t/2),n+=n;while(t);return r}function Rr(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(h(n),v(n)+1):(t=Vr(t),n.slice(o(n,t),i(n,t)+1)):n}function Nr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||ht(n,t,r):"object"==e?Lr(n):$r(n)}function Tr(n){return n -}function Lr(n){var t=ze(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||xr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=fe.call(e,o)&&At(e[o],n[o],null,true)););return o}:function(n){return n&&fe.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function Wr(n,t,r){var e=true,u=t&&dr(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=dr(t)),false===r?e=false:xr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=wr(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},c.assign=yr,c.at=function(n,t){var r=arguments,e=-1,u=xt(r,true,false,1),o=u.length,i=typeof t;for("number"!=i&&"string"!=i||!r[2]||r[2][t]!==n||(o=1),Ie.unindexedChars&&kr(n)&&(n=n.split("")),r=Pr(o);++earguments.length?Ft(t,b|_,null,n):Ft(t,b|_|C,null,n,Jt(arguments,2))},c.chain=function(n){return new q(n,true)},c.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?e(p,l):i(s,l))){for(t=u;--t;){var g=o[t]; -if(0>(g?e(g,l):i(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},c.invert=function(n,t){for(var r=-1,e=ze(n),u=e.length,o={};++ro?0:o>>>0);return bt(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):d}),i},c.keys=ze,c.keysIn=Or,c.map=ir,c.mapValues=function(n,t,r){var e={};return t=c.createCallback(t,r,3),Ot(n,function(n,r,u){e[r]=t(n,r,u) -}),e},c.matches=Lr,c.max=ar,c.memoize=function(n,t){if(!wr(n)||t&&!wr(t))throw new Jr(E);var r=function(){var e=r.cache,u=t?t.apply(this,arguments):"_"+arguments[0];return fe.call(e,u)?e[u]:e[u]=n.apply(this,arguments)};return r.cache={},r},c.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0);for(o||(t=c.createCallback(t,r,3)),bt(n,function(n,r,u){if(o)for(r=t.length,u=Pr(r);r--;)u[r]=n[t[r]]; -else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?l:a);u--;)i[u]=i[u].c;return i},c.tap=function(n,t,r){return t.call(r,n),n},c.throttle=function(n,t,r){var e=true,u=true;if(!wr(n))throw new Jr(E);return false===r?e=false:xr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),lt.leading=e,lt.maxWait=+t,lt.trailing=u,hr(n,t,lt)},c.times=function(n,t,r){n=0>n?0:n>>>0,t=ht(t,r,1),r=-1;for(var e=Pr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},c.escape=function(n){return null==n?"":Vr(n).replace(L,s)},c.escapeRegExp=Sr,c.every=tr,c.find=er,c.findIndex=qt,c.findKey=function(n,t,r){return t=c.createCallback(t,r,3),wt(n,t,Ot,true)},c.findLast=function(n,t,r){return t=c.createCallback(t,r,3),wt(n,t,_t) -},c.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=c.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},c.findLastKey=function(n,t,r){return t=c.createCallback(t,r,3),wt(n,t,Et,true)},c.findWhere=function(n,t){return er(n,Lr(t))},c.has=function(n,t){return n?fe.call(n,t):false},c.identity=Tr,c.indexOf=Zt,c.isArguments=br,c.isArray=$e,c.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&re.call(n)==Q||false},c.isDate=function(n){return n&&typeof n=="object"&&re.call(n)==nt||false -},c.isElement=_r,c.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Ce(e+r,0):je(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},c.noConflict=function(){return t._=ne,this},c.noop=Fr,c.now=Ue,c.pad=function(n,t,r){n=null==n?"":Vr(n),t=+t;var e=n.length; -return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},c.template=function(n,t,r){var e=c.templateSettings;r=mr({},r,e),n=Vr(null==n?"":n);var u,o,i=mr({},r.imports,e.imports),e=ze(i),i=Ar(i),a=0,l=r.interpolate||U,f="__p+='",l=Mr((r.escape||U).source+"|"+l.source+"|"+(l===$?P:U).source+"|"+(r.evaluate||U).source+"|$","g"); -n.replace(l,function(t,r,e,i,l,c){return e||(e=i),f+=n.slice(a,c).replace(M,p),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(I,""):f).replace(R,"$1").replace(N,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var s=qr(e,"return "+f).apply(d,i) -}catch(g){throw g.source=f,g}return t?s(t):(s.source=f,s)},c.trim=Rr,c.trimLeft=function(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(h(n)):(t=Vr(t),n.slice(o(n,t))):n},c.trimRight=function(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(0,v(n)+1):(t=Vr(t),n.slice(0,i(n,t)+1)):n},c.truncate=function(n,t){var r=30,e="...";if(t&&xr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Vr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Vr(n),r>=n.length)return n; -var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(jr(u)){if(n.slice(o).search(u)){var i,a,l=n.slice(0,o);for(u.global||(u=Mr(u.source,(z.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(l);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(T,y))},c.uniqueId=function(n){var t=++A;return Vr(null==n?"":n)+t},c.all=tr,c.any=pr,c.detect=er,c.foldl=fr,c.foldr=cr,c.include=nr,c.inject=fr,Wr(c,function(){var n={}; -return Ot(c,function(t,r){c.prototype[r]||(n[r]=t)}),n}(),false),c.first=Ut,c.last=Mt,c.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Ar(n):Ie.unindexedChars&&kr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},c.take=Ut,c.takeRight=Mt,c.takeRightWhile=Mt,c.takeWhile=Ut,c.head=Ut,Ot(c,function(n,t){var r="sample"!==t;c.prototype[t]||(c.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new q(o,u):o -})}),c.VERSION=k,c.prototype.chain=function(){return this.__chain__=true,this},c.prototype.toJSON=Qt,c.prototype.toString=function(){return Vr(this.__wrapped__)},c.prototype.value=Qt,c.prototype.valueOf=Qt,V(["join","pop","shift"],function(n){var t=Xr[n];c.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new q(r,n):r}}),V(["push","reverse","sort","unshift"],function(n){var t=Xr[n];c.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),V(["concat","splice"],function(n){var t=Xr[n]; -c.prototype[n]=function(){return new q(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Ie.spliceObjects||V(["pop","shift","splice"],function(n){var t=Xr[n],r="splice"==n;c.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new q(u,n):u}}),c}var d,b=1,_=2,w=4,x=8,C=16,j=32,k="2.4.1",O="__lodash@"+k+"__",E="Expected a function",A=0,S=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,N=/(__e\(.*?\)|\b__t\))\+'';/g,T=/&(?:amp|lt|gt|quot|#39);/g,L=/[&<>"']/g,W=/<%-([\s\S]+?)%>/g,F=/<%([\s\S]+?)%>/g,$=/<%=([\s\S]+?)%>/g,P=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,z=/\w*$/,D=/^\s*function[ \n\r\t]+\w/,B=/^0[xX]/,q=/[\xC0-\xFF]/g,U=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,M=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Y="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),G="[object Arguments]",H="[object Array]",Q="[object Boolean]",nt="[object Date]",tt="[object Error]",rt="[object Function]",et="[object Number]",ut="[object Object]",ot="[object RegExp]",it="[object String]",at={}; -at[rt]=false,at[G]=at[H]=at[Q]=at[nt]=at[et]=at[ut]=at[ot]=at[it]=true;var lt={leading:false,maxWait:0,trailing:false},ft={configurable:false,enumerable:false,value:null,writable:false},ct={"&":"&","<":"<",">":">",'"':""","'":"'"},st={"&":"&","<":"<",">":">",""":'"',"'":"'"},pt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},gt={"function":true,object:true},ht={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},vt=gt[typeof window]&&window||this,yt=gt[typeof exports]&&exports&&!exports.nodeType&&exports,gt=gt[typeof module]&&module&&!module.nodeType&&module,mt=yt&>&&typeof global=="object"&&global; -!mt||mt.global!==mt&&mt.window!==mt&&mt.self!==mt||(vt=mt);var mt=gt&>.exports===yt&&yt,dt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(vt._=dt, define(function(){return dt})):yt&>?mt?(gt.exports=dt)._=dt:yt._=dt:vt._=dt}).call(this); \ No newline at end of file +;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Dr(e);++ri(t,l)&&f.push(l);return f}function wt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1a(s,g)&&((r||f)&&s.push(g),c.push(p))}return c}function Lt(n,t){for(var r=-1,e=t(n),u=e.length,o=Dr(u);++ro?0:o)}function Mt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?ke(u+r,0):r||0;else if(r)return r=Gt(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function Vt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),Yt(n,0,0>o?0:o)}function Jt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; +for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:b;return o=e-(o||0),Yt(n,0>o?0:o)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return Yt(n,o)}function Yt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=ke(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=ke(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Dr(u);++e>>1,r(n[e])r?0:r);++tr?ke(e+r,0):r||0:0,typeof n=="string"||!ze(n)&&Er(n)?ru&&(u=a)}else t=null==t&&Er(n)?o:U.createCallback(t,r,3),wt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function cr(n,t){return lr(n,zr(t))}function sr(n,t,r,e){var u=3>arguments.length; +if(t=U.createCallback(t,e,4),ze(n)){var o=-1,i=n.length;for(u&&i&&(r=n[++o]);++oarguments.length;return t=U.createCallback(t,e,4),xt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function gr(n){var t=-1,r=n&&n.length,e=Dr(0>r?0:r>>>0);return wt(n,function(n){var r=Nt(0,++t);e[t]=e[r],e[r]=n}),e}function hr(n,t,r){var e;if(t=U.createCallback(t,r,3),ze(n)){r=-1;for(var u=n.length;++rarguments.length)return Pt(n,_,null,t);if(n)var r=n[E]?n[E][2]:n.length,e=Yt(arguments,2),r=r-e.length;return Pt(n,_|j,r,t,e)}function yr(n,t,r){var e,u,o,i,a,l,f,c=0,s=false,p=true;if(!Cr(n))throw new Yr(A);if(t=0>t?0:t,true===r)var g=true,p=false;else jr(r)&&(g=r.leading,s="maxWait"in r&&ke(t,+r.maxWait||0),p="trailing"in r?r.trailing:p);var h=function(){var r=t-(Ke()-i);0>=r||r>t?(u&&ae(u),r=f,u=l=f=b,r&&(c=Ke(),o=n.apply(a,e),l||u||(e=a=null))):l=ve(h,r) +},v=function(){l&&ae(l),u=l=f=b,(p||s!==t)&&(c=Ke(),o=n.apply(a,e),l||u||(e=a=null))};return function(){if(e=arguments,i=Ke(),a=this,f=p&&(l||!g),false===s)var r=g&&!l;else{u||g||(c=i);var y=s-(i-c),m=0>=y||y>s;m?(u&&(u=ae(u)),c=i,o=n.apply(a,e)):u||(u=ve(v,y))}return m&&l?l=ae(l):l||t===s||(l=ve(h,t)),r&&(m=true,o=n.apply(a,e)),!m||l||u||(e=a=null),o}}function mr(n){if(!Cr(n))throw new Yr(A);return function(){return!n.apply(this,arguments)}}function dr(n,t,r){var e=arguments;if(!n||2>e.length)return n; +var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,i=r-1,e=Dr(r),a=0t||null==n||!xe(t))return r;n=Xr(n);do t%2&&(r+=n),t=le(t/2),n+=n;while(t);return r}function Tr(n,t){return(n=null==n?"":Xr(n))?null==t?n.slice(v(n),y(n)+1):(t=Xr(t),n.slice(i(n,t),a(n,t)+1)):n}function Lr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||mt(n,t,r):"object"==e?Fr(n):zr(n)}function Wr(n){return n +}function Fr(n){var t=Be(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||jr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=se.call(e,o)&&It(e[o],n[o],null,true)););return o}:function(n){return n&&se.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function $r(n,t,r){var e=true,u=t&&_r(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=_r(t)),false===r?e=false:jr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=Cr(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},U.assign=dr,U.at=function(n){return Ne.unindexedChars&&Er(n)&&(n=n.split("")),t(n,jt(arguments,true,false,1))},U.bind=vr,U.bindAll=function(n){for(var t=1arguments.length?Pt(t,_|w,null,n):Pt(t,_|w|j,null,n,Yt(arguments,2))},U.chain=function(n){return new J(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?u(p,l):i(s,l))){for(t=r;--t;){var g=o[t];if(0>(g?u(g,l):i(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},U.invert=function(n,t){for(var r=-1,e=Be(n),u=e.length,o={};++ro?0:o>>>0);return wt(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):b}),i},U.keys=Be,U.keysIn=Ar,U.map=lr,U.mapValues=function(n,t,r){var e={};return t=U.createCallback(t,r,3),At(n,function(n,r,u){e[r]=t(n,r,u)}),e},U.matches=Fr,U.max=fr,U.memoize=function(n,t){if(!Cr(n)||t&&!Cr(t))throw new Yr(A);var r=function(){var e=r.cache,u=t?t.apply(this,arguments):"_"+arguments[0]; +return se.call(e,u)?e[u]:e[u]=n.apply(this,arguments)};return r.cache={},r},U.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0); +for(o||(t=U.createCallback(t,r,3)),wt(n,function(n,r,u){if(o)for(r=t.length,u=Dr(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?f:l);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!Cr(n))throw new Yr(A);return false===r?e=false:jr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ft.leading=e,ft.maxWait=+t,ft.trailing=u,yr(n,t,ft)},U.times=function(n,t,r){n=0>n?0:n>>>0,t=mt(t,r,1),r=-1; +for(var e=Dr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Xr(n).replace(W,p)},U.escapeRegExp=Rr,U.every=er,U.find=or,U.findIndex=Zt,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,At,true) +},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,xt)},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,St,true)},U.findWhere=function(n,t){return or(n,Fr(t))},U.has=function(n,t){return n?se.call(n,t):false},U.identity=Wr,U.indexOf=Mt,U.isArguments=wr,U.isArray=ze,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ue.call(n)==nt||false +},U.isDate=function(n){return n&&typeof n=="object"&&ue.call(n)==tt||false},U.isElement=xr,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?ke(e+r,0):Oe(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return s._=re,this},U.noop=Pr,U.now=Ke,U.pad=function(n,t,r){n=null==n?"":Xr(n),t=+t; +var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=br({},r,e),n=Xr(null==n?"":n);var u,o,i=br({},r.imports,e.imports),e=Be(i),i=Ir(i),a=0,l=r.interpolate||Z,f="__p+='",l=Jr((r.escape||Z).source+"|"+l.source+"|"+(l===P?z:Z).source+"|"+(r.evaluate||Z).source+"|$","g"); +n.replace(l,function(t,r,e,i,l,c){return e||(e=i),f+=n.slice(a,c).replace(V,g),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(R,""):f).replace(N,"$1").replace(T,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var c=Zr(e,"return "+f).apply(b,i) +}catch(s){throw s.source=f,s}return t?c(t):(c.source=f,c)},U.trim=Tr,U.trimLeft=function(n,t){return(n=null==n?"":Xr(n))?null==t?n.slice(v(n)):(t=Xr(t),n.slice(i(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Xr(n))?null==t?n.slice(0,y(n)+1):(t=Xr(t),n.slice(0,a(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&jr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Xr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Xr(n),r>=n.length)return n; +var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(Or(u)){if(n.slice(o).search(u)){var i,a,l=n.slice(0,o);for(u.global||(u=Jr(u.source,(D.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(l);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(L,m))},U.uniqueId=function(n){var t=++S;return Xr(null==n?"":n)+t},U.all=er,U.any=hr,U.detect=or,U.foldl=sr,U.foldr=pr,U.include=rr,U.inject=sr,$r(U,function(){var n={}; +return At(U,function(t,r){U.prototype[r]||(n[r]=t)}),n}(),false),U.first=Kt,U.last=Jt,U.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Ir(n):Ne.unindexedChars&&Er(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Kt,U.takeRight=Jt,U.takeRightWhile=Jt,U.takeWhile=Kt,U.head=Kt,At(U,function(n,t){var r="sample"!==t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o +})}),U.VERSION=O,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=tr,U.prototype.toString=function(){return Xr(this.__wrapped__)},U.prototype.value=tr,U.prototype.valueOf=tr,st(["join","pop","shift"],function(n){var t=Gr[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),st(["push","reverse","sort","unshift"],function(n){var t=Gr[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this} +}),st(["concat","splice"],function(n){var t=Gr[n];U.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Ne.spliceObjects||st(["pop","shift","splice"],function(n){var t=Gr[n],r="splice"==n;U.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),U}var b,_=1,w=2,x=4,C=8,j=16,k=32,O="2.4.1",E="__lodash@"+O+"__",A="Expected a function",S=0,I=/^[A-Z]+$/,R=/\b__p\+='';/g,N=/\b(__p\+=)''\+/g,T=/(__e\(.*?\)|\b__t\))\+'';/g,L=/&(?:amp|lt|gt|quot|#39);/g,W=/[&<>"']/g,F=/<%-([\s\S]+?)%>/g,$=/<%([\s\S]+?)%>/g,P=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,D=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,U=/[\xC0-\xFF]/g,Z=/($^)/,K=/[.*+?^${}()|[\]\/\\]/g,M=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",it="[object RegExp]",at="[object String]",lt={}; +lt[et]=false,lt[H]=lt[Q]=lt[nt]=lt[tt]=lt[ut]=lt[ot]=lt[it]=lt[at]=true;var ft={leading:false,maxWait:0,trailing:false},ct={configurable:false,enumerable:false,value:null,writable:false},st={"&":"&","<":"<",">":">",'"':""","'":"'"},pt={"&":"&","<":"<",">":">",""":'"',"'":"'"},gt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},ht={"function":true,object:true},vt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},yt=ht[typeof window]&&window||this,mt=ht[typeof exports]&&exports&&!exports.nodeType&&exports,ht=ht[typeof module]&&module&&!module.nodeType&&module,dt=mt&&ht&&typeof global=="object"&&global; +!dt||dt.global!==dt&&dt.window!==dt&&dt.self!==dt||(yt=dt);var dt=ht&&ht.exports===mt&&mt,bt=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(yt._=bt, define(function(){return bt})):mt&&ht?dt?(ht.exports=bt)._=bt:mt._=bt:yt._=bt}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 4c73927e7a..eb914d1a43 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -243,6 +243,26 @@ return typeof objectValue == 'undefined' ? sourceValue : objectValue; } + /** + * The base implementation of `_.at` without support for strings or individual + * key arguments. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {number[]|string[]} [keys] The keys of elements to pick. + * @returns {Array} Returns the new array of picked elements. + */ + function baseAt(collection, props) { + var index = -1, + length = props.length, + result = Array(length); + + while(++index < length) { + result[index] = collection[props[index]]; + } + return result; + } + /** * The base implementation of `compareAscending` used to compare values and * sort them in ascending order without guaranteeing a stable sort. @@ -629,8 +649,8 @@ * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, - * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, - * `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, + * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, @@ -2751,6 +2771,47 @@ return array; } + /** + * Removes elements from `array` corresponding to the specified indexes and + * returns an array of removed elements. Indexes may be specified as an array + * of indexes or as individual arguments. + * + * Note: Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to modify. + * @param {...(number|number[])} [index] The indexes of values to remove, + * specified as individual indexes or arrays of indexes. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [5, 10, 15, 20]; + * var evens = _.removeAt(array, [1, 3]); + * + * console.log(array); + * // => [5, 15] + * + * console.log(evens); + * // => [10, 20] + */ + function pullAt(array) { + var indexes = baseFlatten(arguments, true, false, 1), + length = indexes.length, + result = baseAt(array, indexes); + + indexes.sort(baseCompareAscending); + while (length--) { + var index = indexes[length]; + if (index != previous) { + var previous = index; + splice.call(array, index, 1); + } + } + return result; + } + /** * Removes all elements from `array` that the predicate returns truthy for * and returns an array of removed elements. The predicate is bound to `thisArg` @@ -2773,17 +2834,17 @@ * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the array of removed elements. + * @returns {Array} Returns the new array of removed elements. * @example * - * var array = [1, 2, 3, 4, 5, 6]; + * var array = [1, 2, 3, 4]; * var evens = _.remove(array, function(num) { return num % 2 == 0; }); * * console.log(array); - * // => [1, 3, 5] + * // => [1, 3] * * console.log(evens); - * // => [2, 4, 6] + * // => [2, 4] */ function remove(array, predicate, thisArg) { var index = -1, @@ -3411,17 +3472,17 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array of elements from the specified indexes, or keys, of the - * `collection`. Indexes may be specified as individual arguments or as arrays - * of indexes. + * Creates an array of elements corresponding to the specified keys, or indexes, + * of the collection. Keys may be specified as individual arguments or as arrays + * of keys. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes to retrieve, - * specified as individual indexes or arrays of indexes. - * @returns {Array} Returns the array of picked elements. + * @param {...(number|number[]|string|string[])} [keys] The keys of elements + * to pick, specified as individual keys or arrays of keys. + * @returns {Array} Returns the new array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); @@ -3430,22 +3491,8 @@ * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ - function at(collection, guard) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), - length = props.length, - type = typeof guard; - - // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) { - length = 1; - } - var result = Array(length); - while(++index < length) { - result[index] = collection[props[index]]; - } - return result; + function at(collection) { + return baseAt(collection, baseFlatten(arguments, true, false, 1)); } /** @@ -4731,8 +4778,8 @@ * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. + * @param {...string} [methodNames] The object method names to bind, specified + * as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * @@ -5347,7 +5394,7 @@ * @alias extend * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -5555,7 +5602,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example @@ -6508,7 +6555,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -6587,7 +6634,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6613,7 +6660,7 @@ while (length--) { omitProps[length] = String(omitProps[length]); } - return pick(object, baseDifference(keysIn(object), omitProps)); + return pick(object, baseDifference(keysIn(object), omitProps)); } /** @@ -6655,7 +6702,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -8122,6 +8169,7 @@ lodash.pluck = pluck; lodash.property = property; lodash.pull = pull; + lodash.pullAt = pullAt; lodash.range = range; lodash.reject = reject; lodash.remove = remove; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index f39a589898..a2357273a2 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,64 +3,64 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(nr||13r||8202e||13e||8202>>0:0,u=$e(r);++ei(t,f)&&l.push(f);return l}function mt(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number"&&-1a(p,h)&&((u||l)&&p.push(h),c.push(s))}return c}function Rt(n,t){for(var e=-1,r=t(n),u=r.length,o=$e(u);++eo?0:o)}function Ut(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?br(u+r,0):r||0;else if(r)return r=Vt(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function Zt(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=c.createCallback(t,e,3);u--&&t(n[u],u,n);)o++ -}else o=null==t||e?1:t;return o=r-(o||0),Mt(n,0,0>o?0:o)}function Pt(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=c.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||e)return n?n[r-1]:m;return o=r-(o||0),Mt(n,0>o?0:o)}function Kt(n,t,e){if(typeof t!="number"&&null!=t){var r=-1,u=n?n.length:0,o=0;for(t=c.createCallback(t,e,3);++rt?0:t;return Mt(n,o)}function Mt(n,t,e){var r=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=br(u+t,0):t>u&&(t=u),e=typeof e=="undefined"?u:+e||0,0>e?e=br(u+e,0):e>u&&(e=u),u=t>e?0:e-t,e=$e(u);++r>>1,e(n[r])e?0:e);++te?br(r+e,0):e||0:0,typeof n=="string"||!Sr(n)&&ke(n)?eo&&(o=a)}else t=null==t&&ke(n)?u:c.createCallback(t,e,3),mt(n,function(n,e,u){e=t(n,e,u),(e>r||-1/0===e&&e===o)&&(r=e,o=n)});return o}function ie(n,t){return ue(n,Fe(t))}function ae(n,t,e,r){var u=3>arguments.length;t=c.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return t=c.createCallback(t,r,4),dt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o) -}),e}function le(n){var t=-1,e=n&&n.length,r=$e(0>e?0:e>>>0);return mt(n,function(n){var e=Et(0,++t);r[t]=r[e],r[e]=n}),r}function ce(n,t,e){var r;t=c.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return Wt(n,d,null,t);if(n)var e=n[C]?n[C][2]:n.length,r=Mt(arguments,2),e=e-r.length;return Wt(n,d|j,e,t,r)}function se(n,t,e){function r(){c&&tr(c),i=c=p=m,(g||h!==t)&&(s=Dr(),a=n.apply(l,o),c||i||(o=l=null)) -}function u(){var e=t-(Dr()-f);0>=e||e>t?(i&&tr(i),e=p,i=c=p=m,e&&(s=Dr(),a=n.apply(l,o),c||i||(o=l=null))):c=lr(u,e)}var o,i,a,f,l,c,p,s=0,h=false,g=true;if(!be(n))throw new Ke(O);if(t=0>t?0:t,true===e)var v=true,g=false;else _e(e)&&(v=e.leading,h="maxWait"in e&&br(t,+e.maxWait||0),g="trailing"in e?e.trailing:g);return function(){if(o=arguments,f=Dr(),l=this,p=g&&(c||!v),false===h)var e=v&&!c;else{i||v||(s=f);var y=h-(f-s),m=0>=y||y>h;m?(i&&(i=tr(i)),s=f,a=n.apply(l,o)):i||(i=lr(r,y))}return m&&c?c=tr(c):c||t===h||(c=lr(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a -}}function he(n){if(!be(n))throw new Ke(O);return function(){return!n.apply(this,arguments)}}function ge(n,t,e){var r=arguments;if(!n||2>r.length)return n;var u=0,o=r.length,i=typeof e;if("number"!=i&&"string"!=i||!r[3]||r[3][e]!==t||(o=2),3>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,i=$e(e),a=0t||null==n||!yr(t))return e;n=Pe(n);do t%2&&(e+=n),t=er(t/2),n+=n;while(t);return e}function Ie(n,t){return(n=null==n?"":Pe(n))?null==t?n.slice(h(n),g(n)+1):(t=Pe(t),n.slice(o(n,t),i(n,t)+1)):n}function Re(n,t,e){var r=typeof n;return"function"==r||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||st(n,t,e):"object"==r?Se(n):Fe(n) -}function Ne(n){return n}function Se(n){var t=Wr(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||_e(u)?function(r){var u=e;if(u&&!r)return false;for(var o=true;u--&&(o=t[u],o=or.call(r,o)&&Ot(r[o],n[o],null,true)););return o}:function(n){return n&&or.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function Te(n,t,e){var r=true,u=t&&ye(t);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=ye(t)),false===e?r=false:_e(e)&&"chain"in e&&(r=e.chain),e=-1;for(var o=be(n),i=u?u.length:0;++e--n?t.apply(this,arguments):void 0 -}},c.assign=ge,c.at=function(n,t){var e=arguments,r=-1,u=_t(e,true,false,1),o=u.length,i=typeof t;for("number"!=i&&"string"!=i||!e[2]||e[2][t]!==n||(o=1),e=$e(o);++rarguments.length?Wt(t,d|b,null,n):Wt(t,d|b|j,null,n,Mt(arguments,2))},c.chain=function(n){return new q(n,true)},c.compact=function(n){for(var t=-1,e=n?n.length:0,r=0,u=[];++t(s?r(s,f):i(p,f))){for(t=u;--t;){var h=o[t];if(0>(h?r(h,f):i(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},c.invert=function(n,t){for(var e=-1,r=Wr(n),u=r.length,o={};++eo?0:o>>>0);return mt(n,function(n){var o=u?t:null!=n&&n[t];i[++r]=o?o.apply(n,e):m -}),i},c.keys=Wr,c.keysIn=xe,c.map=ue,c.mapValues=function(n,t,e){var r={};return t=c.createCallback(t,e,3),xt(n,function(n,e,u){r[e]=t(n,e,u)}),r},c.matches=Se,c.max=oe,c.memoize=function(n,t){function e(){var r=e.cache,u=t?t.apply(this,arguments):"_"+arguments[0];return or.call(r,u)?r[u]:r[u]=n.apply(this,arguments)}if(!be(n)||t&&!be(t))throw new Ke(O);return e.cache={},e},c.merge=function(n,t,e){var r=arguments,u=r.length,o=typeof e;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!r[3]||r[3][e]!==t||(u=2),3u?0:u>>>0);for(o||(t=c.createCallback(t,e,3)),mt(n,function(n,e,u){if(o)for(e=t.length,u=$e(e);e--;)u[e]=n[t[e]];else u=t(n,e,u);i[++r]={a:u,b:r,c:n}}),u=i.length,i.sort(o?f:a);u--;)i[u]=i[u].c;return i},c.tap=function(n,t,e){return t.call(e,n),n},c.throttle=function(n,t,e){var r=true,u=true;if(!be(n))throw new Ke(O); -return false===e?r=false:_e(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),it.leading=r,it.maxWait=+t,it.trailing=u,se(n,t,it)},c.times=function(n,t,e){n=0>n?0:n>>>0,t=st(t,e,1),e=-1;for(var r=$e(n);++ee?0:+e||0,r))-t.length,0<=e&&n.indexOf(t,e)==e},c.escape=function(n){return null==n?"":Pe(n).replace(T,p)},c.escapeRegExp=Ae,c.every=Qt,c.find=te,c.findIndex=Bt,c.findKey=function(n,t,e){return t=c.createCallback(t,e,3),bt(n,t,xt,true) -},c.findLast=function(n,t,e){return t=c.createCallback(t,e,3),bt(n,t,dt)},c.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=c.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},c.findLastKey=function(n,t,e){return t=c.createCallback(t,e,3),bt(n,t,Ct,true)},c.findWhere=function(n,t){return te(n,Se(t))},c.has=function(n,t){return n?or.call(n,t):false},c.identity=Ne,c.indexOf=Ut,c.isArguments=me,c.isArray=Sr,c.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&He.call(n)==G||false -},c.isDate=function(n){return n&&typeof n=="object"&&He.call(n)==H||false},c.isElement=de,c.isEmpty=function(n){var t=true;if(!n)return t;var e=n.length;return-1e?br(r+e,0):_r(e||0,r-1))+1);r--;)if(n[r]===t)return r;return-1},c.noConflict=function(){return t._=Ye,this},c.noop=We,c.now=Dr,c.pad=function(n,t,e){n=null==n?"":Pe(n),t=+t; -var r=n.length;return re?0:+e||0,n.length),n.lastIndexOf(t,e)==e},c.template=function(n,t,e){var r=c.templateSettings;e=ve({},e,r),n=Pe(null==n?"":n);var u,o,i=ve({},e.imports,r.imports),r=Wr(i),i=Oe(i),a=0,f=e.interpolate||U,l="__p+='",f=Ze((e.escape||U).source+"|"+f.source+"|"+(f===$?z:U).source+"|"+(e.evaluate||U).source+"|$","g"); -n.replace(f,function(t,e,r,i,f,c){return r||(r=i),l+=n.slice(a,c).replace(K,s),e&&(u=true,l+="'+__e("+e+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t}),l+="';",(e=e.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(I,""):l).replace(R,"$1").replace(N,"$1;"),l="function("+(e||"obj")+"){"+(e?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var p=Le(r,"return "+l).apply(m,i) -}catch(h){throw h.source=l,h}return t?p(t):(p.source=l,p)},c.trim=Ie,c.trimLeft=function(n,t){return(n=null==n?"":Pe(n))?null==t?n.slice(h(n)):(t=Pe(t),n.slice(o(n,t))):n},c.trimRight=function(n,t){return(n=null==n?"":Pe(n))?null==t?n.slice(0,g(n)+1):(t=Pe(t),n.slice(0,i(n,t)+1)):n},c.truncate=function(n,t){var e=30,r="...";if(t&&_e(t))var u="separator"in t?t.separator:u,e="length"in t?+t.length||0:e,r="omission"in t?Pe(t.omission):r;else null!=t&&(e=+t||0);if(n=null==n?"":Pe(n),e>=n.length)return n; -var o=e-r.length;if(1>o)return r;if(e=n.slice(0,o),null==u)return e+r;if(je(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Ze(u.source,(D.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;e=e.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=e.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(S,v))},c.uniqueId=function(n){var t=++A;return Pe(null==n?"":n)+t},c.all=Qt,c.any=ce,c.detect=te,c.foldl=ae,c.foldr=fe,c.include=Ht,c.inject=ae,Te(c,function(){var n={}; -return xt(c,function(t,e){c.prototype[e]||(n[e]=t)}),n}(),false),c.first=qt,c.last=Pt,c.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Oe(n)),null==t||e?(t=n?n.length:0,0t?0:+t||0,n.length),n)},c.take=qt,c.takeRight=Pt,c.takeRightWhile=Pt,c.takeWhile=qt,c.head=qt,xt(c,function(n,t){var e="sample"!==t;c.prototype[t]||(c.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new q(o,u):o -})}),c.VERSION=x,c.prototype.chain=function(){return this.__chain__=true,this},c.prototype.toJSON=Gt,c.prototype.toString=function(){return Pe(this.__wrapped__)},c.prototype.value=Gt,c.prototype.valueOf=Gt,M(["join","pop","shift"],function(n){var t=Me[n];c.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new q(e,n):e}}),M(["push","reverse","sort","unshift"],function(n){var t=Me[n];c.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),M(["concat","splice"],function(n){var t=Me[n]; -c.prototype[n]=function(){return new q(t.apply(this.__wrapped__,arguments),this.__chain__)}}),c}var m,d=1,b=2,_=4,w=8,j=16,k=32,x="2.4.1",C="__lodash@"+x+"__",O="Expected a function",A=0,E=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,N=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39);/g,T=/[&<>"']/g,W=/<%-([\s\S]+?)%>/g,F=/<%([\s\S]+?)%>/g,$=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,D=/\w*$/,L=/^\s*function[ \n\r\t]+\w/,B=/^0[xX]/,q=/[\xC0-\xFF]/g,U=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,M=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,V=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",J="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),X="[object Arguments]",Y="[object Array]",G="[object Boolean]",H="[object Date]",Q="[object Error]",nt="[object Function]",tt="[object Number]",et="[object Object]",rt="[object RegExp]",ut="[object String]",ot={}; -ot[nt]=false,ot[X]=ot[Y]=ot[G]=ot[H]=ot[tt]=ot[et]=ot[rt]=ot[ut]=true;var it={leading:false,maxWait:0,trailing:false},at={configurable:false,enumerable:false,value:null,writable:false},ft={"&":"&","<":"<",">":">",'"':""","'":"'"},lt={"&":"&","<":"<",">":">",""":'"',"'":"'"},ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},pt={"function":true,object:true},st={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ht=pt[typeof window]&&window||this,gt=pt[typeof exports]&&exports&&!exports.nodeType&&exports,pt=pt[typeof module]&&module&&!module.nodeType&&module,vt=gt&&pt&&typeof global=="object"&&global; -!vt||vt.global!==vt&&vt.window!==vt&&vt.self!==vt||(ht=vt);var vt=pt&&pt.exports===gt&>,yt=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ht._=yt, define(function(){return yt})):gt&&pt?vt?(pt.exports=yt)._=yt:gt._=yt:ht._=yt}).call(this); \ No newline at end of file +;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Dr(e);++ri(t,f)&&l.push(f);return l}function bt(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number"&&-1a(p,h)&&((r||l)&&p.push(h),c.push(s))}return c}function St(n,t){for(var r=-1,e=t(n),u=e.length,o=Dr(u);++ro?0:o)}function Pt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?we(u+r,0):r||0;else if(r)return r=Xt(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function Kt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++ +}else o=null==t||r?1:t;return o=e-(o||0),Jt(n,0,0>o?0:o)}function Mt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:d;return o=e-(o||0),Jt(n,0>o?0:o)}function Vt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return Jt(n,o)}function Jt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=we(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=we(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Dr(u);++e>>1,r(n[e])r?0:r);++tr?we(e+r,0):r||0:0,typeof n=="string"||!We(n)&&Cr(n)?ru&&(u=a)}else t=null==t&&Cr(n)?o:U.createCallback(t,r,3),bt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function fr(n,t){return ir(n,zr(t))}function lr(n,t,r,e){var u=3>arguments.length;t=U.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return t=U.createCallback(t,e,4),_t(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) +}),r}function pr(n){var t=-1,r=n&&n.length,e=Dr(0>r?0:r>>>0);return bt(n,function(n){var r=Rt(0,++t);e[t]=e[r],e[r]=n}),e}function sr(n,t,r){var e;t=U.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return $t(n,b,null,t);if(n)var r=n[A]?n[A][2]:n.length,e=Jt(arguments,2),r=r-e.length;return $t(n,b|k,r,t,e)}function gr(n,t,r){var e,u,o,i,a,f,l,c=0,p=false,s=true; +if(!wr(n))throw new Vr(O);if(t=0>t?0:t,true===r)var h=true,s=false;else jr(r)&&(h=r.leading,p="maxWait"in r&&we(t,+r.maxWait||0),s="trailing"in r?r.trailing:s);var g=function(){var r=t-(Be()-i);0>=r||r>t?(u&&ee(u),r=l,u=f=l=d,r&&(c=Be(),o=n.apply(a,e),f||u||(e=a=null))):f=pe(g,r)},v=function(){f&&ee(f),u=f=l=d,(s||p!==t)&&(c=Be(),o=n.apply(a,e),f||u||(e=a=null))};return function(){if(e=arguments,i=Be(),a=this,l=s&&(f||!h),false===p)var r=h&&!f;else{u||h||(c=i);var y=p-(i-c),m=0>=y||y>p;m?(u&&(u=ee(u)),c=i,o=n.apply(a,e)):u||(u=pe(v,y)) +}return m&&f?f=ee(f):f||t===p||(f=pe(g,t)),r&&(m=true,o=n.apply(a,e)),!m||f||u||(e=a=null),o}}function vr(n){if(!wr(n))throw new Vr(O);return function(){return!n.apply(this,arguments)}}function yr(n,t,r){var e=arguments;if(!n||2>e.length)return n;var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=Dr(r),a=0t||null==n||!de(t))return r;n=Mr(n);do t%2&&(r+=n),t=ue(t/2),n+=n;while(t);return r}function Nr(n,t){return(n=null==n?"":Mr(n))?null==t?n.slice(g(n),v(n)+1):(t=Mr(t),n.slice(i(n,t),a(n,t)+1)):n +}function Sr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||vt(n,t,r):"object"==e?Wr(n):zr(n)}function Tr(n){return n}function Wr(n){var t=$e(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||jr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=ae.call(e,o)&&Et(e[o],n[o],null,true)););return o}:function(n){return n&&ae.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function Fr(n,t,r){var e=true,u=t&&dr(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=dr(t)),false===r?e=false:jr(r)&&"chain"in r&&(e=r.chain),r=-1; +for(var o=wr(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0 +}},U.assign=yr,U.at=function(n){return t(n,jt(arguments,true,false,1))},U.bind=hr,U.bindAll=function(n){for(var t=1arguments.length?$t(t,b|_,null,n):$t(t,b|_|k,null,n,Jt(arguments,2))},U.chain=function(n){return new V(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(s?u(s,f):i(p,f))){for(t=r;--t;){var h=o[t]; +if(0>(h?u(h,f):i(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},U.invert=function(n,t){for(var r=-1,e=$e(n),u=e.length,o={};++ro?0:o>>>0);return bt(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):d}),i},U.keys=$e,U.keysIn=Ar,U.map=ir,U.mapValues=function(n,t,r){var e={};return t=U.createCallback(t,r,3),At(n,function(n,r,u){e[r]=t(n,r,u) +}),e},U.matches=Wr,U.max=ar,U.memoize=function(n,t){if(!wr(n)||t&&!wr(t))throw new Vr(O);var r=function(){var e=r.cache,u=t?t.apply(this,arguments):"_"+arguments[0];return ae.call(e,u)?e[u]:e[u]=n.apply(this,arguments)};return r.cache={},r},U.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0);for(o||(t=U.createCallback(t,r,3)),bt(n,function(n,r,u){if(o)for(r=t.length,u=Dr(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?l:f);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!wr(n))throw new Vr(O);return false===r?e=false:jr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),at.leading=e,at.maxWait=+t,at.trailing=u,gr(n,t,at) +},U.times=function(n,t,r){n=0>n?0:n>>>0,t=vt(t,r,1),r=-1;for(var e=Dr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Mr(n).replace(W,s)},U.escapeRegExp=Ir,U.every=tr,U.find=er,U.findIndex=Ut,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,At,true) +},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,_t)},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,Ot,true)},U.findWhere=function(n,t){return er(n,Wr(t))},U.has=function(n,t){return n?ae.call(n,t):false},U.identity=Tr,U.indexOf=Pt,U.isArguments=br,U.isArray=We,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ne.call(n)==H||false +},U.isDate=function(n){return n&&typeof n=="object"&&ne.call(n)==Q||false},U.isElement=_r,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?we(e+r,0):je(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return p._=Hr,this},U.noop=$r,U.now=Be,U.pad=function(n,t,r){n=null==n?"":Mr(n),t=+t; +var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=mr({},r,e),n=Mr(null==n?"":n);var u,o,i=mr({},r.imports,e.imports),e=$e(i),i=Er(i),a=0,f=r.interpolate||Z,l="__p+='",f=Kr((r.escape||Z).source+"|"+f.source+"|"+(f===z?D:Z).source+"|"+(r.evaluate||Z).source+"|$","g"); +n.replace(f,function(t,r,e,i,f,c){return e||(e=i),l+=n.slice(a,c).replace(M,h),r&&(u=true,l+="'+__e("+r+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),l+="';",(r=r.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(R,""):l).replace(N,"$1").replace(S,"$1;"),l="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=qr(e,"return "+l).apply(d,i) +}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},U.trim=Nr,U.trimLeft=function(n,t){return(n=null==n?"":Mr(n))?null==t?n.slice(g(n)):(t=Mr(t),n.slice(i(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Mr(n))?null==t?n.slice(0,v(n)+1):(t=Mr(t),n.slice(0,a(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&jr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Mr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Mr(n),r>=n.length)return n; +var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(xr(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Kr(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(T,y))},U.uniqueId=function(n){var t=++E;return Mr(null==n?"":n)+t},U.all=tr,U.any=sr,U.detect=er,U.foldl=lr,U.foldr=cr,U.include=nr,U.inject=lr,Fr(U,function(){var n={}; +return At(U,function(t,r){U.prototype[r]||(n[r]=t)}),n}(),false),U.first=Zt,U.last=Mt,U.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Er(n)),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Zt,U.takeRight=Mt,U.takeRightWhile=Mt,U.takeWhile=Zt,U.head=Zt,At(U,function(n,t){var r="sample"!==t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o +})}),U.VERSION=C,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=Qt,U.prototype.toString=function(){return Mr(this.__wrapped__)},U.prototype.value=Qt,U.prototype.valueOf=Qt,lt(["join","pop","shift"],function(n){var t=Jr[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=Jr[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this} +}),lt(["concat","splice"],function(n){var t=Jr[n];U.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__)}}),U}var d,b=1,_=2,w=4,j=8,k=16,x=32,C="2.4.1",A="__lodash@"+C+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,R=/\b__p\+='';/g,N=/\b(__p\+=)''\+/g,S=/(__e\(.*?\)|\b__t\))\+'';/g,T=/&(?:amp|lt|gt|quot|#39);/g,W=/[&<>"']/g,F=/<%-([\s\S]+?)%>/g,$=/<%([\s\S]+?)%>/g,z=/<%=([\s\S]+?)%>/g,D=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,U=/[\xC0-\xFF]/g,Z=/($^)/,P=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,M=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Function]",rt="[object Number]",et="[object Object]",ut="[object RegExp]",ot="[object String]",it={}; +it[tt]=false,it[Y]=it[G]=it[H]=it[Q]=it[rt]=it[et]=it[ut]=it[ot]=true;var at={leading:false,maxWait:0,trailing:false},ft={configurable:false,enumerable:false,value:null,writable:false},lt={"&":"&","<":"<",">":">",'"':""","'":"'"},ct={"&":"&","<":"<",">":">",""":'"',"'":"'"},pt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},st={"function":true,object:true},ht={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},gt=st[typeof window]&&window||this,vt=st[typeof exports]&&exports&&!exports.nodeType&&exports,st=st[typeof module]&&module&&!module.nodeType&&module,yt=vt&&st&&typeof global=="object"&&global; +!yt||yt.global!==yt&&yt.window!==yt&&yt.self!==yt||(gt=yt);var yt=st&&st.exports===vt&&vt,mt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(gt._=mt, define(function(){return mt})):vt&&st?yt?(st.exports=mt)._=mt:vt._=mt:gt._=mt}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 8ad0e1bca0..aaf23e3082 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -284,8 +284,8 @@ * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, - * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, - * `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, + * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `partialRight`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, @@ -3209,8 +3209,8 @@ * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. + * @param {...string} [methodNames] The object method names to bind, specified + * as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * @@ -3703,7 +3703,7 @@ * @alias extend * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. @@ -3804,7 +3804,7 @@ * @memberOf _ * @category Objects * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. + * @param {...Object} [sources] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example @@ -4411,7 +4411,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4433,7 +4433,7 @@ while (length--) { omitProps[length] = String(omitProps[length]); } - return pick(object, baseDifference(keysIn(object), omitProps)); + return pick(object, baseDifference(keysIn(object), omitProps)); } /** @@ -4475,7 +4475,7 @@ * @memberOf _ * @category Objects * @param {Object} object The source object. - * @param {Function|...string|string[]} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function called per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. From 8d145d7a32150da8ed3ec8d1a15f9603e165219d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 12:28:49 -0700 Subject: [PATCH 0622/1608] Make `threshold` account for job batch sizes smaller than the `throttled` amount. --- test/saucelabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index a884d0df8a..6ee85f640f 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -647,7 +647,7 @@ function Tunnel(properties) { restarted.push(this); } // restart tunnel if all active jobs have restarted - var threshold = _.isFinite(throttled) ? throttled : 3; + var threshold = Math.min(all.length, _.isFinite(throttled) ? throttled : 3); if (active.length >= threshold && _.isEmpty(_.difference(active, restarted))) { tunnel.restart(); } From a23ccd863d5b2e48040bfa6c794b26ddbaff1e28 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 13:10:50 -0700 Subject: [PATCH 0623/1608] Message format nit for logging retries. [ci skip] --- test/saucelabs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 6ee85f640f..772c304877 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -508,7 +508,7 @@ Job.prototype.restart = function(callback) { label = options.name + ':'; logInline(); - console.log(label + ' ' + description + ' restart #%d of %d', ++this.attempts, this.retries); + console.log(label + ' ' + description + ' restart %d of %d', ++this.attempts, this.retries); _.defer(_.bind(this.emit, this, 'restart')); this.stop(_.partial(this.start, callback)); @@ -674,7 +674,7 @@ util.inherits(Tunnel, EventEmitter); */ Tunnel.prototype.restart = function(callback) { logInline(); - console.log('Tunnel ' + this.id + ': restart #%d of %d', ++this.attempts, this.retries); + console.log('Tunnel ' + this.id + ': restart %d of %d', ++this.attempts, this.retries); _.defer(_.bind(this.emit, this, 'restart')); this.stop(_.partial(this.start, callback)); From 907ed641bf2a41e2993e4ec06baf18e3e14d3d63 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 13:49:54 -0700 Subject: [PATCH 0624/1608] Use the `chrome` sauce browser identifier in place of `googlechrome`. --- test/saucelabs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 772c304877..6aa281b9b2 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -99,8 +99,8 @@ var platforms = [ ['Windows 8.1', 'firefox', '27'], ['Windows 8.1', 'firefox', '20'], ['Windows 8.1', 'firefox', '3.0'], - ['Windows 8.1', 'googlechrome', '34'], - ['Windows 8.1', 'googlechrome', '33'], + ['Windows 8.1', 'chrome', '34'], + ['Windows 8.1', 'chrome', '33'], ['Windows 8.1', 'internet explorer', '11'], ['Windows 8', 'internet explorer', '10'], ['Windows 7', 'internet explorer', '9'], From 1874ad2ff29a1a97b9cb7252227152831a069771 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 15:39:50 -0700 Subject: [PATCH 0625/1608] Correct typo in `Job#reset`. --- test/saucelabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 6aa281b9b2..9b16062a3c 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -488,7 +488,7 @@ Job.prototype.reset = function(callback) { this.failed = false; this.id = this.result = this.url = null; - this.once('start', _.callback(callback, this)); + this.once('reset', _.callback(callback, this)); _.defer(_.bind(this.emit, this, 'reset')); return this; From 56ee4c1ae54788e9540b382463bfcc5418e19d53 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 15:55:52 -0700 Subject: [PATCH 0626/1608] Remove unnecessary `this` binding and emit register `restart` callbacks so they execute sooner. --- test/saucelabs.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 9b16062a3c..fd50c0cf0c 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -488,7 +488,7 @@ Job.prototype.reset = function(callback) { this.failed = false; this.id = this.result = this.url = null; - this.once('reset', _.callback(callback, this)); + this.once('reset', _.callback(callback)); _.defer(_.bind(this.emit, this, 'reset')); return this; @@ -510,10 +510,10 @@ Job.prototype.restart = function(callback) { logInline(); console.log(label + ' ' + description + ' restart %d of %d', ++this.attempts, this.retries); + this.once('restart', _.callback(callback)); _.defer(_.bind(this.emit, this, 'restart')); - this.stop(_.partial(this.start, callback)); - return this; + return this.stop(this.start); }; /** @@ -526,7 +526,7 @@ Job.prototype.restart = function(callback) { Job.prototype.start = function(callback) { var tunnel = this.tunnel; - this.once('start', _.callback(callback, this)); + this.once('start', _.callback(callback)); if (this.starting || this.running || tunnel.starting || tunnel.stopping) { return this; } @@ -549,7 +549,7 @@ Job.prototype.start = function(callback) { Job.prototype.status = function(callback) { var tunnel = this.tunnel; - this.once('status', _.callback(callback, this)); + this.once('status', _.callback(callback)); if (this.checking || this.starting || this.stopping || tunnel.starting || tunnel.stopping) { return this; } @@ -570,7 +570,7 @@ Job.prototype.status = function(callback) { * @param {Object} Returns the job instance. */ Job.prototype.stop = function(callback) { - this.once('stop', _.callback(callback, this)); + this.once('stop', _.callback(callback)); if (this.stopping || this.tunnel.starting) { return this; } @@ -676,10 +676,10 @@ Tunnel.prototype.restart = function(callback) { logInline(); console.log('Tunnel ' + this.id + ': restart %d of %d', ++this.attempts, this.retries); + this.once('restart', _.callback(callback)); _.defer(_.bind(this.emit, this, 'restart')); - this.stop(_.partial(this.start, callback)); - return this; + return this.stop(this.start); }; /** @@ -690,7 +690,7 @@ Tunnel.prototype.restart = function(callback) { * @param {Object} Returns the tunnel instance. */ Tunnel.prototype.start = function(callback) { - this.once('start', _.callback(callback, this)); + this.once('start', _.callback(callback)); if (!(this.starting || this.running)) { console.log('Opening Sauce Connect tunnel...'); this.starting = true; @@ -725,7 +725,7 @@ Tunnel.prototype.dequeue = function() { * @param {Object} Returns the tunnel instance. */ Tunnel.prototype.stop = function(callback) { - this.once('stop', _.callback(callback, this)); + this.once('stop', _.callback(callback)); if (this.stopping) { return this; } From 4cde537a7f4a1ec8d112a683d734b754287f61ff Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 16:13:07 -0700 Subject: [PATCH 0627/1608] Cleanup initialization of `Job` and `Tunnel` instances. --- test/saucelabs.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index fd50c0cf0c..c197cab831 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -464,11 +464,8 @@ function Job(properties) { _.defaults(this.options, _.cloneDeep(jobOptions)); this.attempts = 0; - this.checking = false; - this.failed = false; - this.running = false; - this.starting = false; - this.stopping = false; + this.checking = this.failed = this.running = this.starting = this.stopping = false; + this.id = this.result = this.url = null; } util.inherits(Job, EventEmitter); @@ -606,11 +603,6 @@ function Tunnel(properties) { this.retries = maxTunnelRetries; _.merge(this, properties); - this.attempts = 0; - this.running = false; - this.starting = false; - this.stopping = false; - var active = [], queue = []; @@ -660,6 +652,8 @@ function Tunnel(properties) { _.invoke(all, 'reset'); }); + this.attempts = 0; + this.running = this.starting = this.stopping = false; this.jobs = { 'active': active, 'all': all, 'queue': queue }; this.connection = new SauceTunnel(this.user, this.pass, this.id, this.tunneled, this.timeout); } From 5fd641e8c7465b40009a55b5574ce787cd6b382a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 4 May 2014 19:24:43 -0700 Subject: [PATCH 0628/1608] Add `_.pullAt` to features section of readme. [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fe2b14d2ba..c49907370f 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ A list of upcoming features is available on our [roadmap](https://github.com/lod * [_.negate](http://lodash.com/docs#negate) to create negated predicate functions * [_.noop](http://lodash.com/docs#noop) for function placeholders * [_.parseInt](http://lodash.com/docs#parseInt) for consistent behavior - * [_.pull](http://lodash.com/docs#pull) & [_.remove](http://lodash.com/docs#remove) for mutating arrays + * [_.pull](http://lodash.com/docs#pull), [_.pullAt](http://lodash.com/docs#pullAt), & [_.remove](http://lodash.com/docs#remove) for mutating arrays * [_.random](http://lodash.com/docs#random) supports returning floating-point numbers * [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking * [_.slice](http://lodash.com/docs#slice) for creating subsets of array-like values From f4a22f8aef6e9d917e3ff245038d668a965dc479 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 05:13:45 -0700 Subject: [PATCH 0629/1608] Add `Job#remove` to remove old jobs when restarting. --- test/saucelabs.js | 69 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index c197cab831..e438d4702c 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -293,6 +293,17 @@ function optionToValue(name, string) { /*----------------------------------------------------------------------------*/ +/** + * The `request.del` callback used by `Jobs#remove`. + * + * @private + */ +function onJobRemove() { + this.id = this.url = null; + this.removing = false; + this.emit('remove'); +} + /** * The `request.post` callback used by `Jobs#start`. * @@ -307,7 +318,7 @@ function onJobStart(error, res, body) { tunnel = this.tunnel; this.starting = false; - if (this.stopping || tunnel.starting) { + if (this.stopping) { return; } if (error || !id || statusCode != 200) { @@ -401,9 +412,7 @@ function onJobStatus(error, res, body) { */ function onJobStop() { this.running = this.stopping = false; - if (!this.tunnel.starting) { - this.emit('stop'); - } + this.emit('stop'); } /** @@ -464,12 +473,41 @@ function Job(properties) { _.defaults(this.options, _.cloneDeep(jobOptions)); this.attempts = 0; - this.checking = this.failed = this.running = this.starting = this.stopping = false; + this.checking = this.failed = this.removing = this.running = this.starting = this.stopping = false; this.id = this.result = this.url = null; } util.inherits(Job, EventEmitter); +/** + * Removes the job. + * + * @memberOf Job + * @param {Function} callback The function called once the job is removed. + * @param {Object} Returns the job instance. + */ +Job.prototype.remove = function(callback) { + if (this.running) { + return this.stop(_.partial(this.remove, callback)); + } + this.once('remove', _.callback(callback)); + if (this.removing) { + return this; + } + var onRemove = _.bind(onJobRemove, this); + + this.removing = true; + if (this.id == null) { + _.defer(onRemove); + return this; + } + request.del(_.template('https://saucelabs.com/rest/v1/${user}/jobs/${id}', this), { + 'auth': { 'user': this.user, 'pass': this.pass } + }, onRemove); + + return this; +}; + /** * Resets the job. * @@ -478,8 +516,8 @@ util.inherits(Job, EventEmitter); * @param {Object} Returns the job instance. */ Job.prototype.reset = function(callback) { - if (this.running) { - return this.stop(_.partial(this.reset, callback)); + if (this.id != null) { + return this.remove(_.partial(this.reset, callback)); } this.attempts = 0; this.failed = false; @@ -510,7 +548,7 @@ Job.prototype.restart = function(callback) { this.once('restart', _.callback(callback)); _.defer(_.bind(this.emit, this, 'restart')); - return this.stop(this.start); + return this.remove(this.start); }; /** @@ -521,10 +559,8 @@ Job.prototype.restart = function(callback) { * @param {Object} Returns the job instance. */ Job.prototype.start = function(callback) { - var tunnel = this.tunnel; - this.once('start', _.callback(callback)); - if (this.starting || this.running || tunnel.starting || tunnel.stopping) { + if (this.starting || this.running) { return this; } this.starting = true; @@ -544,10 +580,8 @@ Job.prototype.start = function(callback) { * @param {Object} Returns the job instance. */ Job.prototype.status = function(callback) { - var tunnel = this.tunnel; - this.once('status', _.callback(callback)); - if (this.checking || this.starting || this.stopping || tunnel.starting || tunnel.stopping) { + if (this.checking || this.removing || this.starting || this.stopping) { return this; } this.checking = true; @@ -568,16 +602,15 @@ Job.prototype.status = function(callback) { */ Job.prototype.stop = function(callback) { this.once('stop', _.callback(callback)); - if (this.stopping || this.tunnel.starting) { + if (this.stopping) { return this; } - var onStop = _.bind(onJobStop, this); - this.stopping = true; if (this.statusId) { this.checking = false; this.statusId = clearTimeout(this.statusId); } + var onStop = _.bind(onJobStop, this); if (this.id == null || !this.running) { _.defer(onStop); return this; @@ -645,7 +678,7 @@ function Tunnel(properties) { } }); - this.on('stop', function() { + this.on('restart', function() { completed = 0; success = true; restarted.length = 0; From 8cfebee922c00bf0e40c6d4ed697a25627e98755 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 05:21:11 -0700 Subject: [PATCH 0630/1608] Remove `id` check from `Job#stop`. --- test/saucelabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index e438d4702c..0a5a76e5b5 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -611,7 +611,7 @@ Job.prototype.stop = function(callback) { this.statusId = clearTimeout(this.statusId); } var onStop = _.bind(onJobStop, this); - if (this.id == null || !this.running) { + if (!this.running) { _.defer(onStop); return this; } From 5eb7faec290413fcad30b3ab52f0efd71598986d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 05:39:41 -0700 Subject: [PATCH 0631/1608] Specify Node 0.11.11 to avoid 0.11.13 which isn't compatible with istanbul. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 395c324770..7707903b79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,7 @@ before_install: - "mkdir ./node_modules/lodash-cli/node_modules && cd ./node_modules/lodash-cli/node_modules/ && ln -s ../../../ ./lodash && cd ../ && npm i . && cd ../../" - "node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./dist/lodash.$BUILD.js" script: - - "[ $ISTANBUL == false ] || (nvm use 0.11 && $BIN --harmony ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./dist/lodash.$BUILD.js)" + - "[ $ISTANBUL == false ] || (nvm install 0.11.11 && $BIN --harmony ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./dist/lodash.$BUILD.js)" - "[ $ISTANBUL == true ] && [ $TRAVIS_PULL_REQUEST == false ] && nvm use 0.10 && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage || true" - "([ $SAUCE_LABS == true ] || [ $ISTANBUL == true ]) || cd ./test" - "([ $SAUCE_LABS == true ] || [ $ISTANBUL == true ]) || $BIN $OPTION ./test.js ../dist/lodash.$BUILD.js" From e332a916b08ccfca70184ac1804f6e3bb49b06a6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 07:36:54 -0700 Subject: [PATCH 0632/1608] Add debug. --- test/saucelabs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 0a5a76e5b5..2fbe0d9072 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -298,7 +298,8 @@ function optionToValue(name, string) { * * @private */ -function onJobRemove() { +function onJobRemove(error, res, body) { + console.log('removed job id ' + this.id + ': ' + this.url); this.id = this.url = null; this.removing = false; this.emit('remove'); From 2514987d3e65637ebab824eaf43fde5bc474d898 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 08:44:35 -0700 Subject: [PATCH 0633/1608] Comment nit. [ci skip] --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 2a486a64fe..99fafde740 100644 --- a/lodash.js +++ b/lodash.js @@ -8522,7 +8522,7 @@ lodash.takeRightWhile = takeRightWhile; lodash.takeWhile = takeWhile; - // add aliases + // add alias lodash.head = first; baseForOwn(lodash, function(func, methodName) { From ff673f053bad196ddc6f87bf53f760f0bbbe032c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 09:20:44 -0700 Subject: [PATCH 0634/1608] Use `String` instead of `+''` for consistent style. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 99fafde740..a177b548f7 100644 --- a/lodash.js +++ b/lodash.js @@ -8164,7 +8164,7 @@ } if (floating || min % 1 || max % 1) { var rand = nativeRandom(); - return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max); + return nativeMin(min + (rand * (max - min + parseFloat('1e-' + (String(rand).length - 1)))), max); } return baseRandom(min, max); } From 9c30d69d55d1bc8ffa3dc8cb895a2acfb6b79653 Mon Sep 17 00:00:00 2001 From: Dan Allison Date: Tue, 6 May 2014 10:16:51 -0700 Subject: [PATCH 0635/1608] Fix old `pullAt` example --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index a177b548f7..e171a2a70d 100644 --- a/lodash.js +++ b/lodash.js @@ -2968,7 +2968,7 @@ * @example * * var array = [5, 10, 15, 20]; - * var evens = _.removeAt(array, [1, 3]); + * var evens = _.pullAt(array, [1, 3]); * * console.log(array); * // => [5, 15] From 086e1e1a749c6d7da4a34a33e1c785950f564d5d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 21:49:33 -0700 Subject: [PATCH 0636/1608] Fix resolving job ids. --- test/saucelabs.js | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 2fbe0d9072..ef4a4f6083 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -300,7 +300,7 @@ function optionToValue(name, string) { */ function onJobRemove(error, res, body) { console.log('removed job id ' + this.id + ': ' + this.url); - this.id = this.url = null; + this.id = this.testId = this.url = null; this.removing = false; this.emit('remove'); } @@ -314,7 +314,7 @@ function onJobRemove(error, res, body) { * @param {Object} body The response body JSON object. */ function onJobStart(error, res, body) { - var id = _.result(body, 'js tests', [])[0], + var testId = _.first(_.result(body, 'js tests')), statusCode = _.result(res, 'statusCode'), tunnel = this.tunnel; @@ -322,7 +322,7 @@ function onJobStart(error, res, body) { if (this.stopping) { return; } - if (error || !id || statusCode != 200) { + if (error || !testId || statusCode != 200) { if (this.attempts < this.retries) { this.restart(); return; @@ -336,8 +336,8 @@ function onJobStart(error, res, body) { this.emit('complete'); return; } - this.id = id; this.running = true; + this.testId = testId; this.timestamp = _.now(); this.emit('start'); this.status(); @@ -352,34 +352,34 @@ function onJobStart(error, res, body) { * @param {Object} body The response body JSON object. */ function onJobStatus(error, res, body) { - var data = _.result(body, 'js tests', [{}])[0], + var completed = _.result(body, 'completed'), + data = _.result(body, 'js tests', [{}])[0], + jobResult = data.result, jobStatus = data.status, + jobUrl = data.url, options = this.options, platform = options.platforms[0], - result = data.result, - completed = _.result(body, 'completed'), description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]), elapsed = (_.now() - this.timestamp) / 1000, expired = (jobStatus != 'test session in progress' && elapsed >= queueTimeout), - failures = _.result(result, 'failed'), + failures = _.result(jobResult, 'failed'), label = options.name + ':', - tunnel = this.tunnel, - url = data.url; + tunnel = this.tunnel; this.checking = false; + this.id = _.last(url.parse(jobUrl).pathname.split('/')); + this.url = jobUrl; + if (!this.running || this.stopping) { return; } this.emit('status', jobStatus); - if (!completed && !expired) { - this.statusId = setTimeout(_.bind(this.status, this), this.statusInterval); + this._timerId = setTimeout(_.bind(this.status, this), this.statusInterval); return; } - this.result = result; - this.url = url; - - if (!result || failures || reError.test(result.message)) { + this.result = jobResult; + if (!jobResult || failures || reError.test(jobResult.message)) { if (this.attempts < this.retries) { this.restart(); return; @@ -396,7 +396,7 @@ function onJobStatus(error, res, body) { return; } else { - var message = _.result(result, 'message', 'no results available. ' + details); + var message = _.result(jobResult, 'message', 'no results available. ' + details); console.error(label, description, chalk.red('failed') + ';', message); } } else { @@ -475,7 +475,7 @@ function Job(properties) { this.attempts = 0; this.checking = this.failed = this.removing = this.running = this.starting = this.stopping = false; - this.id = this.result = this.url = null; + this._timerId = this.id = this.result = this.testId = this.url = null; } util.inherits(Job, EventEmitter); @@ -522,7 +522,7 @@ Job.prototype.reset = function(callback) { } this.attempts = 0; this.failed = false; - this.id = this.result = this.url = null; + this._timerId = this.id = this.result = this.testId = this.url = null; this.once('reset', _.callback(callback)); _.defer(_.bind(this.emit, this, 'reset')); @@ -588,7 +588,7 @@ Job.prototype.status = function(callback) { this.checking = true; request.post(_.template('https://saucelabs.com/rest/v1/${user}/js-tests/status', this), { 'auth': { 'user': this.user, 'pass': this.pass }, - 'json': { 'js tests': [this.id] } + 'json': { 'js tests': [this.testId] } }, _.bind(onJobStatus, this)); return this; @@ -607,9 +607,10 @@ Job.prototype.stop = function(callback) { return this; } this.stopping = true; - if (this.statusId) { + if (this._timerId) { + clearTimeout(this._timerId); + this._timerId = null; this.checking = false; - this.statusId = clearTimeout(this.statusId); } var onStop = _.bind(onJobStop, this); if (!this.running) { From f09ae1e2e3149d452e7ea2d84f61cb5ca1bd5cca Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 6 May 2014 22:09:25 -0700 Subject: [PATCH 0637/1608] Fix url parsing. --- test/saucelabs.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index ef4a4f6083..8b49704fa2 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -299,7 +299,6 @@ function optionToValue(name, string) { * @private */ function onJobRemove(error, res, body) { - console.log('removed job id ' + this.id + ': ' + this.url); this.id = this.testId = this.url = null; this.removing = false; this.emit('remove'); @@ -314,8 +313,8 @@ function onJobRemove(error, res, body) { * @param {Object} body The response body JSON object. */ function onJobStart(error, res, body) { - var testId = _.first(_.result(body, 'js tests')), - statusCode = _.result(res, 'statusCode'), + var statusCode = _.result(res, 'statusCode'), + testId = _.first(_.result(body, 'js tests')), tunnel = this.tunnel; this.starting = false; @@ -353,10 +352,10 @@ function onJobStart(error, res, body) { */ function onJobStatus(error, res, body) { var completed = _.result(body, 'completed'), - data = _.result(body, 'js tests', [{}])[0], - jobResult = data.result, - jobStatus = data.status, - jobUrl = data.url, + data = _.first(_.result(body, 'js tests')), + jobResult = _.result(data, 'result'), + jobStatus = _.result(data, 'status'), + jobUrl = _.result(data, 'url'), options = this.options, platform = options.platforms[0], description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]), @@ -367,13 +366,14 @@ function onJobStatus(error, res, body) { tunnel = this.tunnel; this.checking = false; - this.id = _.last(url.parse(jobUrl).pathname.split('/')); - this.url = jobUrl; - if (!this.running || this.stopping) { return; } this.emit('status', jobStatus); + if (jobUrl) { + this.id = _.last(url.parse(jobUrl).pathname.split('/')); + this.url = jobUrl; + } if (!completed && !expired) { this._timerId = setTimeout(_.bind(this.status, this), this.statusInterval); return; From 32167b45cef7e9b73c9ecd310de0980a0ae962c6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 7 May 2014 00:12:12 -0700 Subject: [PATCH 0638/1608] Ensure `_.pullAt` ignores non-index values. --- lodash.js | 4 ++-- test/test.js | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lodash.js b/lodash.js index e171a2a70d..e9e7dea6c5 100644 --- a/lodash.js +++ b/lodash.js @@ -2983,8 +2983,8 @@ indexes.sort(baseCompareAscending); while (length--) { - var index = indexes[length]; - if (index != previous) { + var index = parseFloat(indexes[length]); + if (index != previous && index > -1 && index % 1 == 0) { var previous = index; splice.call(array, index, 1); } diff --git a/test/test.js b/test/test.js index f60bd7a107..1a6ff086da 100644 --- a/test/test.js +++ b/test/test.js @@ -7278,11 +7278,11 @@ }); test('should work with unsorted indexes', 2, function() { - var array = [1, 2, 3, 4, 5], - actual = _.pullAt(array, [4, 1, 0, 3]); + var array = [1, 2, 3, 4], + actual = _.pullAt(array, [1, 3, 0]); deepEqual(array, [3]); - deepEqual(actual, [5, 2, 1, 4]); + deepEqual(actual, [2, 4, 1]); }); test('should work with repeated indexes', 2, function() { @@ -7316,6 +7316,21 @@ deepEqual(array, ['b']); deepEqual(actual, ['d', 'a', 'c']); }); + + test('should ignore non-index values', 2, function() { + var array = ['a', 'b', 'c'], + clone = array.slice(); + + var values = _.reject(empties, function(value) { + return value === 0 || _.isArray(value); + }).concat(-1, 1.1); + + var expected = _.map(values, _.constant(undefined)), + actual = _.pullAt.apply(_, [array].concat(values)); + + deepEqual(actual, expected); + deepEqual(array, clone); + }); }()); /*--------------------------------------------------------------------------*/ From 43c13c22a8d9faff4284b74a8ba1fdacb4aeee05 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 7 May 2014 00:40:27 -0700 Subject: [PATCH 0639/1608] Make `_.memoize` skip the `__proto__` key. --- lodash.js | 8 +++++--- test/test.js | 36 +++++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/lodash.js b/lodash.js index e9e7dea6c5..572f7cab4f 100644 --- a/lodash.js +++ b/lodash.js @@ -5340,9 +5340,11 @@ throw new TypeError(funcErrorText); } var memoized = function() { - var cache = memoized.cache, - key = resolver ? resolver.apply(this, arguments) : '_' + arguments[0]; - + var key = resolver ? resolver.apply(this, arguments) : arguments[0]; + if (key == '__proto__') { + return func.apply(this, arguments); + } + var cache = memoized.cache; return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); diff --git a/test/test.js b/test/test.js index 1a6ff086da..dd48716db5 100644 --- a/test/test.js +++ b/test/test.js @@ -3443,15 +3443,6 @@ deepEqual(_.uniq(largeArray), expected); deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []); }); - - test('lodash.memoize should support values that resolve to the `__proto__` key', 1, function() { - var count = 0, - memoized = _.memoize(function() { return ++count; }); - - memoized('__proto__'); - memoized('__proto__'); - strictEqual(count, 1); - }); }()); /*--------------------------------------------------------------------------*/ @@ -6098,16 +6089,35 @@ }); test('should expose a `cache` object on the `memoized` function', 4, function() { - _.each(['_a', 'a'], function(key, index) { - var memoized = _.memoize(_.identity, index && _.identity); + _.times(2, function(index) { + var resolver = index && _.identity, + memoized = _.memoize(_.identity, resolver); memoized('a'); - strictEqual(memoized.cache[key], 'a'); + strictEqual(memoized.cache.a, 'a'); - memoized.cache[key] = 'b'; + memoized.cache.a = 'b'; strictEqual(memoized('a'), 'b'); }); }); + + test('should skip the `__proto__` key', 4, function() { + _.times(2, function(index) { + var count = 0, + resolver = index && _.identity; + + var memoized = _.memoize(function() { + count++; + return []; + }, resolver); + + memoized('__proto__'); + memoized('__proto__'); + + strictEqual(count, 2); + ok(!(memoized.cache instanceof Array)); + }); + }); }()); /*--------------------------------------------------------------------------*/ From b583530c66673d9ec49462306e9dc0ca0e0016ea Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 7 May 2014 01:32:21 -0700 Subject: [PATCH 0640/1608] Simplify `memoize` doc example. [ci skip] --- lodash.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lodash.js b/lodash.js index 572f7cab4f..54ca12a695 100644 --- a/lodash.js +++ b/lodash.js @@ -5321,19 +5321,17 @@ * fibonacci(9) * // => 34 * - * var data = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; - * * // modifying the result cache - * var get = _.memoize(function(name) { return data[name]; }, _.identity); - * get('pebbles'); - * // => { 'name': 'pebbles', 'age': 1 } + * var upperCase = _.memoize(function(string) { + * return string.toUpperCase(); + * }); + * + * upperCase('fred'); + * // => 'FRED' * - * get.cache.pebbles.name = 'penelope'; - * get('pebbles'); - * // => { 'name': 'penelope', 'age': 1 } + * upperCase.cache.fred = 'BARNEY' + * upperCase('fred'); + * // => 'BARNEY' */ function memoize(func, resolver) { if (!isFunction(func) || (resolver && !isFunction(resolver))) { From 4155e8e0ceffdcb024ae2d2ce258201e0a4c3042 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 7 May 2014 20:19:42 -0700 Subject: [PATCH 0641/1608] Add a doc note for iterating inherited properties to `_.bindAll` and `_.functions`. [ci skip] --- lodash.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lodash.js b/lodash.js index 54ca12a695..b193655d42 100644 --- a/lodash.js +++ b/lodash.js @@ -4947,8 +4947,8 @@ /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * of method names. If no method names are provided all enumerable function + * properties, own and inherited, of `object` will be bound. * * Note: This method does not set the `length` property of bound functions. * @@ -6000,8 +6000,8 @@ } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * Creates a sorted array of property names of all enumerable function + * properties, own and inherited, of `object`. * * @static * @memberOf _ From 9b920cf813365d0bbc37ffd757ec93832898d3ae Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 8 May 2014 23:42:40 -0700 Subject: [PATCH 0642/1608] Add `baseFunctions` to ensure `_.mixin` only iterates over own keys of `source` objects. --- lodash.js | 44 +++++++++++++++++++++++++++++++------------- test/test.js | 33 ++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/lodash.js b/lodash.js index b193655d42..3c3d9a1ee6 100644 --- a/lodash.js +++ b/lodash.js @@ -1599,6 +1599,30 @@ return baseForRight(object, callback, keys); } + /** + * The base implementation of `_.functions` which creates a sorted array of + * function property names from those returned by `keysFunc`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Array} Returns the new sorted array of property names. + */ + function baseFunctions(object, keysFunc) { + var index = -1, + props = keysFunc(object), + length = props.length, + result = []; + + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result.push(key); + } + } + return result.sort(); + } + /** * The base implementation of `_.isEqual`, without support for `thisArg` * binding, that allows partial "_.where" style comparisons. @@ -6000,7 +6024,7 @@ } /** - * Creates a sorted array of property names of all enumerable function + * Creates a sorted array of function property names from all enumerable * properties, own and inherited, of `object`. * * @static @@ -6015,14 +6039,7 @@ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - var result = []; - - baseForIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); - } - }); - return result.sort(); + return baseFunctions(object, keysIn); } /** @@ -7922,8 +7939,9 @@ } /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. + * Adds all own enumerable function properties of a source object to the + * destination object. If `object` is a function methods will be added to + * its prototype as well. * * @static * @memberOf _ @@ -7955,7 +7973,7 @@ */ function mixin(object, source, options) { var chain = true, - methodNames = source && functions(source); + methodNames = source && baseFunctions(source, keys); if (!source || (!options && !methodNames.length)) { if (options == null) { @@ -7963,7 +7981,7 @@ } source = object; object = this; - methodNames = functions(source); + methodNames = baseFunctions(source, keys); } if (options === false) { chain = false; diff --git a/test/test.js b/test/test.js index dd48716db5..6e2d2de1a3 100644 --- a/test/test.js +++ b/test/test.js @@ -6383,6 +6383,22 @@ var value = ['a'], source = { 'a': function(array) { return array[0]; }, 'b': 'B' }; + test('should mixin `source` methods into lodash', 4, function() { + _.mixin(source); + + strictEqual(_.a(value), 'a'); + strictEqual(_(value).a().__wrapped__, 'a'); + + delete _.a; + delete _.prototype.a; + + ok(!('b' in _)); + ok(!('b' in _.prototype)); + + delete _.b; + delete _.prototype.b; + }); + test('should use `this` as the default `object` value', 3, function() { var object = _.create(_); object.mixin(source); @@ -6425,20 +6441,11 @@ delete wrapper.prototype.b; }); - test('should mixin `source` methods into lodash', 4, function() { - _.mixin(source); - - strictEqual(_.a(value), 'a'); - strictEqual(_(value).a().__wrapped__, 'a'); - - delete _.a; - delete _.prototype.a; - - ok(!('b' in _)); - ok(!('b' in _.prototype)); + test('should not assign inherited `source` properties', 1, function() { + function Foo() {} + Foo.prototype = { 'a': _.noop }; - delete _.b; - delete _.prototype.b; + deepEqual(_.mixin({}, new Foo, {}), {}); }); test('should accept an `options` argument', 16, function() { From f999195f4707862dec527ee3905928c36ade9604 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 9 May 2014 02:12:16 -0700 Subject: [PATCH 0643/1608] Style nit on the IIFE used with `mixin`. --- lodash.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index 3c3d9a1ee6..5d6c156eee 100644 --- a/lodash.js +++ b/lodash.js @@ -8519,7 +8519,7 @@ lodash.include = contains; lodash.inject = reduce; - mixin(lodash, function() { + mixin(lodash, (function() { var source = {} baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { @@ -8527,7 +8527,7 @@ } }); return source; - }(), false); + }()), false); /*--------------------------------------------------------------------------*/ From 5deb7371abc701e79a36c5c7119e7e3a7192adbf Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 9 May 2014 02:32:14 -0700 Subject: [PATCH 0644/1608] Rebuild dist. --- dist/lodash.compat.js | 92 ++++++++++++++---------- dist/lodash.compat.min.js | 127 ++++++++++++++++----------------- dist/lodash.js | 92 ++++++++++++++---------- dist/lodash.min.js | 114 +++++++++++++++--------------- dist/lodash.underscore.js | 129 +++++++++++++++++++--------------- dist/lodash.underscore.min.js | 11 +-- 6 files changed, 311 insertions(+), 254 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index d9d2f478b1..61e4bfe99b 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -1600,6 +1600,30 @@ return baseForRight(object, callback, keys); } + /** + * The base implementation of `_.functions` which creates a sorted array of + * function property names from those returned by `keysFunc`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Array} Returns the new sorted array of property names. + */ + function baseFunctions(object, keysFunc) { + var index = -1, + props = keysFunc(object), + length = props.length, + result = []; + + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result.push(key); + } + } + return result.sort(); + } + /** * The base implementation of `_.isEqual`, without support for `thisArg` * binding, that allows partial "_.where" style comparisons. @@ -2969,7 +2993,7 @@ * @example * * var array = [5, 10, 15, 20]; - * var evens = _.removeAt(array, [1, 3]); + * var evens = _.pullAt(array, [1, 3]); * * console.log(array); * // => [5, 15] @@ -2984,8 +3008,8 @@ indexes.sort(baseCompareAscending); while (length--) { - var index = indexes[length]; - if (index != previous) { + var index = parseFloat(indexes[length]); + if (index != previous && index > -1 && index % 1 == 0) { var previous = index; splice.call(array, index, 1); } @@ -4948,8 +4972,8 @@ /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * of method names. If no method names are provided all enumerable function + * properties, own and inherited, of `object` will be bound. * * Note: This method does not set the `length` property of bound functions. * @@ -5322,28 +5346,28 @@ * fibonacci(9) * // => 34 * - * var data = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; - * * // modifying the result cache - * var get = _.memoize(function(name) { return data[name]; }, _.identity); - * get('pebbles'); - * // => { 'name': 'pebbles', 'age': 1 } + * var upperCase = _.memoize(function(string) { + * return string.toUpperCase(); + * }); * - * get.cache.pebbles.name = 'penelope'; - * get('pebbles'); - * // => { 'name': 'penelope', 'age': 1 } + * upperCase('fred'); + * // => 'FRED' + * + * upperCase.cache.fred = 'BARNEY' + * upperCase('fred'); + * // => 'BARNEY' */ function memoize(func, resolver) { if (!isFunction(func) || (resolver && !isFunction(resolver))) { throw new TypeError(funcErrorText); } var memoized = function() { - var cache = memoized.cache, - key = resolver ? resolver.apply(this, arguments) : '_' + arguments[0]; - + var key = resolver ? resolver.apply(this, arguments) : arguments[0]; + if (key == '__proto__') { + return func.apply(this, arguments); + } + var cache = memoized.cache; return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); @@ -6001,8 +6025,8 @@ } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * Creates a sorted array of function property names from all enumerable + * properties, own and inherited, of `object`. * * @static * @memberOf _ @@ -6016,14 +6040,7 @@ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - var result = []; - - baseForIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); - } - }); - return result.sort(); + return baseFunctions(object, keysIn); } /** @@ -7923,8 +7940,9 @@ } /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. + * Adds all own enumerable function properties of a source object to the + * destination object. If `object` is a function methods will be added to + * its prototype as well. * * @static * @memberOf _ @@ -7956,7 +7974,7 @@ */ function mixin(object, source, options) { var chain = true, - methodNames = source && functions(source); + methodNames = source && baseFunctions(source, keys); if (!source || (!options && !methodNames.length)) { if (options == null) { @@ -7964,7 +7982,7 @@ } source = object; object = this; - methodNames = functions(source); + methodNames = baseFunctions(source, keys); } if (options === false) { chain = false; @@ -8165,7 +8183,7 @@ } if (floating || min % 1 || max % 1) { var rand = nativeRandom(); - return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max); + return nativeMin(min + (rand * (max - min + parseFloat('1e-' + (String(rand).length - 1)))), max); } return baseRandom(min, max); } @@ -8502,7 +8520,7 @@ lodash.include = contains; lodash.inject = reduce; - mixin(lodash, function() { + mixin(lodash, (function() { var source = {} baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { @@ -8510,7 +8528,7 @@ } }); return source; - }(), false); + }()), false); /*--------------------------------------------------------------------------*/ @@ -8523,7 +8541,7 @@ lodash.takeRightWhile = takeRightWhile; lodash.takeWhile = takeWhile; - // add aliases + // add alias lodash.head = first; baseForOwn(lodash, function(func, methodName) { diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 0c06c15857..3ea1cb76f6 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -3,67 +3,68 @@ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Dr(e);++ri(t,l)&&f.push(l);return f}function wt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1a(s,g)&&((r||f)&&s.push(g),c.push(p))}return c}function Lt(n,t){for(var r=-1,e=t(n),u=e.length,o=Dr(u);++ro?0:o)}function Mt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?ke(u+r,0):r||0;else if(r)return r=Gt(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function Vt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),Yt(n,0,0>o?0:o)}function Jt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; -for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:b;return o=e-(o||0),Yt(n,0>o?0:o)}function Xt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return Yt(n,o)}function Yt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=ke(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=ke(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Dr(u);++e>>1,r(n[e])r?0:r);++tr?ke(e+r,0):r||0:0,typeof n=="string"||!ze(n)&&Er(n)?ru&&(u=a)}else t=null==t&&Er(n)?o:U.createCallback(t,r,3),wt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function cr(n,t){return lr(n,zr(t))}function sr(n,t,r,e){var u=3>arguments.length; -if(t=U.createCallback(t,e,4),ze(n)){var o=-1,i=n.length;for(u&&i&&(r=n[++o]);++oarguments.length;return t=U.createCallback(t,e,4),xt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function gr(n){var t=-1,r=n&&n.length,e=Dr(0>r?0:r>>>0);return wt(n,function(n){var r=Nt(0,++t);e[t]=e[r],e[r]=n}),e}function hr(n,t,r){var e;if(t=U.createCallback(t,r,3),ze(n)){r=-1;for(var u=n.length;++rarguments.length)return Pt(n,_,null,t);if(n)var r=n[E]?n[E][2]:n.length,e=Yt(arguments,2),r=r-e.length;return Pt(n,_|j,r,t,e)}function yr(n,t,r){var e,u,o,i,a,l,f,c=0,s=false,p=true;if(!Cr(n))throw new Yr(A);if(t=0>t?0:t,true===r)var g=true,p=false;else jr(r)&&(g=r.leading,s="maxWait"in r&&ke(t,+r.maxWait||0),p="trailing"in r?r.trailing:p);var h=function(){var r=t-(Ke()-i);0>=r||r>t?(u&&ae(u),r=f,u=l=f=b,r&&(c=Ke(),o=n.apply(a,e),l||u||(e=a=null))):l=ve(h,r) -},v=function(){l&&ae(l),u=l=f=b,(p||s!==t)&&(c=Ke(),o=n.apply(a,e),l||u||(e=a=null))};return function(){if(e=arguments,i=Ke(),a=this,f=p&&(l||!g),false===s)var r=g&&!l;else{u||g||(c=i);var y=s-(i-c),m=0>=y||y>s;m?(u&&(u=ae(u)),c=i,o=n.apply(a,e)):u||(u=ve(v,y))}return m&&l?l=ae(l):l||t===s||(l=ve(h,t)),r&&(m=true,o=n.apply(a,e)),!m||l||u||(e=a=null),o}}function mr(n){if(!Cr(n))throw new Yr(A);return function(){return!n.apply(this,arguments)}}function dr(n,t,r){var e=arguments;if(!n||2>e.length)return n; -var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,i=r-1,e=Dr(r),a=0t||null==n||!xe(t))return r;n=Xr(n);do t%2&&(r+=n),t=le(t/2),n+=n;while(t);return r}function Tr(n,t){return(n=null==n?"":Xr(n))?null==t?n.slice(v(n),y(n)+1):(t=Xr(t),n.slice(i(n,t),a(n,t)+1)):n}function Lr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||mt(n,t,r):"object"==e?Fr(n):zr(n)}function Wr(n){return n -}function Fr(n){var t=Be(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||jr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=se.call(e,o)&&It(e[o],n[o],null,true)););return o}:function(n){return n&&se.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function $r(n,t,r){var e=true,u=t&&_r(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=_r(t)),false===r?e=false:jr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=Cr(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},U.assign=dr,U.at=function(n){return Ne.unindexedChars&&Er(n)&&(n=n.split("")),t(n,jt(arguments,true,false,1))},U.bind=vr,U.bindAll=function(n){for(var t=1arguments.length?Pt(t,_|w,null,n):Pt(t,_|w|j,null,n,Yt(arguments,2))},U.chain=function(n){return new J(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?u(p,l):i(s,l))){for(t=r;--t;){var g=o[t];if(0>(g?u(g,l):i(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},U.invert=function(n,t){for(var r=-1,e=Be(n),u=e.length,o={};++ro?0:o>>>0);return wt(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):b}),i},U.keys=Be,U.keysIn=Ar,U.map=lr,U.mapValues=function(n,t,r){var e={};return t=U.createCallback(t,r,3),At(n,function(n,r,u){e[r]=t(n,r,u)}),e},U.matches=Fr,U.max=fr,U.memoize=function(n,t){if(!Cr(n)||t&&!Cr(t))throw new Yr(A);var r=function(){var e=r.cache,u=t?t.apply(this,arguments):"_"+arguments[0]; -return se.call(e,u)?e[u]:e[u]=n.apply(this,arguments)};return r.cache={},r},U.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0); -for(o||(t=U.createCallback(t,r,3)),wt(n,function(n,r,u){if(o)for(r=t.length,u=Dr(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?f:l);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!Cr(n))throw new Yr(A);return false===r?e=false:jr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ft.leading=e,ft.maxWait=+t,ft.trailing=u,yr(n,t,ft)},U.times=function(n,t,r){n=0>n?0:n>>>0,t=mt(t,r,1),r=-1; -for(var e=Dr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Xr(n).replace(W,p)},U.escapeRegExp=Rr,U.every=er,U.find=or,U.findIndex=Zt,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,At,true) -},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,xt)},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,St,true)},U.findWhere=function(n,t){return or(n,Fr(t))},U.has=function(n,t){return n?se.call(n,t):false},U.identity=Wr,U.indexOf=Mt,U.isArguments=wr,U.isArray=ze,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ue.call(n)==nt||false -},U.isDate=function(n){return n&&typeof n=="object"&&ue.call(n)==tt||false},U.isElement=xr,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?ke(e+r,0):Oe(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return s._=re,this},U.noop=Pr,U.now=Ke,U.pad=function(n,t,r){n=null==n?"":Xr(n),t=+t; -var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=br({},r,e),n=Xr(null==n?"":n);var u,o,i=br({},r.imports,e.imports),e=Be(i),i=Ir(i),a=0,l=r.interpolate||Z,f="__p+='",l=Jr((r.escape||Z).source+"|"+l.source+"|"+(l===P?z:Z).source+"|"+(r.evaluate||Z).source+"|$","g"); -n.replace(l,function(t,r,e,i,l,c){return e||(e=i),f+=n.slice(a,c).replace(V,g),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(R,""):f).replace(N,"$1").replace(T,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var c=Zr(e,"return "+f).apply(b,i) -}catch(s){throw s.source=f,s}return t?c(t):(c.source=f,c)},U.trim=Tr,U.trimLeft=function(n,t){return(n=null==n?"":Xr(n))?null==t?n.slice(v(n)):(t=Xr(t),n.slice(i(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Xr(n))?null==t?n.slice(0,y(n)+1):(t=Xr(t),n.slice(0,a(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&jr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Xr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Xr(n),r>=n.length)return n; -var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(Or(u)){if(n.slice(o).search(u)){var i,a,l=n.slice(0,o);for(u.global||(u=Jr(u.source,(D.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(l);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(L,m))},U.uniqueId=function(n){var t=++S;return Xr(null==n?"":n)+t},U.all=er,U.any=hr,U.detect=or,U.foldl=sr,U.foldr=pr,U.include=rr,U.inject=sr,$r(U,function(){var n={}; -return At(U,function(t,r){U.prototype[r]||(n[r]=t)}),n}(),false),U.first=Kt,U.last=Jt,U.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Ir(n):Ne.unindexedChars&&Er(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Kt,U.takeRight=Jt,U.takeRightWhile=Jt,U.takeWhile=Kt,U.head=Kt,At(U,function(n,t){var r="sample"!==t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o -})}),U.VERSION=O,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=tr,U.prototype.toString=function(){return Xr(this.__wrapped__)},U.prototype.value=tr,U.prototype.valueOf=tr,st(["join","pop","shift"],function(n){var t=Gr[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),st(["push","reverse","sort","unshift"],function(n){var t=Gr[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this} -}),st(["concat","splice"],function(n){var t=Gr[n];U.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Ne.spliceObjects||st(["pop","shift","splice"],function(n){var t=Gr[n],r="splice"==n;U.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),U}var b,_=1,w=2,x=4,C=8,j=16,k=32,O="2.4.1",E="__lodash@"+O+"__",A="Expected a function",S=0,I=/^[A-Z]+$/,R=/\b__p\+='';/g,N=/\b(__p\+=)''\+/g,T=/(__e\(.*?\)|\b__t\))\+'';/g,L=/&(?:amp|lt|gt|quot|#39);/g,W=/[&<>"']/g,F=/<%-([\s\S]+?)%>/g,$=/<%([\s\S]+?)%>/g,P=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,D=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,U=/[\xC0-\xFF]/g,Z=/($^)/,K=/[.*+?^${}()|[\]\/\\]/g,M=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",it="[object RegExp]",at="[object String]",lt={}; -lt[et]=false,lt[H]=lt[Q]=lt[nt]=lt[tt]=lt[ut]=lt[ot]=lt[it]=lt[at]=true;var ft={leading:false,maxWait:0,trailing:false},ct={configurable:false,enumerable:false,value:null,writable:false},st={"&":"&","<":"<",">":">",'"':""","'":"'"},pt={"&":"&","<":"<",">":">",""":'"',"'":"'"},gt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},ht={"function":true,object:true},vt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},yt=ht[typeof window]&&window||this,mt=ht[typeof exports]&&exports&&!exports.nodeType&&exports,ht=ht[typeof module]&&module&&!module.nodeType&&module,dt=mt&&ht&&typeof global=="object"&&global; +;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Br(e);++ra(t,l)&&f.push(l);return f}function wt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1i(s,g)&&((r||f)&&s.push(g),c.push(p))}return c}function Lt(n,t){for(var r=-1,e=t(n),u=e.length,o=Br(u);++ro?0:o)}function Vt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?Oe(u+r,0):r||0;else if(r)return r=Ht(n,t),u&&n[r]===t?r:-1;return e(n,t,r) +}function Jt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),Gt(n,0,0>o?0:o)}function Xt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:b;return o=e-(o||0),Gt(n,0>o?0:o)}function Yt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return Gt(n,o)}function Gt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=Oe(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=Oe(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Br(u);++e>>1,r(n[e])r?0:r);++tr?Oe(e+r,0):r||0:0,typeof n=="string"||!De(n)&&Ar(n)?ru&&(u=i)}else t=null==t&&Ar(n)?o:U.createCallback(t,r,3),wt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n) +});return u}function sr(n,t){return fr(n,Dr(t))}function pr(n,t,r,e){var u=3>arguments.length;if(t=U.createCallback(t,e,4),De(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=U.createCallback(t,e,4),xt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function hr(n){var t=-1,r=n&&n.length,e=Br(0>r?0:r>>>0);return wt(n,function(n){var r=Tt(0,++t);e[t]=e[r],e[r]=n}),e}function vr(n,t,r){var e; +if(t=U.createCallback(t,r,3),De(n)){r=-1;for(var u=n.length;++rarguments.length)return zt(n,_,null,t);if(n)var r=n[E]?n[E][2]:n.length,e=Gt(arguments,2),r=r-e.length;return zt(n,_|j,r,t,e)}function mr(n,t,r){var e,u,o,a,i,l,f,c=0,s=false,p=true;if(!jr(n))throw new Gr(A);if(t=0>t?0:t,true===r)var g=true,p=false;else kr(r)&&(g=r.leading,s="maxWait"in r&&Oe(t,+r.maxWait||0),p="trailing"in r?r.trailing:p); +var h=function(){var r=t-(Me()-a);0>=r||r>t?(u&&le(u),r=f,u=l=f=b,r&&(c=Me(),o=n.apply(i,e),l||u||(e=i=null))):l=ye(h,r)},v=function(){l&&le(l),u=l=f=b,(p||s!==t)&&(c=Me(),o=n.apply(i,e),l||u||(e=i=null))};return function(){if(e=arguments,a=Me(),i=this,f=p&&(l||!g),false===s)var r=g&&!l;else{u||g||(c=a);var y=s-(a-c),m=0>=y||y>s;m?(u&&(u=le(u)),c=a,o=n.apply(i,e)):u||(u=ye(v,y))}return m&&l?l=le(l):l||t===s||(l=ye(h,t)),r&&(m=true,o=n.apply(i,e)),!m||l||u||(e=i=null),o}}function dr(n){if(!jr(n))throw new Gr(A); +return function(){return!n.apply(this,arguments)}}function br(n,t,r){var e=arguments;if(!n||2>e.length)return n;var u=0,o=e.length,a=typeof r;if("number"!=a&&"string"!=a||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,a=r-1,e=Br(r),i=0t||null==n||!Ce(t))return r;n=Yr(n);do t%2&&(r+=n),t=fe(t/2),n+=n;while(t); +return r}function Fr(n,t){return(n=null==n?"":Yr(n))?null==t?n.slice(v(n),y(n)+1):(t=Yr(t),n.slice(a(n,t),i(n,t)+1)):n}function Lr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||mt(n,t,r):"object"==e?$r(n):Dr(n)}function Wr(n){return n}function $r(n){var t=qe(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||kr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=pe.call(e,o)&&Rt(e[o],n[o],null,true)););return o}:function(n){return n&&pe.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false +}}function Pr(n,t,r){var e=true,u=t&&It(t,qe);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=It(t,qe)),false===r?e=false:kr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=jr(n),a=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},U.assign=br,U.at=function(n){return Te.unindexedChars&&Ar(n)&&(n=n.split("")),t(n,jt(arguments,true,false,1))},U.bind=yr,U.bindAll=function(n){for(var t=1arguments.length?zt(t,_|w,null,n):zt(t,_|w|j,null,n,Gt(arguments,2))},U.chain=function(n){return new J(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?u(p,l):a(s,l))){for(t=r;--t;){var g=o[t];if(0>(g?u(g,l):a(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},U.invert=function(n,t){for(var r=-1,e=qe(n),u=e.length,o={};++ro?0:o>>>0);return wt(n,function(n){var o=u?t:null!=n&&n[t];a[++e]=o?o.apply(n,r):b}),a},U.keys=qe,U.keysIn=Sr,U.map=fr,U.mapValues=function(n,t,r){var e={};return t=U.createCallback(t,r,3),At(n,function(n,r,u){e[r]=t(n,r,u)}),e},U.matches=$r,U.max=cr,U.memoize=function(n,t){if(!jr(n)||t&&!jr(t))throw new Gr(A);var r=function(){var e=t?t.apply(this,arguments):arguments[0]; +if("__proto__"==e)return n.apply(this,arguments);var u=r.cache;return pe.call(u,e)?u[e]:u[e]=n.apply(this,arguments)};return r.cache={},r},U.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0); +for(o||(t=U.createCallback(t,r,3)),wt(n,function(n,r,u){if(o)for(r=t.length,u=Br(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?f:l);u--;)a[u]=a[u].c;return a},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!jr(n))throw new Gr(A);return false===r?e=false:kr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ft.leading=e,ft.maxWait=+t,ft.trailing=u,mr(n,t,ft)},U.times=function(n,t,r){n=0>n?0:n>>>0,t=mt(t,r,1),r=-1; +for(var e=Br(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Yr(n).replace(L,p)},U.escapeRegExp=Nr,U.every=ur,U.find=ar,U.findIndex=Kt,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,At,true) +},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,xt)},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),Ct(n,t,St,true)},U.findWhere=function(n,t){return ar(n,$r(t))},U.has=function(n,t){return n?pe.call(n,t):false},U.identity=Wr,U.indexOf=Vt,U.isArguments=xr,U.isArray=De,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&oe.call(n)==nt||false +},U.isDate=function(n){return n&&typeof n=="object"&&oe.call(n)==tt||false},U.isElement=Cr,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Oe(e+r,0):Ee(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return s._=ee,this},U.noop=zr,U.now=Me,U.pad=function(n,t,r){n=null==n?"":Yr(n),t=+t; +var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=_r({},r,e),n=Yr(null==n?"":n);var u,o,a=_r({},r.imports,e.imports),e=qe(a),a=Rr(a),i=0,l=r.interpolate||Z,f="__p+='",l=Xr((r.escape||Z).source+"|"+l.source+"|"+(l===P?z:Z).source+"|"+(r.evaluate||Z).source+"|$","g"); +n.replace(l,function(t,r,e,a,l,c){return e||(e=a),f+=n.slice(i,c).replace(V,g),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(R,""):f).replace(N,"$1").replace(T,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var c=Kr(e,"return "+f).apply(b,a) +}catch(s){throw s.source=f,s}return t?c(t):(c.source=f,c)},U.trim=Fr,U.trimLeft=function(n,t){return(n=null==n?"":Yr(n))?null==t?n.slice(v(n)):(t=Yr(t),n.slice(a(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Yr(n))?null==t?n.slice(0,y(n)+1):(t=Yr(t),n.slice(0,i(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&kr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Yr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Yr(n),r>=n.length)return n; +var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(Er(u)){if(n.slice(o).search(u)){var a,i,l=n.slice(0,o);for(u.global||(u=Xr(u.source,(D.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(l);)i=a.index;r=r.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(F,m))},U.uniqueId=function(n){var t=++S;return Yr(null==n?"":n)+t},U.all=ur,U.any=vr,U.detect=ar,U.foldl=pr,U.foldr=gr,U.include=er,U.inject=pr,Pr(U,function(){var n={}; +return At(U,function(t,r){U.prototype[r]||(n[r]=t)}),n}(),false),U.first=Mt,U.last=Xt,U.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Rr(n):Te.unindexedChars&&Ar(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Mt,U.takeRight=Xt,U.takeRightWhile=Xt,U.takeWhile=Mt,U.head=Mt,At(U,function(n,t){var r="sample"!==t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o +})}),U.VERSION=O,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=rr,U.prototype.toString=function(){return Yr(this.__wrapped__)},U.prototype.value=rr,U.prototype.valueOf=rr,st(["join","pop","shift"],function(n){var t=Hr[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),st(["push","reverse","sort","unshift"],function(n){var t=Hr[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this} +}),st(["concat","splice"],function(n){var t=Hr[n];U.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Te.spliceObjects||st(["pop","shift","splice"],function(n){var t=Hr[n],r="splice"==n;U.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),U}var b,_=1,w=2,x=4,C=8,j=16,k=32,O="2.4.1",E="__lodash@"+O+"__",A="Expected a function",S=0,I=/^[A-Z]+$/,R=/\b__p\+='';/g,N=/\b(__p\+=)''\+/g,T=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39);/g,L=/[&<>"']/g,W=/<%-([\s\S]+?)%>/g,$=/<%([\s\S]+?)%>/g,P=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,D=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,U=/[\xC0-\xFF]/g,Z=/($^)/,K=/[.*+?^${}()|[\]\/\\]/g,M=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt={}; +lt[et]=false,lt[H]=lt[Q]=lt[nt]=lt[tt]=lt[ut]=lt[ot]=lt[at]=lt[it]=true;var ft={leading:false,maxWait:0,trailing:false},ct={configurable:false,enumerable:false,value:null,writable:false},st={"&":"&","<":"<",">":">",'"':""","'":"'"},pt={"&":"&","<":"<",">":">",""":'"',"'":"'"},gt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},ht={"function":true,object:true},vt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},yt=ht[typeof window]&&window||this,mt=ht[typeof exports]&&exports&&!exports.nodeType&&exports,ht=ht[typeof module]&&module&&!module.nodeType&&module,dt=mt&&ht&&typeof global=="object"&&global; !dt||dt.global!==dt&&dt.window!==dt&&dt.self!==dt||(yt=dt);var dt=ht&&ht.exports===mt&&mt,bt=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(yt._=bt, define(function(){return bt})):mt&&ht?dt?(ht.exports=bt)._=bt:mt._=bt:yt._=bt}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index eb914d1a43..b0b568a55a 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -1436,6 +1436,30 @@ return baseForRight(object, callback, keys); } + /** + * The base implementation of `_.functions` which creates a sorted array of + * function property names from those returned by `keysFunc`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Array} Returns the new sorted array of property names. + */ + function baseFunctions(object, keysFunc) { + var index = -1, + props = keysFunc(object), + length = props.length, + result = []; + + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result.push(key); + } + } + return result.sort(); + } + /** * The base implementation of `_.isEqual`, without support for `thisArg` * binding, that allows partial "_.where" style comparisons. @@ -2788,7 +2812,7 @@ * @example * * var array = [5, 10, 15, 20]; - * var evens = _.removeAt(array, [1, 3]); + * var evens = _.pullAt(array, [1, 3]); * * console.log(array); * // => [5, 15] @@ -2803,8 +2827,8 @@ indexes.sort(baseCompareAscending); while (length--) { - var index = indexes[length]; - if (index != previous) { + var index = parseFloat(indexes[length]); + if (index != previous && index > -1 && index % 1 == 0) { var previous = index; splice.call(array, index, 1); } @@ -4769,8 +4793,8 @@ /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * of method names. If no method names are provided all enumerable function + * properties, own and inherited, of `object` will be bound. * * Note: This method does not set the `length` property of bound functions. * @@ -5143,28 +5167,28 @@ * fibonacci(9) * // => 34 * - * var data = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; - * * // modifying the result cache - * var get = _.memoize(function(name) { return data[name]; }, _.identity); - * get('pebbles'); - * // => { 'name': 'pebbles', 'age': 1 } + * var upperCase = _.memoize(function(string) { + * return string.toUpperCase(); + * }); * - * get.cache.pebbles.name = 'penelope'; - * get('pebbles'); - * // => { 'name': 'penelope', 'age': 1 } + * upperCase('fred'); + * // => 'FRED' + * + * upperCase.cache.fred = 'BARNEY' + * upperCase('fred'); + * // => 'BARNEY' */ function memoize(func, resolver) { if (!isFunction(func) || (resolver && !isFunction(resolver))) { throw new TypeError(funcErrorText); } var memoized = function() { - var cache = memoized.cache, - key = resolver ? resolver.apply(this, arguments) : '_' + arguments[0]; - + var key = resolver ? resolver.apply(this, arguments) : arguments[0]; + if (key == '__proto__') { + return func.apply(this, arguments); + } + var cache = memoized.cache; return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); @@ -5822,8 +5846,8 @@ } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * Creates a sorted array of function property names from all enumerable + * properties, own and inherited, of `object`. * * @static * @memberOf _ @@ -5837,14 +5861,7 @@ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - var result = []; - - baseForIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); - } - }); - return result.sort(); + return baseFunctions(object, keysIn); } /** @@ -7707,8 +7724,9 @@ } /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. + * Adds all own enumerable function properties of a source object to the + * destination object. If `object` is a function methods will be added to + * its prototype as well. * * @static * @memberOf _ @@ -7740,7 +7758,7 @@ */ function mixin(object, source, options) { var chain = true, - methodNames = source && functions(source); + methodNames = source && baseFunctions(source, keys); if (!source || (!options && !methodNames.length)) { if (options == null) { @@ -7748,7 +7766,7 @@ } source = object; object = this; - methodNames = functions(source); + methodNames = baseFunctions(source, keys); } if (options === false) { chain = false; @@ -7949,7 +7967,7 @@ } if (floating || min % 1 || max % 1) { var rand = nativeRandom(); - return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max); + return nativeMin(min + (rand * (max - min + parseFloat('1e-' + (String(rand).length - 1)))), max); } return baseRandom(min, max); } @@ -8286,7 +8304,7 @@ lodash.include = contains; lodash.inject = reduce; - mixin(lodash, function() { + mixin(lodash, (function() { var source = {} baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { @@ -8294,7 +8312,7 @@ } }); return source; - }(), false); + }()), false); /*--------------------------------------------------------------------------*/ @@ -8307,7 +8325,7 @@ lodash.takeRightWhile = takeRightWhile; lodash.takeWhile = takeWhile; - // add aliases + // add alias lodash.head = first; baseForOwn(lodash, function(func, methodName) { diff --git a/dist/lodash.min.js b/dist/lodash.min.js index a2357273a2..f77af7c970 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -5,62 +5,62 @@ */ ;(function(){function n(n,t){return typeof n=="undefined"?t:n}function t(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Dr(e);++ri(t,f)&&l.push(f);return l}function bt(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number"&&-1a(p,h)&&((r||l)&&p.push(h),c.push(s))}return c}function St(n,t){for(var r=-1,e=t(n),u=e.length,o=Dr(u);++ro?0:o)}function Pt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?we(u+r,0):r||0;else if(r)return r=Xt(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function Kt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++ -}else o=null==t||r?1:t;return o=e-(o||0),Jt(n,0,0>o?0:o)}function Mt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:d;return o=e-(o||0),Jt(n,0>o?0:o)}function Vt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return Jt(n,o)}function Jt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=we(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=we(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Dr(u);++e>>1,r(n[e])r?0:r);++tr?we(e+r,0):r||0:0,typeof n=="string"||!We(n)&&Cr(n)?ru&&(u=a)}else t=null==t&&Cr(n)?o:U.createCallback(t,r,3),bt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function fr(n,t){return ir(n,zr(t))}function lr(n,t,r,e){var u=3>arguments.length;t=U.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return t=U.createCallback(t,e,4),_t(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) -}),r}function pr(n){var t=-1,r=n&&n.length,e=Dr(0>r?0:r>>>0);return bt(n,function(n){var r=Rt(0,++t);e[t]=e[r],e[r]=n}),e}function sr(n,t,r){var e;t=U.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return $t(n,b,null,t);if(n)var r=n[A]?n[A][2]:n.length,e=Jt(arguments,2),r=r-e.length;return $t(n,b|k,r,t,e)}function gr(n,t,r){var e,u,o,i,a,f,l,c=0,p=false,s=true; -if(!wr(n))throw new Vr(O);if(t=0>t?0:t,true===r)var h=true,s=false;else jr(r)&&(h=r.leading,p="maxWait"in r&&we(t,+r.maxWait||0),s="trailing"in r?r.trailing:s);var g=function(){var r=t-(Be()-i);0>=r||r>t?(u&&ee(u),r=l,u=f=l=d,r&&(c=Be(),o=n.apply(a,e),f||u||(e=a=null))):f=pe(g,r)},v=function(){f&&ee(f),u=f=l=d,(s||p!==t)&&(c=Be(),o=n.apply(a,e),f||u||(e=a=null))};return function(){if(e=arguments,i=Be(),a=this,l=s&&(f||!h),false===p)var r=h&&!f;else{u||h||(c=i);var y=p-(i-c),m=0>=y||y>p;m?(u&&(u=ee(u)),c=i,o=n.apply(a,e)):u||(u=pe(v,y)) -}return m&&f?f=ee(f):f||t===p||(f=pe(g,t)),r&&(m=true,o=n.apply(a,e)),!m||f||u||(e=a=null),o}}function vr(n){if(!wr(n))throw new Vr(O);return function(){return!n.apply(this,arguments)}}function yr(n,t,r){var e=arguments;if(!n||2>e.length)return n;var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=Dr(r),a=0t||null==n||!de(t))return r;n=Mr(n);do t%2&&(r+=n),t=ue(t/2),n+=n;while(t);return r}function Nr(n,t){return(n=null==n?"":Mr(n))?null==t?n.slice(g(n),v(n)+1):(t=Mr(t),n.slice(i(n,t),a(n,t)+1)):n -}function Sr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||vt(n,t,r):"object"==e?Wr(n):zr(n)}function Tr(n){return n}function Wr(n){var t=$e(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||jr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=ae.call(e,o)&&Et(e[o],n[o],null,true)););return o}:function(n){return n&&ae.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function Fr(n,t,r){var e=true,u=t&&dr(t);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=dr(t)),false===r?e=false:jr(r)&&"chain"in r&&(e=r.chain),r=-1; -for(var o=wr(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0 -}},U.assign=yr,U.at=function(n){return t(n,jt(arguments,true,false,1))},U.bind=hr,U.bindAll=function(n){for(var t=1arguments.length?$t(t,b|_,null,n):$t(t,b|_|k,null,n,Jt(arguments,2))},U.chain=function(n){return new V(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(s?u(s,f):i(p,f))){for(t=r;--t;){var h=o[t]; -if(0>(h?u(h,f):i(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},U.invert=function(n,t){for(var r=-1,e=$e(n),u=e.length,o={};++ro?0:o>>>0);return bt(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):d}),i},U.keys=$e,U.keysIn=Ar,U.map=ir,U.mapValues=function(n,t,r){var e={};return t=U.createCallback(t,r,3),At(n,function(n,r,u){e[r]=t(n,r,u) -}),e},U.matches=Wr,U.max=ar,U.memoize=function(n,t){if(!wr(n)||t&&!wr(t))throw new Vr(O);var r=function(){var e=r.cache,u=t?t.apply(this,arguments):"_"+arguments[0];return ae.call(e,u)?e[u]:e[u]=n.apply(this,arguments)};return r.cache={},r},U.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0);for(o||(t=U.createCallback(t,r,3)),bt(n,function(n,r,u){if(o)for(r=t.length,u=Dr(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?l:f);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!wr(n))throw new Vr(O);return false===r?e=false:jr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),at.leading=e,at.maxWait=+t,at.trailing=u,gr(n,t,at) -},U.times=function(n,t,r){n=0>n?0:n>>>0,t=vt(t,r,1),r=-1;for(var e=Dr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Mr(n).replace(W,s)},U.escapeRegExp=Ir,U.every=tr,U.find=er,U.findIndex=Ut,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,At,true) -},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,_t)},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,Ot,true)},U.findWhere=function(n,t){return er(n,Wr(t))},U.has=function(n,t){return n?ae.call(n,t):false},U.identity=Tr,U.indexOf=Pt,U.isArguments=br,U.isArray=We,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ne.call(n)==H||false -},U.isDate=function(n){return n&&typeof n=="object"&&ne.call(n)==Q||false},U.isElement=_r,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?we(e+r,0):je(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return p._=Hr,this},U.noop=$r,U.now=Be,U.pad=function(n,t,r){n=null==n?"":Mr(n),t=+t; -var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=mr({},r,e),n=Mr(null==n?"":n);var u,o,i=mr({},r.imports,e.imports),e=$e(i),i=Er(i),a=0,f=r.interpolate||Z,l="__p+='",f=Kr((r.escape||Z).source+"|"+f.source+"|"+(f===z?D:Z).source+"|"+(r.evaluate||Z).source+"|$","g"); -n.replace(f,function(t,r,e,i,f,c){return e||(e=i),l+=n.slice(a,c).replace(M,h),r&&(u=true,l+="'+__e("+r+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),l+="';",(r=r.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(R,""):l).replace(N,"$1").replace(S,"$1;"),l="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=qr(e,"return "+l).apply(d,i) -}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},U.trim=Nr,U.trimLeft=function(n,t){return(n=null==n?"":Mr(n))?null==t?n.slice(g(n)):(t=Mr(t),n.slice(i(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Mr(n))?null==t?n.slice(0,v(n)+1):(t=Mr(t),n.slice(0,a(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&jr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Mr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Mr(n),r>=n.length)return n; -var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(xr(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Kr(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(T,y))},U.uniqueId=function(n){var t=++E;return Mr(null==n?"":n)+t},U.all=tr,U.any=sr,U.detect=er,U.foldl=lr,U.foldr=cr,U.include=nr,U.inject=lr,Fr(U,function(){var n={}; -return At(U,function(t,r){U.prototype[r]||(n[r]=t)}),n}(),false),U.first=Zt,U.last=Mt,U.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Er(n)),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Zt,U.takeRight=Mt,U.takeRightWhile=Mt,U.takeWhile=Zt,U.head=Zt,At(U,function(n,t){var r="sample"!==t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o -})}),U.VERSION=C,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=Qt,U.prototype.toString=function(){return Mr(this.__wrapped__)},U.prototype.value=Qt,U.prototype.valueOf=Qt,lt(["join","pop","shift"],function(n){var t=Jr[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=Jr[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this} -}),lt(["concat","splice"],function(n){var t=Jr[n];U.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__)}}),U}var d,b=1,_=2,w=4,j=8,k=16,x=32,C="2.4.1",A="__lodash@"+C+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,R=/\b__p\+='';/g,N=/\b(__p\+=)''\+/g,S=/(__e\(.*?\)|\b__t\))\+'';/g,T=/&(?:amp|lt|gt|quot|#39);/g,W=/[&<>"']/g,F=/<%-([\s\S]+?)%>/g,$=/<%([\s\S]+?)%>/g,z=/<%=([\s\S]+?)%>/g,D=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,U=/[\xC0-\xFF]/g,Z=/($^)/,P=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,M=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Function]",rt="[object Number]",et="[object Object]",ut="[object RegExp]",ot="[object String]",it={}; +}return t}function v(n){for(var t=n.length;t--;){var r=n.charCodeAt(t);if((160r||13r||8202>>0:0,u=Lr(e);++ri(t,f)&&l.push(f);return l}function bt(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number"&&-1a(p,h)&&((r||l)&&p.push(h),c.push(s))}return c}function Tt(n,t){for(var r=-1,e=t(n),u=e.length,o=Lr(u);++ro?0:o)}function Kt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?je(u+r,0):r||0;else if(r)return r=Yt(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function Mt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++ +}else o=null==t||r?1:t;return o=e-(o||0),Xt(n,0,0>o?0:o)}function Vt(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:d;return o=e-(o||0),Xt(n,0>o?0:o)}function Jt(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return Xt(n,o)}function Xt(n,t,r){var e=-1,u=n?n.length:0;for(t=typeof t=="undefined"?0:+t||0,0>t?t=je(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=je(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Lr(u);++e>>1,r(n[e])r?0:r);++tr?je(e+r,0):r||0:0,typeof n=="string"||!We(n)&&Ar(n)?ru&&(u=a)}else t=null==t&&Ar(n)?o:U.createCallback(t,r,3),bt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function lr(n,t){return ar(n,Dr(t))}function cr(n,t,r,e){var u=3>arguments.length;t=U.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return t=U.createCallback(t,e,4),_t(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) +}),r}function sr(n){var t=-1,r=n&&n.length,e=Lr(0>r?0:r>>>0);return bt(n,function(n){var r=Nt(0,++t);e[t]=e[r],e[r]=n}),e}function hr(n,t,r){var e;t=U.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return zt(n,b,null,t);if(n)var r=n[A]?n[A][2]:n.length,e=Xt(arguments,2),r=r-e.length;return zt(n,b|k,r,t,e)}function vr(n,t,r){var e,u,o,i,a,f,l,c=0,p=false,s=true; +if(!jr(n))throw new Jr(O);if(t=0>t?0:t,true===r)var h=true,s=false;else kr(r)&&(h=r.leading,p="maxWait"in r&&je(t,+r.maxWait||0),s="trailing"in r?r.trailing:s);var g=function(){var r=t-(qe()-i);0>=r||r>t?(u&&ue(u),r=l,u=f=l=d,r&&(c=qe(),o=n.apply(a,e),f||u||(e=a=null))):f=se(g,r)},v=function(){f&&ue(f),u=f=l=d,(s||p!==t)&&(c=qe(),o=n.apply(a,e),f||u||(e=a=null))};return function(){if(e=arguments,i=qe(),a=this,l=s&&(f||!h),false===p)var r=h&&!f;else{u||h||(c=i);var y=p-(i-c),m=0>=y||y>p;m?(u&&(u=ue(u)),c=i,o=n.apply(a,e)):u||(u=se(v,y)) +}return m&&f?f=ue(f):f||t===p||(f=se(g,t)),r&&(m=true,o=n.apply(a,e)),!m||f||u||(e=a=null),o}}function yr(n){if(!jr(n))throw new Jr(O);return function(){return!n.apply(this,arguments)}}function mr(n,t,r){var e=arguments;if(!n||2>e.length)return n;var u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=Lr(r),a=0t||null==n||!be(t))return r;n=Vr(n);do t%2&&(r+=n),t=oe(t/2),n+=n;while(t);return r}function Sr(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(g(n),v(n)+1):(t=Vr(t),n.slice(i(n,t),a(n,t)+1)):n}function Tr(n,t,r){var e=typeof n;return"function"==e||null==n?(typeof t=="undefined"||!(n&&"prototype"in n))&&n||vt(n,t,r):"object"==e?Wr(n):Dr(n) +}function Fr(n){return n}function Wr(n){var t=ze(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||kr(u)?function(e){var u=r;if(u&&!e)return false;for(var o=true;u--&&(o=t[u],o=fe.call(e,o)&&It(e[o],n[o],null,true)););return o}:function(n){return n&&fe.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function $r(n,t,r){var e=true,u=t&&Et(t,ze);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Et(t,ze)),false===r?e=false:kr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=jr(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0 +}},U.assign=mr,U.at=function(n){return t(n,jt(arguments,true,false,1))},U.bind=gr,U.bindAll=function(n){for(var t=1arguments.length?zt(t,b|_,null,n):zt(t,b|_|k,null,n,Xt(arguments,2))},U.chain=function(n){return new V(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(s?u(s,f):i(p,f))){for(t=r;--t;){var h=o[t]; +if(0>(h?u(h,f):i(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},U.invert=function(n,t){for(var r=-1,e=ze(n),u=e.length,o={};++ro?0:o>>>0);return bt(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):d}),i},U.keys=ze,U.keysIn=Or,U.map=ar,U.mapValues=function(n,t,r){var e={};return t=U.createCallback(t,r,3),At(n,function(n,r,u){e[r]=t(n,r,u) +}),e},U.matches=Wr,U.max=fr,U.memoize=function(n,t){if(!jr(n)||t&&!jr(t))throw new Jr(O);var r=function(){var e=t?t.apply(this,arguments):arguments[0];if("__proto__"==e)return n.apply(this,arguments);var u=r.cache;return fe.call(u,e)?u[e]:u[e]=n.apply(this,arguments)};return r.cache={},r},U.merge=function(n,t,r){var e=arguments,u=e.length,o=typeof r;if(!n||2>u)return n;if("number"!=o&&"string"!=o||!e[3]||e[3][r]!==t||(u=2),3u?0:u>>>0);for(o||(t=U.createCallback(t,r,3)),bt(n,function(n,r,u){if(o)for(r=t.length,u=Lr(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?l:f);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!jr(n))throw new Jr(O);return false===r?e=false:kr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),at.leading=e,at.maxWait=+t,at.trailing=u,vr(n,t,at) +},U.times=function(n,t,r){n=0>n?0:n>>>0,t=vt(t,r,1),r=-1;for(var e=Lr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Vr(n).replace(F,s)},U.escapeRegExp=Rr,U.every=rr,U.find=ur,U.findIndex=Zt,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,At,true) +},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,_t)},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),wt(n,t,Ot,true)},U.findWhere=function(n,t){return ur(n,Wr(t))},U.has=function(n,t){return n?fe.call(n,t):false},U.identity=Fr,U.indexOf=Kt,U.isArguments=_r,U.isArray=We,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&te.call(n)==H||false +},U.isDate=function(n){return n&&typeof n=="object"&&te.call(n)==Q||false},U.isElement=wr,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?je(e+r,0):ke(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return p._=Qr,this},U.noop=zr,U.now=qe,U.pad=function(n,t,r){n=null==n?"":Vr(n),t=+t; +var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=dr({},r,e),n=Vr(null==n?"":n);var u,o,i=dr({},r.imports,e.imports),e=ze(i),i=Ir(i),a=0,f=r.interpolate||Z,l="__p+='",f=Mr((r.escape||Z).source+"|"+f.source+"|"+(f===z?D:Z).source+"|"+(r.evaluate||Z).source+"|$","g"); +n.replace(f,function(t,r,e,i,f,c){return e||(e=i),l+=n.slice(a,c).replace(M,h),r&&(u=true,l+="'+__e("+r+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),l+="';",(r=r.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(R,""):l).replace(N,"$1").replace(S,"$1;"),l="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=Ur(e,"return "+l).apply(d,i) +}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},U.trim=Sr,U.trimLeft=function(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(g(n)):(t=Vr(t),n.slice(i(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Vr(n))?null==t?n.slice(0,v(n)+1):(t=Vr(t),n.slice(0,a(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&kr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Vr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Vr(n),r>=n.length)return n; +var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e;if(Cr(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Mr(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(T,y))},U.uniqueId=function(n){var t=++E;return Vr(null==n?"":n)+t},U.all=rr,U.any=hr,U.detect=ur,U.foldl=cr,U.foldr=pr,U.include=tr,U.inject=cr,$r(U,function(){var n={}; +return At(U,function(t,r){U.prototype[r]||(n[r]=t)}),n}(),false),U.first=Pt,U.last=Vt,U.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Ir(n)),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Pt,U.takeRight=Vt,U.takeRightWhile=Vt,U.takeWhile=Pt,U.head=Pt,At(U,function(n,t){var r="sample"!==t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o +})}),U.VERSION=C,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=nr,U.prototype.toString=function(){return Vr(this.__wrapped__)},U.prototype.value=nr,U.prototype.valueOf=nr,lt(["join","pop","shift"],function(n){var t=Xr[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),lt(["push","reverse","sort","unshift"],function(n){var t=Xr[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this} +}),lt(["concat","splice"],function(n){var t=Xr[n];U.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__)}}),U}var d,b=1,_=2,w=4,j=8,k=16,x=32,C="2.4.1",A="__lodash@"+C+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,R=/\b__p\+='';/g,N=/\b(__p\+=)''\+/g,S=/(__e\(.*?\)|\b__t\))\+'';/g,T=/&(?:amp|lt|gt|quot|#39);/g,F=/[&<>"']/g,W=/<%-([\s\S]+?)%>/g,$=/<%([\s\S]+?)%>/g,z=/<%=([\s\S]+?)%>/g,D=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,q=/^0[xX]/,U=/[\xC0-\xFF]/g,Z=/($^)/,P=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,M=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Function]",rt="[object Number]",et="[object Object]",ut="[object RegExp]",ot="[object String]",it={}; it[tt]=false,it[Y]=it[G]=it[H]=it[Q]=it[rt]=it[et]=it[ut]=it[ot]=true;var at={leading:false,maxWait:0,trailing:false},ft={configurable:false,enumerable:false,value:null,writable:false},lt={"&":"&","<":"<",">":">",'"':""","'":"'"},ct={"&":"&","<":"<",">":">",""":'"',"'":"'"},pt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},st={"function":true,object:true},ht={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},gt=st[typeof window]&&window||this,vt=st[typeof exports]&&exports&&!exports.nodeType&&exports,st=st[typeof module]&&module&&!module.nodeType&&module,yt=vt&&st&&typeof global=="object"&&global; !yt||yt.global!==yt&&yt.window!==yt&&yt.self!==yt||(gt=yt);var yt=st&&st.exports===vt&&vt,mt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(gt._=mt, define(function(){return mt})):vt&&st?yt?(st.exports=mt)._=mt:vt._=mt:gt._=mt}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index aaf23e3082..e8b84665ae 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -807,6 +807,30 @@ return baseForRight(object, callback, keys); } + /** + * The base implementation of `_.functions` which creates a sorted array of + * function property names from those returned by `keysFunc`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Array} Returns the new sorted array of property names. + */ + function baseFunctions(object, keysFunc) { + var index = -1, + props = keysFunc(object), + length = props.length, + result = []; + + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result.push(key); + } + } + return result.sort(); + } + /** * The base implementation of `_.isEqual`, without support for `thisArg` * binding, that allows partial "_.where" style comparisons. @@ -3200,8 +3224,8 @@ /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * of method names. If no method names are provided all enumerable function + * properties, own and inherited, of `object` will be bound. * * Note: This method does not set the `length` property of bound functions. * @@ -3496,19 +3520,17 @@ * fibonacci(9) * // => 34 * - * var data = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; - * * // modifying the result cache - * var get = _.memoize(function(name) { return data[name]; }, _.identity); - * get('pebbles'); - * // => { 'name': 'pebbles', 'age': 1 } + * var upperCase = _.memoize(function(string) { + * return string.toUpperCase(); + * }); + * + * upperCase('fred'); + * // => 'FRED' * - * get.cache.pebbles.name = 'penelope'; - * get('pebbles'); - * // => { 'name': 'penelope', 'age': 1 } + * upperCase.cache.fred = 'BARNEY' + * upperCase('fred'); + * // => 'BARNEY' */ function memoize(func, resolver) { if (!isFunction(func) || (resolver && !isFunction(resolver))) { @@ -3516,7 +3538,10 @@ } var cache = {}; return function() { - var key = resolver ? resolver.apply(this, arguments) : '_' + arguments[0]; + var key = resolver ? resolver.apply(this, arguments) : arguments[0]; + if (key == '__proto__') { + return func.apply(this, arguments); + } return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); @@ -3836,8 +3861,8 @@ } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * Creates a sorted array of function property names from all enumerable + * properties, own and inherited, of `object`. * * @static * @memberOf _ @@ -3851,14 +3876,7 @@ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - var result = []; - - baseForIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); - } - }); - return result.sort(); + return baseFunctions(object, keysIn); } /** @@ -4874,8 +4892,9 @@ } /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. + * Adds all own enumerable function properties of a source object to the + * destination object. If `object` is a function methods will be added to + * its prototype as well. * * @static * @memberOf _ @@ -5312,7 +5331,7 @@ lodash.sample = sample; lodash.take = take; - // add aliases + // add alias lodash.head = first; /*--------------------------------------------------------------------------*/ @@ -5333,36 +5352,36 @@ lodash.prototype.chain = wrapperChain; lodash.prototype.value = wrapperValueOf; - // add `Array` mutator functions to the wrapper - arrayEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { - var func = arrayRef[methodName]; - lodash.prototype[methodName] = function() { - var value = this.__wrapped__; - func.apply(value, arguments); - - // avoid array-like object bugs with `Array#shift` and `Array#splice` - // in Firefox < 10 and IE < 9 - if (!support.spliceObjects && value.length === 0) { - delete value[0]; - } - return this; - }; - }); + // add `Array` mutator functions to the wrapper + arrayEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var func = arrayRef[methodName]; + lodash.prototype[methodName] = function() { + var value = this.__wrapped__; + func.apply(value, arguments); + + // avoid array-like object bugs with `Array#shift` and `Array#splice` + // in Firefox < 10 and IE < 9 + if (!support.spliceObjects && value.length === 0) { + delete value[0]; + } + return this; + }; + }); - // add `Array` accessor functions to the wrapper - arrayEach(['concat', 'join', 'slice'], function(methodName) { - var func = arrayRef[methodName]; - lodash.prototype[methodName] = function() { - var value = this.__wrapped__, - result = func.apply(value, arguments); + // add `Array` accessor functions to the wrapper + arrayEach(['concat', 'join', 'slice'], function(methodName) { + var func = arrayRef[methodName]; + lodash.prototype[methodName] = function() { + var value = this.__wrapped__, + result = func.apply(value, arguments); - if (this.__chain__) { - result = new lodashWrapper(result); - result.__chain__ = true; - } - return result; - }; - }); + if (this.__chain__) { + result = new lodashWrapper(result); + result.__chain__ = true; + } + return result; + }; + }); /*--------------------------------------------------------------------------*/ diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index 1d369098e7..9b3b9c8131 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -18,17 +18,18 @@ r=or(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length;return r=or(r,e,4),h(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function U(n){var r=-1,t=n&&n.length,e=Array(0>t?0:t>>>0);return g(n,function(n){var t=_(++r);e[r]=e[t],e[t]=n}),e}function V(n,r,t){var e;r=or(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length?x(n,pr,r):x(n,pr|gr,r,N(arguments,2))}function H(n,r,t){function e(){l&&clearTimeout(l),i=l=p=lr,(h||g!==r)&&(s=yt(),f=n.apply(c,o),l||i||(o=c=null))}function u(){var t=r-(yt()-a);0>=t||t>r?(i&&clearTimeout(i),t=p,i=l=p=lr,t&&(s=yt(),f=n.apply(c,o),l||i||(o=c=null))):l=setTimeout(u,t)}var o,i,f,a,c,l,p,s=0,g=false,h=true;if(!Y(n))throw new TypeError(vr);if(r=0>r?0:r,true===t)var v=true,h=false;else Z(t)&&(v=t.leading,g="maxWait"in t&&et(r,+t.maxWait||0),h="trailing"in t?t.trailing:h); return function(){if(o=arguments,a=yt(),c=this,p=h&&(l||!v),false===g)var t=v&&!l;else{i||v||(s=a);var y=g-(a-s),m=0>=y||y>g;m?(i&&(i=clearTimeout(i)),s=a,f=n.apply(c,o)):i||(i=setTimeout(e,y))}return m&&l?l=clearTimeout(l):l||r===g||(l=setTimeout(u,r)),t&&(m=true,f=n.apply(c,o)),!m||l||i||(o=c=null),f}}function J(n){if(!Y(n))throw new TypeError(vr);return function(){return!n.apply(this,arguments)}}function K(n,r,t){if(!n)return n;var e=arguments,u=0,o=e.length,i=typeof t;for("number"!=i&&"string"!=i||!e[3]||e[3][t]!==r||(o=2);++u"']/g,dr=/($^)/,_r=/[.*+?^${}()|[\]\/\\]/g,wr=/['\n\r\u2028\u2029\\]/g,jr="[object Arguments]",xr="[object Array]",Tr="[object Boolean]",Ar="[object Date]",Er="[object Number]",Or="[object Object]",kr="[object RegExp]",Sr="[object String]",Nr={"&":"&","<":"<",">":">",'"':""","'":"'"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'"},Fr={"function":true,object:true},Br={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mr=Fr[typeof window]&&window||this,Rr=Fr[typeof exports]&&exports&&!exports.nodeType&&exports,$r=Fr[typeof module]&&module&&!module.nodeType&&module,Ir=Rr&&$r&&typeof global=="object"&&global; +for(var f in r)n[f]=r[f]}return n}function L(n,r,t){if(!n)return n;var e=arguments,u=0,o=e.length,i=typeof t;for("number"!=i&&"string"!=i||!e[3]||e[3][t]!==r||(o=2);++u"']/g,dr=/($^)/,_r=/[.*+?^${}()|[\]\/\\]/g,wr=/['\n\r\u2028\u2029\\]/g,jr="[object Arguments]",xr="[object Array]",Tr="[object Boolean]",Ar="[object Date]",Er="[object Number]",Or="[object Object]",kr="[object RegExp]",Sr="[object String]",Nr={"&":"&","<":"<",">":">",'"':""","'":"'"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'"},Fr={"function":true,object:true},Br={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mr=Fr[typeof window]&&window||this,Rr=Fr[typeof exports]&&exports&&!exports.nodeType&&exports,$r=Fr[typeof module]&&module&&!module.nodeType&&module,Ir=Rr&&$r&&typeof global=="object"&&global; !Ir||Ir.global!==Ir&&Ir.window!==Ir&&Ir.self!==Ir||(Mr=Ir);var Dr=$r&&$r.exports===Rr&&Rr,Wr=Array.prototype,zr=Object.prototype,Cr=Mr._,Pr=Math.pow(2,53)-1,Ur=zr.toString,Vr=RegExp("^"+(null==Ur?"":(Ur+"").replace(_r,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Gr=Math.ceil,Hr=Math.floor,Jr=Function.prototype.toString,Kr=zr.hasOwnProperty,Lr=Wr.push,Qr=zr.propertyIsEnumerable,Xr=Wr.splice,Yr=A(Yr=Object.create)&&Yr,Zr=A(Zr=Array.isArray)&&Zr,nt=Mr.isFinite,rt=Mr.isNaN,tt=A(tt=Object.keys)&&tt,et=Math.max,ut=Math.min,ot=A(ot=Date.now)&&ot,it=Math.random; i.prototype=o.prototype;var ft={};!function(){var n={0:1,length:1};ft.spliceObjects=(Xr.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Yr||(c=function(){function n(){}return function(r){if(Z(r)){n.prototype=r;var t=new n;n.prototype=null}return t||Mr.Object()}}());var at=S,ct=O,lt=j(function(n,r,t){Kr.call(n,t)?n[t]++:n[t]=1}),pt=j(function(n,r,t){Kr.call(n,t)?n[t].push(r):n[t]=[r]}),st=j(function(n,r,t){n[t]=r }),gt=j(function(n,r,t){n[t?0:1].push(r)},function(){return[[],[]]});X(arguments)||(X=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Kr.call(n,"callee")&&!Qr.call(n,"callee")||false});var ht=Zr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ur.call(n)==xr||false};Y(/x/)&&(Y=function(n){return typeof n=="function"&&"[object Function]"==Ur.call(n)});var vt=tt?function(n){return Z(n)?tt(n):[]}:E,yt=ot||function(){return(new Date).getTime()};o.after=function(n,r){if(!Y(r))throw new TypeError(vr); return n=nt(n=+n)?n:0,function(){return 1>--n?r.apply(this,arguments):void 0}},o.bind=G,o.bindAll=function(n){for(var r=1r?0:r)},o.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},o.invert=function(n){for(var r=-1,t=vt(n),e=t.length,u={};++ro?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):lr}),i},o.keys=vt,o.map=D,o.matches=fr,o.max=W,o.memoize=function(n,r){if(!Y(n)||r&&!Y(r))throw new TypeError(vr);var t={};return function(){var e=r?r.apply(this,arguments):"_"+arguments[0];return Kr.call(t,e)?t[e]:t[e]=n.apply(this,arguments)}},o.min=function(n,r,t){var e=1/0,u=e,o=typeof r;"number"!=o&&"string"!=o||!t||t[r]!==n||(r=null); -var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number"&&-1o?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):lr}),i},o.keys=vt,o.map=D,o.matches=fr,o.max=W,o.memoize=function(n,r){if(!Y(n)||r&&!Y(r))throw new TypeError(vr);var t={};return function(){var e=r?r.apply(this,arguments):arguments[0];return"__proto__"==e?n.apply(this,arguments):Kr.call(t,e)?t[e]:t[e]=n.apply(this,arguments)}},o.min=function(n,r,t){var e=1/0,u=e,o=typeof r; +"number"!=o&&"string"!=o||!t||t[r]!==n||(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number"&&-1o?0:o>>>0);for(t=or(t,e,3),g(n,function(n,r,e){i[++u]={a:t(n,r,e),b:u,c:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].c; return i},o.tap=function(n,r){return r(n),n},o.throttle=function(n,r,t){var e=true,u=true;if(!Y(n))throw new TypeError(vr);return false===t?e=false:Z(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),H(n,r,{leading:e,maxWait:r,trailing:u})},o.times=function(n,r,t){n=0>n?0:n>>>0,r=l(r,t,1),t=-1;for(var e=Array(n);++tr?0:r);++n Date: Fri, 9 May 2014 08:46:56 -0700 Subject: [PATCH 0645/1608] Fix typo in `_.times` docs. [ci skip] [closes #549] --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 5d6c156eee..2315f57e18 100644 --- a/lodash.js +++ b/lodash.js @@ -8297,7 +8297,7 @@ * @returns {Array} Returns the array of results. * @example * - * var diceRolls = _.times(3, _.partial(_.random, 1, 6)); + * var diceRolls = _.times(3, _.partial(_.random, 1, 6, false)); * // => [3, 6, 4] * * _.times(3, function(n) { mage.castSpell(n); }); From ee4a7034072ff6356b18a20cfc8353f47ca48a71 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 10 May 2014 01:14:52 -0700 Subject: [PATCH 0646/1608] Add `createAssigner`, `defaultsOwn`, and expand the `callback` args of `_.assign` and `_.merge`. --- lodash.js | 87 ++++++++++++++++++++++++++++++++++++++-------------- test/test.js | 77 +++++++++++++++++++++------------------------- 2 files changed, 99 insertions(+), 65 deletions(-) diff --git a/lodash.js b/lodash.js index 2315f57e18..fdacc3b4be 100644 --- a/lodash.js +++ b/lodash.js @@ -248,6 +248,22 @@ return typeof objectValue == 'undefined' ? sourceValue : objectValue; } + /** + * Used by `defaultsOwn` to customize its `_.assign` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @param {string} key The key associated with the object and source values. + * @param {Object} object The destination object. + * @returns {*} Returns the value to assign to the destination object. + */ + function assignDefaultsOwn(objectValue, sourceValue, key, object) { + return (!hasOwnProperty.call(object, key) || typeof objectValue == 'undefined') + ? sourceValue + : objectValue + } + /** * The base implementation of `_.at` without support for strings or individual * key arguments. @@ -1814,17 +1830,17 @@ * @param {Array} [stackB=[]] Associates values with source counterparts. */ function baseMerge(object, source, callback, stackA, stackB) { - (isArray(source) ? arrayEach : baseForOwn)(source, function(source, key) { + (isArray(source) ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { var found, isArr, - result = source, + result = srcValue, value = object[key]; - if (source && ((isArr = isArray(source)) || isPlainObject(source))) { + if (srcValue && ((isArr = isArray(srcValue)) || isPlainObject(srcValue))) { // avoid merging previously merged cyclic sources var stackLength = stackA.length; while (stackLength--) { - if ((found = stackA[stackLength] == source)) { + if ((found = stackA[stackLength] == srcValue)) { value = stackB[stackLength]; break; } @@ -1832,7 +1848,7 @@ if (!found) { var isShallow; if (callback) { - result = callback(value, source); + result = callback(value, srcValue, key, object, source); if ((isShallow = typeof result != 'undefined')) { value = result; } @@ -1843,20 +1859,20 @@ : (isPlainObject(value) ? value : {}); } // add `source` and associated `value` to the stack of traversed objects - stackA.push(source); + stackA.push(srcValue); stackB.push(value); // recursively merge objects and arrays (susceptible to call stack limits) if (!isShallow) { - baseMerge(value, source, callback, stackA, stackB); + baseMerge(value, srcValue, callback, stackA, stackB); } } } else { if (callback) { - result = callback(value, source); + result = callback(value, srcValue, key, object, source); if (typeof result == 'undefined') { - result = source; + result = srcValue; } } if (typeof result != 'undefined') { @@ -2059,6 +2075,27 @@ }; } + /** + * Creates a function that assigns own enumerable properties of source + * object(s) to the destination object executing the callback to produce + * the assigned values. The callback is invoked with five arguments; + * (objectValue, sourceValue, key, object, source). + * + * @private + * @param {Function} [callback] The function to customize assigning values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(callback) { + return function(object) { + if (!object) { + return object; + } + var args = slice(arguments); + args.push(callback); + return assign.apply(null, args); + }; + } + /** * Creates a cache object to optimize linear searches of large arrays. * @@ -2203,6 +2240,17 @@ : baseCreateWrapper(data); } + /** + * This method is like `_.defaults` except that it ignores inherited + * property values when checking if a property is `undefined`. + * + * @private + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns the destination object. + */ + var defaultsOwn = createAssigner(assignDefaultsOwn); + /** * Finds the indexes of all placeholder elements in `array`. * @@ -5588,8 +5636,8 @@ * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources will overwrite property assignments of previous * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with two - * arguments; (objectValue, sourceValue). + * assigned values. The callback is bound to `thisArg` and invoked with + * five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -5639,7 +5687,7 @@ while (++index < length) { var key = props[index]; - object[key] = callback ? callback(object[key], source[key]) : source[key]; + object[key] = callback ? callback(object[key], source[key], key, object, source) : source[key]; } } return object; @@ -5812,14 +5860,7 @@ * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ - function defaults(object) { - if (!object) { - return object; - } - var args = slice(arguments); - args.push(assignDefaults); - return assign.apply(null, args); - } + var defaults = createAssigner(assignDefaults); /** * This method is like `_.findIndex` except that it returns the key of the @@ -6781,7 +6822,7 @@ * provided it will be executed to produce the merged values of the destination * and source properties. If the callback returns `undefined` merging will * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (objectValue, sourceValue). + * invoked with five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -7505,10 +7546,10 @@ // and Laura Doktorova's doT.js // https://github.com/olado/doT var settings = lodash.templateSettings; - options = defaults({}, options, settings); + options = defaultsOwn({}, options, settings); string = String(string == null ? '' : string); - var imports = defaults({}, options.imports, settings.imports), + var imports = defaultsOwn({}, options.imports, settings.imports), importsKeys = keys(imports), importsValues = values(imports); diff --git a/test/test.js b/test/test.js index 6e2d2de1a3..3171a1bfec 100644 --- a/test/test.js +++ b/test/test.js @@ -639,24 +639,6 @@ deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); }); - test('should pass the correct `callback` arguments', 1, function() { - var args; - - _.assign({ 'a': 1 }, { 'b': 2 }, function() { - args || (args = slice.call(arguments)); - }); - - deepEqual(args, [undefined, 2]); - }); - - test('should support the `thisArg` argument', 1, function() { - var actual = _.assign({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) { - return typeof this[a] == 'undefined' ? this[b] : this[a]; - }, { '1': 1, '2': 2, '3': 3 }); - - deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); - }); - test('should be aliased', 1, function() { strictEqual(_.extend, _.assign); }); @@ -3356,26 +3338,46 @@ }); _.each(['assign', 'merge'], function(methodName) { - var func = _[methodName]; + var func = _[methodName], + isMerge = methodName == 'merge'; - test('`_.' + methodName + '` should pass the correct `callback` arguments', 2, function() { - var args; + test('`_.' + methodName + '` should pass the correct `callback` arguments', 3, function() { + var args, + object = { 'a': 1 }, + source = { 'a': 2 }; - func({ 'a': 1 }, { 'a': 2 }, function() { + func(object, source, function() { args || (args = slice.call(arguments)); }); - deepEqual(args, [1, 2], 'primitive property values'); - - var array = [1, 2], - object = { 'b': 2 }; + deepEqual(args, [1, 2, 'a', object, source], 'primitive property values'); args = null; - func({ 'a': array }, { 'a': object }, function() { + object = { 'a': 1 }; + source = { 'b': 2 }; + + func(object, source, function() { args || (args = slice.call(arguments)); }); - deepEqual(args, [array, object], 'non-primitive property values'); + deepEqual(args, [undefined, 2, 'b', object, source], 'missing destination property'); + + var argsList = [], + objectValue = [1, 2], + sourceValue = { 'b': 2 }; + + object = { 'a': objectValue }; + source = { 'a': sourceValue }; + + func(object, source, function() { + argsList.push(slice.call(arguments)); + }); + + var expected = [[objectValue, sourceValue, 'a', object, source]]; + if (isMerge) { + expected.push([undefined, 2, 'b', sourceValue, sourceValue]); + } + deepEqual(argsList, expected, 'non-primitive property values'); }); test('`_.' + methodName + '`should support the `thisArg` argument', 1, function() { @@ -6216,18 +6218,6 @@ }); deepEqual(actual, { 'a': { 'b': [0, 1, 2] } }); }); - - test('should pass the correct values to `callback`', 1, function() { - var argsList = [], - array = [1, 2], - object = { 'b': 2 }; - - _.merge({ 'a': array }, { 'a': object }, function(a, b) { - argsList.push(slice.call(arguments)); - }); - - deepEqual(argsList, [[array, object], [undefined, 2]]); - }); }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -6987,8 +6977,11 @@ source = { 'a': { 'b': 2, 'c': 3 } }, expected = { 'a': { 'b': 1, 'c': 3 } }; - var deepDefaults = _.partialRight(_.merge, _.defaults); - deepEqual(deepDefaults(object, source), expected); + var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { + return _.merge(value, other, deep); + }); + + deepEqual(defaultsDeep(object, source), expected); }); }()); From d5c3b258f33ade2617054f3e6d87a01b7c8e3cba Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 11 May 2014 03:49:41 -0700 Subject: [PATCH 0647/1608] Rename `assignDefaultsOwn` to `assignOwnDefaults` and remove `createAssigner` and `defaultsOwn`. --- lodash.js | 104 +++++++++++++++++++++--------------------------------- 1 file changed, 41 insertions(+), 63 deletions(-) diff --git a/lodash.js b/lodash.js index fdacc3b4be..5febbeb128 100644 --- a/lodash.js +++ b/lodash.js @@ -236,34 +236,6 @@ /*--------------------------------------------------------------------------*/ - /** - * Used by `_.defaults` to customize its `_.assign` use. - * - * @private - * @param {*} objectValue The destination object property value. - * @param {*} sourceValue The source object property value. - * @returns {*} Returns the value to assign to the destination object. - */ - function assignDefaults(objectValue, sourceValue) { - return typeof objectValue == 'undefined' ? sourceValue : objectValue; - } - - /** - * Used by `defaultsOwn` to customize its `_.assign` use. - * - * @private - * @param {*} objectValue The destination object property value. - * @param {*} sourceValue The source object property value. - * @param {string} key The key associated with the object and source values. - * @param {Object} object The destination object. - * @returns {*} Returns the value to assign to the destination object. - */ - function assignDefaultsOwn(objectValue, sourceValue, key, object) { - return (!hasOwnProperty.call(object, key) || typeof objectValue == 'undefined') - ? sourceValue - : objectValue - } - /** * The base implementation of `_.at` without support for strings or individual * key arguments. @@ -1079,6 +1051,37 @@ return result; } + /** + * Used by `_.defaults` to customize its `_.assign` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function assignDefaults(objectValue, sourceValue) { + return typeof objectValue == 'undefined' ? sourceValue : objectValue; + } + + /** + * Used by `_.template` to customize its `_.assign` use. + * + * Note: This method is like `assignDefaults` except that it ignores + * inherited property values when checking if a property is `undefined`. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @param {string} key The key associated with the object and source values. + * @param {Object} object The destination object. + * @returns {*} Returns the value to assign to the destination object. + */ + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return (!hasOwnProperty.call(object, key) || typeof objectValue == 'undefined') + ? sourceValue + : objectValue + } + /** * The base implementation of `_.bind` that creates the bound function and * sets its metadata. @@ -2075,27 +2078,6 @@ }; } - /** - * Creates a function that assigns own enumerable properties of source - * object(s) to the destination object executing the callback to produce - * the assigned values. The callback is invoked with five arguments; - * (objectValue, sourceValue, key, object, source). - * - * @private - * @param {Function} [callback] The function to customize assigning values. - * @returns {Function} Returns the new assigner function. - */ - function createAssigner(callback) { - return function(object) { - if (!object) { - return object; - } - var args = slice(arguments); - args.push(callback); - return assign.apply(null, args); - }; - } - /** * Creates a cache object to optimize linear searches of large arrays. * @@ -2240,17 +2222,6 @@ : baseCreateWrapper(data); } - /** - * This method is like `_.defaults` except that it ignores inherited - * property values when checking if a property is `undefined`. - * - * @private - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns the destination object. - */ - var defaultsOwn = createAssigner(assignDefaultsOwn); - /** * Finds the indexes of all placeholder elements in `array`. * @@ -5860,7 +5831,14 @@ * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ - var defaults = createAssigner(assignDefaults); + function defaults(object) { + if (!object) { + return object; + } + var args = slice(arguments); + args.push(assignDefaults); + return assign.apply(null, args); + } /** * This method is like `_.findIndex` except that it returns the key of the @@ -7546,10 +7524,10 @@ // and Laura Doktorova's doT.js // https://github.com/olado/doT var settings = lodash.templateSettings; - options = defaultsOwn({}, options, settings); + options = assign({}, options, settings, assignOwnDefaults); string = String(string == null ? '' : string); - var imports = defaultsOwn({}, options.imports, settings.imports), + var imports = assign({}, options.imports, settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = values(imports); From 0f8c20c3ab0debccd24d4c9574a2b0b523578dfc Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 11 May 2014 16:02:48 -0700 Subject: [PATCH 0648/1608] Add `ui.isForeign`, add guards for Worker tests, and remove Dojo loader filter from test. --- test/asset/test-ui.js | 15 +++++++++------ test/asset/worker.js | 6 +++++- test/index.html | 8 +++----- test/test.js | 16 +++++++++------- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/test/asset/test-ui.js b/test/asset/test-ui.js index c4f038b5d9..5456fd2eea 100644 --- a/test/asset/test-ui.js +++ b/test/asset/test-ui.js @@ -128,6 +128,15 @@ init(); }); + // used to indicate testing a foreign file + ui.isForeign = RegExp('^(\\w+:)?//').test(build); + + // used to indicate testing a modularized build + ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|node)|modularize|npm)\b/.test([location.pathname, location.search]); + + // used to indicate testing in Sauce Labs' automated test cloud + ui.isSauceLabs = location.port == '9001'; + // expose Lo-Dash build file path ui.buildPath = (function() { var result; @@ -170,12 +179,6 @@ 'loadEventEnd': 0 }; - // used to indicate testing a modularized build - ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|node)|modularize|npm)\b/.test([location.pathname, location.search, ui.buildPath]); - - // used to indicate testing in Sauce Labs' automated test cloud - ui.isSauceLabs = location.port == '9001'; - // expose `ui` window.ui = ui; diff --git a/test/asset/worker.js b/test/asset/worker.js index 75f21c9a58..d925de5239 100644 --- a/test/asset/worker.js +++ b/test/asset/worker.js @@ -1,6 +1,10 @@ addEventListener('message', function(e) { if (e.data) { - importScripts('../' + e.data); + try { + importScripts('../' + e.data); + } catch(e) { + self._ = {}; + } postMessage(_.VERSION); } }, false); diff --git a/test/index.html b/test/index.html index 9606cf2a8a..96a59fc924 100644 --- a/test/index.html +++ b/test/index.html @@ -168,7 +168,7 @@ removeBizarroMethods(); } // load test scripts - document.write(ui.urlParams.loader == 'none' + document.write((ui.isForeign || ui.urlParams.loader == 'none') ? ' @@ -42,13 +53,6 @@

    Test

    } }; - // avoid reporting tests to Sauce Labs when script errors occur - if (ui.isSauceLabs) { - window.onerror = function(message) { - QUnit.config.done.length = 0; - global_test_results = { 'message': message }; - }; - } // load Lo-Dash if (!ui.isModularize) { document.write(' @@ -154,13 +165,6 @@ QUnit.config.hidepassed = true; - // avoid reporting tests to Sauce Labs when script errors occur - if (ui.isSauceLabs) { - window.onerror = function(message) { - QUnit.config.done.length = 0; - global_test_results = { 'message': message }; - }; - } // load Lo-Dash and expose it to the bad extensions/shims if (!ui.isModularize) { addBizarroMethods(); diff --git a/test/underscore.html b/test/underscore.html index c9337d1c0d..04db047cc9 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -19,6 +19,17 @@ + @@ -128,13 +139,6 @@ } }; - // avoid reporting tests to Sauce Labs when script errors occur - if (ui.isSauceLabs) { - window.onerror = function(message) { - QUnit.config.done.length = 0; - global_test_results = { 'message': message }; - }; - } // only excuse in Sauce Labs (buggy Safari and timers) else { delete QUnit.config.excused.Chaining['select/reject/sortBy']; From f935b141f15be6c86e38501eb4f5f0783dca5d17 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 28 May 2014 14:24:56 -0400 Subject: [PATCH 0712/1608] Fix test typo. --- test/test.js | 2 +- test/underscore.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index e0b2871412..d8d83bc5e7 100644 --- a/test/test.js +++ b/test/test.js @@ -1376,7 +1376,7 @@ notStrictEqual(actual, object); } else { - skipTest(); + skipTest(2); } }); }); diff --git a/test/underscore.html b/test/underscore.html index 04db047cc9..2f4905fc62 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -140,7 +140,7 @@ }; // only excuse in Sauce Labs (buggy Safari and timers) - else { + if (!ui.isSauceLabs) { delete QUnit.config.excused.Chaining['select/reject/sortBy']; delete QUnit.config.excused.Chaining['select/reject/sortBy in functional style']; delete QUnit.config.excused.Functions['throttle repeatedly with results']; From ae7ef24196cf16abb0e14cd2207572c01835f752 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 28 May 2014 15:19:56 -0400 Subject: [PATCH 0713/1608] Minor source nit in test/test.js. --- test/test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index d8d83bc5e7..925fb044b3 100644 --- a/test/test.js +++ b/test/test.js @@ -113,9 +113,9 @@ }()); /** Load and install QUnit Extras */ - var qa = load('../vendor/qunit-extras/qunit-extras.js'); - if (qa) { - qa.runInContext(root); + var qe = load('../vendor/qunit-extras/qunit-extras.js'); + if (qe) { + qe.runInContext(root); } /*--------------------------------------------------------------------------*/ From c555681c8bb3aa871fe4261a252d5f19dbc668fd Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 28 May 2014 15:35:00 -0400 Subject: [PATCH 0714/1608] Add extra object in doc examples of `_.assign` and `_.defaults`. [ci skip] --- lodash.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lodash.js b/lodash.js index 7ed4c4585c..851e26ac97 100644 --- a/lodash.js +++ b/lodash.js @@ -5910,15 +5910,15 @@ * @returns {Object} Returns the destination object. * @example * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } + * _.assign({ 'name': 'fred' }, { 'age': 40 }, { 'employer': 'slate' }); + * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' } * * var defaults = _.partialRight(_.assign, function(value, other) { * return typeof value == 'undefined' ? other : value; * }); * - * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ var assign = createAssigner(baseAssign); @@ -6086,8 +6086,8 @@ * @returns {Object} Returns the destination object. * @example * - * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { if (!object) { From 691e21fa78c0b78587e26112c89a0799a2429c4d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 28 May 2014 16:29:08 -0400 Subject: [PATCH 0715/1608] Delay status completion until there is a valid job ID. --- test/saucelabs.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index d20b45ca50..8009ed6de7 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -246,6 +246,17 @@ function getOption(name, defaultValue) { }, defaultValue); } +/** + * Checks if `value` is a job ID. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a job ID, else `false`. + */ +function isJobId(value) { + return reJobId.test(value); +} + /** * Writes an inline message to standard output. * @@ -395,7 +406,7 @@ function onJobStart(error, res, body) { * @param {Object} body The response body JSON object. */ function onJobStatus(error, res, body) { - var completed = _.result(body, 'completed'), + var completed = _.result(body, 'completed', false), data = _.first(_.result(body, 'js tests')), jobId = _.result(data, 'job_id', null), jobResult = _.result(data, 'result', null), @@ -416,10 +427,12 @@ function onJobStatus(error, res, body) { if (!this.running || this.stopping) { return; } - if (reJobId.test(jobId)) { + if (isJobId(jobId)) { this.id = jobId; this.result = jobResult; this.url = jobUrl; + } else { + completed = false; } this.emit('status', jobStatus); @@ -533,7 +546,7 @@ Job.prototype.remove = function(callback) { this.removing = true; return this.stop(function() { var onRemove = _.bind(onJobRemove, this); - if (!reJobId.test(this.id)) { + if (!this.id) { _.defer(onRemove); return; } @@ -646,7 +659,7 @@ Job.prototype.stop = function(callback) { this.checking = false; } var onStop = _.bind(onGenericStop, this); - if (!this.running || !reJobId.test(this.id)) { + if (!this.running || !this.id) { _.defer(onStop); return this; } From 95db668c3c2b313ba01fed1c91b632996dbe757a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 10:03:06 -0400 Subject: [PATCH 0716/1608] Make `reError` more robust and leverage `console.log` sugar more. --- test/saucelabs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 8009ed6de7..155729cbf4 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -53,7 +53,7 @@ var prevLine = ''; var push = Array.prototype.push; /** Used to detect error messages */ -var reError = /\berror\b/i; +var reError = /(?:\be|E)rror\b/; /** Used to detect valid job ids */ var reJobId = /^[a-z0-9]{32}$/; @@ -592,7 +592,7 @@ Job.prototype.restart = function(callback) { label = options.name + ':'; logInline(); - console.log(label + ' ' + description + ' restart %d of %d', ++this.attempts, this.retries); + console.log('%s %s restart %d of %d', label, description, ++this.attempts, this.retries); return this.remove(onGenericRestart); }; @@ -755,7 +755,7 @@ Tunnel.prototype.restart = function(callback) { this.restarting = true; logInline(); - console.log('Tunnel ' + this.id + ': restart %d of %d', ++this.attempts, this.retries); + console.log('Tunnel %s: restart %d of %d', this.id, ++this.attempts, this.retries); var jobs = this.jobs, active = jobs.active, From f4a1573586998b5f432fd86e1aa0dcb9d75e428d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 12:26:52 -0400 Subject: [PATCH 0717/1608] Rename `_.truncate` to `_.trunc` to align with ES6. --- README.md | 2 +- lodash.js | 14 +++++++------- test/saucelabs.js | 2 +- test/test.js | 32 ++++++++++++++++---------------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index f93fe914a1..7a9522e361 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ A list of upcoming features is available on our [roadmap](https://github.com/lod * [_.bind](http://lodash.com/docs#bind), [_.curry](http://lodash.com/docs#curry), [_.partial](http://lodash.com/docs#partial), & [more](http://lodash.com/docs "_.bindKey, _.partialRight") support argument placeholders * [_.capitalize](http://lodash.com/docs#capitalize), [_.trim](http://lodash.com/docs#trim), & - [more](http://lodash.com/docs "_.camelCase, _.endsWith, _.escapeRegExp, _.kebabCase, _.pad, _.padLeft, _.padRight, _.repeat, _.snakeCase, _.startsWith, _.trimLeft, _.trimRight, _.truncate") string methods + [more](http://lodash.com/docs "_.camelCase, _.endsWith, _.escapeRegExp, _.kebabCase, _.pad, _.padLeft, _.padRight, _.repeat, _.snakeCase, _.startsWith, _.trimLeft, _.trimRight, _.trunc") string methods * [_.contains](http://lodash.com/docs#contains), [_.toArray](http://lodash.com/docs#toArray), & [more](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.forEachRight, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.size, _.some, _.sortBy, _.where") accept strings * [_.dropWhile](http://lodash.com/docs#dropWhile), [_.takeWhile](http://lodash.com/docs#takeWhile), & diff --git a/lodash.js b/lodash.js index 851e26ac97..5c777b30cf 100644 --- a/lodash.js +++ b/lodash.js @@ -7937,22 +7937,22 @@ * @returns {string} Returns the truncated string. * @example * - * _.truncate('hi-diddly-ho there, neighborino'); + * _.trunc('hi-diddly-ho there, neighborino'); * // => 'hi-diddly-ho there, neighbo...' * - * _.truncate('hi-diddly-ho there, neighborino', 24); + * _.trunc('hi-diddly-ho there, neighborino', 24); * // => 'hi-diddly-ho there, n...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); * // => 'hi-diddly-ho there,...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); * //=> 'hi-diddly-ho there...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); + * _.trunc('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); * // => 'hi-diddly-ho there, neig [...]' */ - function truncate(string, options) { + function trunc(string, options) { var length = 30, omission = '...'; @@ -8740,7 +8740,7 @@ lodash.trim = trim; lodash.trimLeft = trimLeft; lodash.trimRight = trimRight; - lodash.truncate = truncate; + lodash.trunc = trunc; lodash.unescape = unescape; lodash.uniqueId = uniqueId; diff --git a/test/saucelabs.js b/test/saucelabs.js index 155729cbf4..e08cf7ade4 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -265,7 +265,7 @@ function isJobId(value) { */ function logInline(text) { var blankLine = _.repeat(' ', _.size(prevLine)); - prevLine = text = _.truncate(text, 40); + prevLine = text = _.trunc(text, 40); process.stdout.write(text + blankLine.slice(text.length) + '\r'); } diff --git a/test/test.js b/test/test.js index 925fb044b3..cea191069c 100644 --- a/test/test.js +++ b/test/test.js @@ -9148,55 +9148,55 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.truncate'); + QUnit.module('lodash.trunc'); (function() { var string = 'hi-diddly-ho there, neighborino'; test('should truncate to a length of `30` by default', 1, function() { - strictEqual(_.truncate(string), 'hi-diddly-ho there, neighbo...'); + strictEqual(_.trunc(string), 'hi-diddly-ho there, neighbo...'); }); test('should not truncate if `string` is <= `length`', 2, function() { - strictEqual(_.truncate(string, string.length), string); - strictEqual(_.truncate(string, string.length + 2), string); + strictEqual(_.trunc(string, string.length), string); + strictEqual(_.trunc(string, string.length + 2), string); }); test('should truncate string the given length', 1, function() { - strictEqual(_.truncate(string, 24), 'hi-diddly-ho there, n...'); + strictEqual(_.trunc(string, 24), 'hi-diddly-ho there, n...'); }); test('should support a `omission` option', 1, function() { - strictEqual(_.truncate(string, { 'omission': ' [...]' }), 'hi-diddly-ho there, neig [...]'); + strictEqual(_.trunc(string, { 'omission': ' [...]' }), 'hi-diddly-ho there, neig [...]'); }); test('should support a `length` option', 1, function() { - strictEqual(_.truncate(string, { 'length': 4 }), 'h...'); + strictEqual(_.trunc(string, { 'length': 4 }), 'h...'); }); test('should support a `separator` option', 2, function() { - strictEqual(_.truncate(string, { 'length': 24, 'separator': ' ' }), 'hi-diddly-ho there,...'); - strictEqual(_.truncate(string, { 'length': 24, 'separator': /,? +/ }), 'hi-diddly-ho there...'); + strictEqual(_.trunc(string, { 'length': 24, 'separator': ' ' }), 'hi-diddly-ho there,...'); + strictEqual(_.trunc(string, { 'length': 24, 'separator': /,? +/ }), 'hi-diddly-ho there...'); }); test('should treat negative `length` as `0`', 4, function() { _.each([0, -2], function(length) { - strictEqual(_.truncate(string, length), '...'); - strictEqual(_.truncate(string, { 'length': length }), '...'); + strictEqual(_.trunc(string, length), '...'); + strictEqual(_.trunc(string, { 'length': length }), '...'); }); }); test('should coerce `length` to a number', 4, function() { _.each(['', '4'], function(length, index) { var actual = index ? 'h...' : '...'; - strictEqual(_.truncate(string, length), actual); - strictEqual(_.truncate(string, { 'length': { 'valueOf': _.constant(length) } }), actual); + strictEqual(_.trunc(string, length), actual); + strictEqual(_.trunc(string, { 'length': { 'valueOf': _.constant(length) } }), actual); }); }); test('should coerce `string` to a string', 2, function() { - strictEqual(_.truncate(Object(string), 4), 'h...'); - strictEqual(_.truncate({ 'toString': _.constant(string) }, 5), 'hi...'); + strictEqual(_.trunc(Object(string), 4), 'h...'); + strictEqual(_.trunc({ 'toString': _.constant(string) }, 5), 'hi...'); }); }()); @@ -10747,7 +10747,7 @@ 'trim', 'trimLeft', 'trimRight', - 'truncate', + 'trunc', 'unescape' ]; From 1c3f9f7fbfac4509c1bafab950043f882607f5a2 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 13:06:06 -0400 Subject: [PATCH 0718/1608] Ensure tests that timeout are marked as errors. --- test/saucelabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index e08cf7ade4..829d91f9a7 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -417,7 +417,7 @@ function onJobStatus(error, res, body) { platform = options.platforms[0], description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]), elapsed = (_.now() - this.timestamp) / 1000, - errored = !jobResult || reError.test(message) || reError.test(jobStatus), + errored = !_.isObject(jobResult) || !jobResult.passed || reError.test(message) || reError.test(jobStatus), expired = (elapsed >= queueTimeout && !_.contains(jobStatus, 'in progress')), failures = _.result(jobResult, 'failed'), label = options.name + ':', From e3c121497143b9408a4e1e356fb783169b89bc81 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 13:15:32 -0400 Subject: [PATCH 0719/1608] Fix test stability. --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index cea191069c..37255bdbf5 100644 --- a/test/test.js +++ b/test/test.js @@ -9497,7 +9497,7 @@ setTimeout(function() { deepEqual(actual, expected); QUnit.start(); - }, 32); + }, 48); } else { skipTest(2); From e613198af7d8fb74b47ebc2add43c4d0420d42ea Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 14:58:08 -0400 Subject: [PATCH 0720/1608] Detect sauce error message in result. --- test/saucelabs.js | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 829d91f9a7..8dad1e4743 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -406,26 +406,29 @@ function onJobStart(error, res, body) { * @param {Object} body The response body JSON object. */ function onJobStatus(error, res, body) { + this.checking = false; + + if (!this.running || this.stopping) { + return; + } var completed = _.result(body, 'completed', false), data = _.first(_.result(body, 'js tests')), + elapsed = (_.now() - this.timestamp) / 1000, jobId = _.result(data, 'job_id', null), jobResult = _.result(data, 'result', null), jobStatus = _.result(data, 'status', ''), jobUrl = _.result(data, 'url', null), - options = this.options, - message = _.result(jobResult, 'message'), - platform = options.platforms[0], - description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]), - elapsed = (_.now() - this.timestamp) / 1000, - errored = !_.isObject(jobResult) || !jobResult.passed || reError.test(message) || reError.test(jobStatus), expired = (elapsed >= queueTimeout && !_.contains(jobStatus, 'in progress')), - failures = _.result(jobResult, 'failed'), - label = options.name + ':', - tunnel = this.tunnel; + options = this.options, + platform = options.platforms[0]; - this.checking = false; - if (!this.running || this.stopping) { - return; + if (_.isObject(jobResult)) { + var message = _.result(jobResult, 'message'); + } else { + if (typeof jobResult == 'string') { + message = jobResult; + } + jobResult = null; } if (isJobId(jobId)) { this.id = jobId; @@ -440,6 +443,12 @@ function onJobStatus(error, res, body) { this._pollerId = _.delay(_.bind(this.status, this), this.statusInterval * 1000); return; } + var description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]), + errored = !jobResult || !jobResult.passed || reError.test(message) || reError.test(jobStatus), + failures = _.result(jobResult, 'failed'), + label = options.name + ':', + tunnel = this.tunnel; + if (errored || failures) { if (errored && this.attempts < this.retries) { this.restart(); From fcc357ddd157c70a82313021483ae107631d9249 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 14:58:36 -0400 Subject: [PATCH 0721/1608] Source cleanup of `onJobStart`. --- test/saucelabs.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 8dad1e4743..85d3fa634c 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -368,14 +368,14 @@ function onJobReset() { * @param {Object} body The response body JSON object. */ function onJobStart(error, res, body) { - var statusCode = _.result(res, 'statusCode'), - taskId = _.first(_.result(body, 'js tests')), - tunnel = this.tunnel; - this.starting = false; + if (this.stopping) { return; } + var statusCode = _.result(res, 'statusCode'), + taskId = _.first(_.result(body, 'js tests')); + if (error || !taskId || statusCode != 200) { if (this.attempts < this.retries) { this.restart(); From e259f300b18b73a4c1a98fe1ab86d1f00eb05633 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 14:58:47 -0400 Subject: [PATCH 0722/1608] Remove unused fork in `baseAssign` and `baseMerge`. --- lodash.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lodash.js b/lodash.js index 5c777b30cf..d4c977e5a8 100644 --- a/lodash.js +++ b/lodash.js @@ -1138,9 +1138,6 @@ * @returns {Object} Returns the destination object. */ function baseAssign(object, source, callback) { - if (!object) { - return object; - } var index = -1, props = keys(source), length = props.length; @@ -1959,9 +1956,6 @@ * @returns {Object} Returns the destination object. */ function baseMerge(object, source, callback, stackA, stackB) { - if (!object) { - return object; - } (isArrayLike(source) ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { var isArr = srcValue && isArrayLike(srcValue), isObj = srcValue && isPlainObject(srcValue), From 2f9ba719d4dc0c1ac7b4fee35af7aa2afb29eaa8 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 15:24:36 -0400 Subject: [PATCH 0723/1608] Add clone tests for array buffers. --- lodash.js | 2 +- test/test.js | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lodash.js b/lodash.js index d4c977e5a8..4b31aba507 100644 --- a/lodash.js +++ b/lodash.js @@ -1221,7 +1221,7 @@ } switch (className) { case arrayBufferClass: - return value.slice(); + return value.slice(0); case boolClass: case dateClass: diff --git a/test/test.js b/test/test.js index 37255bdbf5..b5c0006601 100644 --- a/test/test.js +++ b/test/test.js @@ -19,6 +19,7 @@ var phantom = root.phantom, amd = root.define && define.amd, argv = root.process && process.argv, + ArrayBuffer = root.ArrayBuffer, document = !phantom && root.document, body = root.document && root.document.body, create = Object.create, @@ -1284,16 +1285,33 @@ _.each(typedArrays, function(type) { test('`_.' + methodName + '` should clone ' + type + ' arrays', 2, function() { - var Ctor = root[type] || Array, - buffer = Ctor == Array ? 4 : new ArrayBuffer(4), - array = new Ctor(buffer), - actual = func(array); + var Ctor = root[type]; + if (Ctor) { + var array = new Ctor(new ArrayBuffer(4)), + actual = func(array); - deepEqual(actual, array); - notStrictEqual(actual, array); + deepEqual(actual, array); + notStrictEqual(actual, array); + } + else { + skipTest(2); + } }); }); + test('`_.' + methodName + '` should clone array buffers', 2, function() { + if (ArrayBuffer) { + var buffer = new ArrayBuffer(4), + actual = func(buffer); + + strictEqual(actual.byteLength, buffer.byteLength); + notStrictEqual(actual, buffer); + } + else { + skipTest(2); + } + }); + test('`_.' + methodName + '` should clone problem JScript properties (test in IE < 9)', 2, function() { var actual = func(shadowedObject); deepEqual(actual, shadowedObject); From e9ab17fcb19a08780e808024093789f7303642a4 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 30 May 2014 15:44:11 -0400 Subject: [PATCH 0724/1608] Fix failing test. --- test/test.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/test.js b/test/test.js index b5c0006601..e210f6f9df 100644 --- a/test/test.js +++ b/test/test.js @@ -1300,10 +1300,9 @@ }); test('`_.' + methodName + '` should clone array buffers', 2, function() { - if (ArrayBuffer) { - var buffer = new ArrayBuffer(4), - actual = func(buffer); - + var buffer = ArrayBuffer && new ArrayBuffer(4); + if (buffer && buffer.slice) { + var actual = func(buffer); strictEqual(actual.byteLength, buffer.byteLength); notStrictEqual(actual, buffer); } From 62775105572ed3c23f14c0699a0271144736b515 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 31 May 2014 08:47:04 +0800 Subject: [PATCH 0725/1608] Use Markdown links formatting. [ci skip] --- lodash.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lodash.js b/lodash.js index 4b31aba507..9a2524a74e 100644 --- a/lodash.js +++ b/lodash.js @@ -194,10 +194,10 @@ * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * - * Backticks are escaped because in Internet Explorer < 9, they can be used - * to break out of attribute values or HTML comments. See - * , , and - * for more details. + * Backticks are escaped because in Internet Explorer < 9, they can be used to + * break out of attribute values or HTML comments. See [#102](http://html5sec.org/#102), + * [#108](http://html5sec.org/#108), and [#133](http://html5sec.org/#133) of + * the [HTML5 Security Cheatsheet](http://html5sec.org/) for more details. */ var htmlEscapes = { '&': '&', From baabdb4ac2b0da3c0ca6e79851925717db71d3c3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 28 May 2014 20:38:36 +0100 Subject: [PATCH 0726/1608] Updated README.md This commit adds links to Lo-Dash documentation under a specific "Documentation" heading, hopefully improving usability for users searching for the API docs. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7a9522e361..e58e7c87a1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # Lo-Dash v2.4.1 A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). +## Documentation +* **[Lo-Dash API Documentation](http://lodash.com/docs)** +* [DevDocs — *a fast, organised & searchable interface for our documentation*](http://devdocs.io/lodash/) + ## Download Check out our [wiki](https://github.com/lodash/lodash/wiki/build-differences) for details over the differences between builds. From 88726aff8c2b154383b286888b43b985a091032c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 31 May 2014 19:25:33 -0500 Subject: [PATCH 0727/1608] Update readme. [ ci skip] --- README.md | 131 ++++++++++++++++++++---------------------------------- 1 file changed, 47 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index e58e7c87a1..0d29cfd80d 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,61 @@ A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). ## Documentation -* **[Lo-Dash API Documentation](http://lodash.com/docs)** -* [DevDocs — *a fast, organised & searchable interface for our documentation*](http://devdocs.io/lodash/) +* [Lo-Dash API Documentation](http://lodash.com/docs) +* [DevDocs – *a fast, organised, & searchable interface for our documentation*](http://devdocs.io/lodash/) ## Download -Check out our [wiki](https://github.com/lodash/lodash/wiki/build-differences) for details over the differences between builds. +Review the [build differences](https://github.com/lodash/lodash/wiki/build-differences) & pick the build that’s right for you. -* [Modern build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js)) perfect for new environments
    (Chrome ≥ 14, Firefox ≥ 10, IE ≥ 9, Node.js, Opera ≥ 12, Safari ≥ 5.1) -* [Compatibility build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js)) for old environments too -* [Underscore build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js)) as a drop-in replacement for [Underscore v1.6.0](http://underscorejs.org/#1.6.0) - -CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash). For smaller file sizes, create [custom builds](http://lodash.com/custom-builds) with only the features needed. +* [Modern build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js))
    + For new environments like Chrome ≥ 14, Firefox ≥ 10, IE ≥ 9, Node.js, Opera ≥ 12, & Safari ≥ 5.1 +* [Compatibility build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js))
    + For new & old environments like IE ≤ 8 & PhantomJS +* [Underscore build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js))
    + A drop-in replacement for [Underscore v1.6.0](http://underscorejs.org/#1.6.0) +CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash).
    +Create [custom builds](http://lodash.com/custom-builds) with only the features you need.
    Love modules? We’ve got you covered with [lodash-amd](https://github.com/lodash/lodash-amd/tree/2.4.1), [lodash-es6](https://github.com/lodash/lodash-es6), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method. ## Dive in -There’s plenty of **[API documentation](http://lodash.com/docs)**, [unit tests](http://lodash.com/tests), & [benchmarks](http://lodash.com/benchmarks).
    -Check out DevDocs; a fast, organized, & searchable interface for our documentation. +Check out our [documentation](http://lodash.com/docs), [unit tests](http://lodash.com/tests), [benchmarks](http://lodash.com/benchmarks), [changelog](https://github.com/lodash/lodash/wiki/Changelog), [roadmap](https://github.com/lodash/lodash/wiki/Roadmap), as well as [community created podcasts, posts, & videos](https://github.com/lodash/lodash/wiki/Resources). + +## Installation + +In browsers: + +```html + +``` + +In an AMD loader: + +```js +require(['lodash'], function(_) {/*…*/}); +``` + +Using npm: -The full changelog for this release is available on our [wiki](https://github.com/lodash/lodash/wiki/Changelog).
    -A list of upcoming features is available on our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap). +```bash +$ npm i --save lodash + +$ {sudo -H} npm i -g lodash +$ npm ln lodash +``` + +In Node.js: + +```js +var _ = require('lodash'); +// or as Underscore +var _ = require('lodash-underscore'); +``` + +**Note:** +Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL ## Features *not* in Underscore @@ -79,81 +112,11 @@ A list of upcoming features is available on our [roadmap](https://github.com/lod * [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick), & [more](http://lodash.com/docs "_.assign, _.clone, _.cloneDeep, _.isEqual, _.merge") accept callbacks -## Resources - - * Podcasts - - [JavaScript Jabber](http://javascriptjabber.com/079-jsj-lo-dash-with-john-david-dalton/) - - * Posts - - [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/) - - [Custom builds in Lo-Dash 2.0](http://kitcambridge.be/blog/custom-builds-in-lo-dash-2-dot-0/) - - * Videos - - [Introduction](https://vimeo.com/44154599) - - [Origins](https://vimeo.com/44154600) - - [Optimizations & builds](https://vimeo.com/44154601) - - [Native method use](https://vimeo.com/48576012) - - [Testing](https://vimeo.com/45865290) - - [CascadiaJS ’12](http://www.youtube.com/watch?v=dpPy4f_SeEk) - - A list of other community created podcasts, posts, & videos is available on our [wiki](https://github.com/lodash/lodash/wiki/Resources). - ## Support -Tested in Chrome (19, 34-35), Firefox (3, 20, 28-29), IE 6-11, Opera (10, 12, 20-21), Safari 5-7, Node.js 0.6.21~0.10.28, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 34-35), Firefox (3, 20, 28-29), IE 6-11, Opera 20-21, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. -Automated browser test results [are available](https://saucelabs.com/u/lodash) as well as [Travis CI](https://travis-ci.org/) builds for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). - -Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing.
    -[![Sauce Labs](http://lodash.com/_img/sauce.png)](https://saucelabs.com/ "Sauce Labs: Selenium Testing & More") - -## Installation & usage - -In browsers: - -```html - -``` - -Using [`npm`](http://npmjs.org/): - -```bash -$ npm i --save lodash - -$ {sudo} npm i -g lodash -$ npm ln lodash -``` - -In [Node.js](http://nodejs.org/) & [Ringo](http://ringojs.org/): - -```js -var _ = require('lodash'); -// or as Underscore -var _ = require('lodash/dist/lodash.underscore'); -``` - -**Notes:** - * Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL - * If Lo-Dash is installed globally, run [`npm ln lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory *before* requiring it - -In [Rhino](http://www.mozilla.org/rhino/): - -```js -load('lodash.js'); -``` - -In an AMD loader: - -```js -require({ - 'packages': [ - { 'name': 'lodash', 'location': 'path/to/lodash', 'main': 'lodash' } - ] -}, -['lodash'], function(_) { - console.log(_.VERSION); -}); -``` +Automated browser test results [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. ## Author From 653aee8b073755682ed7fcefc804c9192e7ed8ea Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 31 May 2014 19:30:13 -0500 Subject: [PATCH 0728/1608] Update to version info to 2.5.0-pre. --- README.md | 2 +- bower.json | 2 +- component.json | 2 +- doc/README.md | 2 +- lodash.js | 4 ++-- package.json | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0d29cfd80d..90c00b5f6f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Lo-Dash v2.4.1 +# Lo-Dash v2.5.0-pre A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). ## Documentation diff --git a/bower.json b/bower.json index e40d243171..acfca13cfc 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "2.4.1", + "version": "2.5.0-pre", "main": "dist/lodash.compat.js", "ignore": [ ".*", diff --git a/component.json b/component.json index edd62a0b05..291094d09f 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "lodash", "repo": "lodash/lodash", - "version": "2.4.1", + "version": "2.5.0-pre", "description": "A utility library delivering consistency, customization, performance, & extras.", "license": "MIT", "main": "dist/lodash.compat.js", diff --git a/doc/README.md b/doc/README.md index 1a74f6f664..dc26641799 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,4 +1,4 @@ -# Lo-Dash v2.4.1 +# Lo-Dash v2.5.0-pre diff --git a/lodash.js b/lodash.js index 9a2524a74e..4a6c8a78ba 100644 --- a/lodash.js +++ b/lodash.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.4.1 + * Lo-Dash 2.5.0-pre * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 * Copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors @@ -20,7 +20,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.4.1'; + var version = '2.5.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; diff --git a/package.json b/package.json index bc6b8fa685..fc76501378 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "2.4.1", + "version": "2.5.0-pre", "description": "A utility library delivering consistency, customization, performance, & extras.", "homepage": "http://lodash.com/", "license": "MIT", From 257ac4d37e9db6a91736a4f41e704ab9235d7138 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 31 May 2014 19:30:27 -0500 Subject: [PATCH 0729/1608] Remove unused vendor files. --- doc/parse.php | 38 - vendor/docdown/LICENSE.txt | 20 - vendor/docdown/docdown.php | 38 - vendor/docdown/src/DocDown/Alias.php | 226 ------ vendor/docdown/src/DocDown/Entry.php | 456 ------------ .../docdown/src/DocDown/MarkdownGenerator.php | 648 ------------------ 6 files changed, 1426 deletions(-) delete mode 100644 doc/parse.php delete mode 100644 vendor/docdown/LICENSE.txt delete mode 100644 vendor/docdown/docdown.php delete mode 100644 vendor/docdown/src/DocDown/Alias.php delete mode 100644 vendor/docdown/src/DocDown/Entry.php delete mode 100644 vendor/docdown/src/DocDown/MarkdownGenerator.php diff --git a/doc/parse.php b/doc/parse.php deleted file mode 100644 index e1c9520689..0000000000 --- a/doc/parse.php +++ /dev/null @@ -1,38 +0,0 @@ -version; - - // generate Markdown - $markdown = docdown(array( - 'path' => '../' . $filePath, - 'title' => 'Lo-Dash v' . $version . '', - 'toc' => 'categories', - 'url' => 'https://github.com/lodash/lodash/blob/master/lodash.js' - )); - - // save to a `.md` file - file_put_contents($outputName . '.md', $markdown); - - // print - header('Content-Type: text/plain;charset=utf-8'); - echo $markdown . PHP_EOL; -?> \ No newline at end of file diff --git a/vendor/docdown/LICENSE.txt b/vendor/docdown/LICENSE.txt deleted file mode 100644 index 6cc7b220b3..0000000000 --- a/vendor/docdown/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2011-2014 John-David Dalton - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/docdown/docdown.php b/vendor/docdown/docdown.php deleted file mode 100644 index f031470d34..0000000000 --- a/vendor/docdown/docdown.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Available under MIT license - */ -require(dirname(__FILE__) . '/src/DocDown/MarkdownGenerator.php'); - -/** - * Generates Markdown from JSDoc entries in a given file. - * - * @param {Array} [$options=array()] The options array. - * @returns {string} The generated Markdown. - * @example - * - * // specify a file path - * $markdown = docdown(array( - * // path to js file - * 'path' => $filepath, - * // url used to reference line numbers in code - * 'url' => 'https://github.com/username/project/blob/master/my.js' - * )); - * - * // or pass raw js - * $markdown = docdown(array( - * // raw JavaScript source - * 'source' => $rawJS, - * // documentation title - * 'title' => 'My API Documentation', - * // url used to reference line numbers in code - * 'url' => 'https://github.com/username/project/blob/master/my.js' - * )); - */ -function docdown( $options = array() ) { - $gen = new MarkdownGenerator($options); - return $gen->generate(); -} -?> \ No newline at end of file diff --git a/vendor/docdown/src/DocDown/Alias.php b/vendor/docdown/src/DocDown/Alias.php deleted file mode 100644 index c04e55cbf2..0000000000 --- a/vendor/docdown/src/DocDown/Alias.php +++ /dev/null @@ -1,226 +0,0 @@ -owner = $owner; - $this->_name = $name; - $this->_call = $owner->getCall(); - $this->_category = $owner->getCategory(); - $this->_desc = $owner->getDesc(); - $this->_example = $owner->getExample(); - $this->_isCtor = $owner->isCtor(); - $this->_isLicense = $owner->isLicense(); - $this->_isPlugin = $owner->isPlugin(); - $this->_isPrivate = $owner->isPrivate(); - $this->_isStatic = $owner->isStatic(); - $this->_lineNumber = $owner->getLineNumber(); - $this->_members = $owner->getMembers(); - $this->_params = $owner->getParams(); - $this->_returns = $owner->getReturns(); - $this->_type = $owner->getType(); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Extracts the entry's `alias` objects. - * - * @memberOf Alias - * @param {number} $index The index of the array value to return. - * @returns {Array|string} The entry's `alias` objects. - */ - public function getAliases( $index = null ) { - $result = array(); - return $index !== null - ? @$result[$index] - : $result; - } - - /** - * Extracts the function call from the owner entry. - * - * @memberOf Alias - * @returns {string} The function call. - */ - public function getCall() { - return $this->_call; - } - - /** - * Extracts the owner entry's `category` data. - * - * @memberOf Alias - * @returns {string} The owner entry's `category` data. - */ - public function getCategory() { - return $this->_category; - } - - /** - * Extracts the owner entry's description. - * - * @memberOf Alias - * @returns {string} The owner entry's description. - */ - public function getDesc() { - return $this->_desc; - } - - /** - * Extracts the owner entry's `example` data. - * - * @memberOf Alias - * @returns {string} The owner entry's `example` data. - */ - public function getExample() { - return $this->_example; - } - - /** - * Checks if the entry is an alias. - * - * @memberOf Alias - * @returns {boolean} Returns `true`. - */ - public function isAlias() { - return true; - } - - /** - * Checks if the owner entry is a constructor. - * - * @memberOf Alias - * @returns {boolean} Returns `true` if a constructor, else `false`. - */ - public function isCtor() { - return $this->_isCtor; - } - - /** - * Checks if the owner entry is a license. - * - * @memberOf Alias - * @returns {boolean} Returns `true` if a license, else `false`. - */ - public function isLicense() { - return $this->_isLicense; - } - - /** - * Checks if the owner entry *is* assigned to a prototype. - * - * @memberOf Alias - * @returns {boolean} Returns `true` if assigned to a prototype, else `false`. - */ - public function isPlugin() { - return $this->_isPlugin; - } - - /** - * Checks if the owner entry is private. - * - * @memberOf Alias - * @returns {boolean} Returns `true` if private, else `false`. - */ - public function isPrivate() { - return $this->_isPrivate; - } - - /** - * Checks if the owner entry is *not* assigned to a prototype. - * - * @memberOf Alias - * @returns {boolean} Returns `true` if not assigned to a prototype, else `false`. - */ - public function isStatic() { - return $this->_isStatic; - } - - /** - * Resolves the owner entry's line number. - * - * @memberOf Alias - * @returns {number} The owner entry's line number. - */ - public function getLineNumber() { - return $this->_lineNumber; - } - - /** - * Extracts the owner entry's `member` data. - * - * @memberOf Alias - * @param {number} $index The index of the array value to return. - * @returns {Array|string} The owner entry's `member` data. - */ - public function getMembers( $index = null ) { - return $index !== null - ? @$this->_members[$index] - : $this->_members; - } - - /** - * Extracts the owner entry's `name` data. - * - * @memberOf Alias - * @returns {string} The owner entry's `name` data. - */ - public function getName() { - return $this->_name; - } - - /** - * Extracts the owner entry's `param` data. - * - * @memberOf Alias - * @param {number} $index The index of the array value to return. - * @returns {Array} The owner entry's `param` data. - */ - public function getParams( $index = null ) { - return $index !== null - ? @$this->_params[$index] - : $this->_params; - } - - /** - * Extracts the owner entry's `returns` data. - * - * @memberOf Alias - * @returns {string} The owner entry's `returns` data. - */ - public function getReturns() { - return $this->_returns; - } - - /** - * Extracts the owner entry's `type` data. - * - * @memberOf Alias - * @returns {string} The owner entry's `type` data. - */ - public function getType() { - return $this->_type; - } -} -?> \ No newline at end of file diff --git a/vendor/docdown/src/DocDown/Entry.php b/vendor/docdown/src/DocDown/Entry.php deleted file mode 100644 index 62d419e5d4..0000000000 --- a/vendor/docdown/src/DocDown/Entry.php +++ /dev/null @@ -1,456 +0,0 @@ -entry = $entry; - $this->lang = $lang; - $this->source = str_replace(PHP_EOL, "\n", $source); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Extracts the documentation entries from source code. - * - * @static - * @memberOf Entry - * @param {string} $source The source code. - * @returns {Array} The array of entries. - */ - public static function getEntries( $source ) { - preg_match_all('#/\*\*(?![-!])[\s\S]*?\*/\s*.+#', $source, $result); - return array_pop($result); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Checks if the entry is a function reference. - * - * @private - * @memberOf Entry - * @returns {boolean} Returns `true` if the entry is a function reference, else `false`. - */ - private function isFunction() { - if (!isset($this->_isFunction)) { - $this->_isFunction = !!( - $this->isCtor() || - count($this->getParams()) || - count($this->getReturns()) || - preg_match('/\*[\t ]*@function\b/', $this->entry) || - preg_match('#\*/\s*function #', $this->entry) - ); - } - return $this->_isFunction; - } - - /*--------------------------------------------------------------------------*/ - - /** - * Extracts the entry's `alias` objects. - * - * @memberOf Entry - * @param {number} $index The index of the array value to return. - * @returns {Array|string} The entry's `alias` objects. - */ - public function getAliases( $index = null ) { - if (!isset($this->_aliases)) { - preg_match('#\*[\t ]*@alias\s+(.+)#', $this->entry, $result); - - if (count($result)) { - $result = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result[1])); - $result = preg_split('/,\s*/', $result); - natsort($result); - - foreach ($result as $resultIndex => $value) { - $result[$resultIndex] = new Alias($value, $this); - } - } - $this->_aliases = $result; - } - return $index !== null - ? @$this->_aliases[$index] - : $this->_aliases; - } - - /** - * Extracts the function call from the entry. - * - * @memberOf Entry - * @returns {string} The function call. - */ - public function getCall() { - if (isset($this->_call)) { - return $this->_call; - } - - preg_match('#\*/\s*(?:function ([^(]*)|(.*?)(?=[:=,]|return\b))#', $this->entry, $result); - if ($result = array_pop($result)) { - $result = array_pop(explode('var ', trim(trim(array_pop(explode('.', $result))), "'"))); - } - // resolve name - // avoid $this->getName() because it calls $this->getCall() - preg_match('#\*[\t ]*@name\s+(.+)#', $this->entry, $name); - if (count($name)) { - $name = trim($name[1]); - } else { - $name = $result; - } - // compile function call syntax - if ($this->isFunction()) { - // compose parts - $result = array($result); - $params = $this->getParams(); - $paramNames = array(); - - foreach ($params as $param) { - // skip params that are properties of other params (e.g. `options.leading`) - preg_match('/\w+(?=\.[\w.]+)/', $param[1], $parentParam); - $parentParam = $parentParam[0]; - if (!in_array($parentParam, $paramNames)) { - $result[] = $param[1]; - } - $paramNames[] = preg_replace('/^\[|\]$/', '', $param[1]); - } - // format - $result = $name .'('. implode(array_slice($result, 1), ', ') .')'; - } - - $this->_call = $result ? $result : $name; - return $this->_call; - } - - /** - * Extracts the entry's `category` data. - * - * @memberOf Entry - * @returns {string} The entry's `category` data. - */ - public function getCategory() { - if (isset($this->_category)) { - return $this->_category; - } - - preg_match('#\*[\t ]*@category\s+(.+)#', $this->entry, $result); - if (count($result)) { - $result = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result[1])); - } else { - $result = $this->getType() == 'Function' ? 'Methods' : 'Properties'; - } - $this->_category = $result; - return $result; - } - - /** - * Extracts the entry's description. - * - * @memberOf Entry - * @returns {string} The entry's description. - */ - public function getDesc() { - if (isset($this->_desc)) { - return $this->_desc; - } - - preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result); - if (count($result)) { - $type = $this->getType(); - $result = preg_replace('/:\n[\t ]*\*[\t ]*/', ":
    \n", $result[1]); - $result = preg_replace('/(?:^|\n)[\t ]*\*\n[\t ]*\*[\t ]*/', "\n\n", $result); - $result = preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result); - $result = trim($result); - $result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result; - } - $this->_desc = $result; - return $result; - } - - /** - * Extracts the entry's `example` data. - * - * @memberOf Entry - * @returns {string} The entry's `example` data. - */ - public function getExample() { - if (isset($this->_example)) { - return $this->_example; - } - - preg_match('#\*[\t ]*@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result); - if (count($result)) { - $result = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', "\n", $result[1])); - $result = '```' . $this->lang . "\n" . $result . "\n```"; - } - $this->_example = $result; - return $result; - } - - /** - * Checks if the entry is an alias. - * - * @memberOf Entry - * @returns {boolean} Returns `false`. - */ - public function isAlias() { - return false; - } - - /** - * Checks if the entry is a constructor. - * - * @memberOf Entry - * @returns {boolean} Returns `true` if a constructor, else `false`. - */ - public function isCtor() { - if (!isset($this->_isCtor)) { - $this->_isCtor = !!preg_match('/\*[\t ]*@constructor\b/', $this->entry); - } - return $this->_isCtor; - } - - /** - * Checks if the entry is a license. - * - * @memberOf Entry - * @returns {boolean} Returns `true` if a license, else `false`. - */ - public function isLicense() { - if (!isset($this->_isLicense)) { - $this->_isLicense = !!preg_match('/\*[\t ]*@license\b/', $this->entry); - } - return $this->_isLicense; - } - - /** - * Checks if the entry *is* assigned to a prototype. - * - * @memberOf Entry - * @returns {boolean} Returns `true` if assigned to a prototype, else `false`. - */ - public function isPlugin() { - if (!isset($this->_isPlugin)) { - $this->_isPlugin = !$this->isCtor() && !$this->isPrivate() && !$this->isStatic(); - } - return $this->_isPlugin; - } - - /** - * Checks if the entry is private. - * - * @memberOf Entry - * @returns {boolean} Returns `true` if private, else `false`. - */ - public function isPrivate() { - if (!isset($this->_isPrivate)) { - $this->_isPrivate = $this->isLicense() || !!preg_match('/\*[\t ]*@private\b/', $this->entry) || !preg_match('/\*[\t ]*@[a-z]+\b/', $this->entry); - } - return $this->_isPrivate; - } - - /** - * Checks if the entry is *not* assigned to a prototype. - * - * @memberOf Entry - * @returns {boolean} Returns `true` if not assigned to a prototype, else `false`. - */ - public function isStatic() { - if (isset($this->_isStatic)) { - return $this->_isStatic; - } - - $public = !$this->isPrivate(); - $result = $public && !!preg_match('/\*[\t ]*@static\b/', $this->entry); - - // set in cases where it isn't explicitly stated - if ($public && !$result) { - if ($parent = array_pop(preg_split('/[#.]/', $this->getMembers(0)))) { - foreach (Entry::getEntries($this->source) as $entry) { - $entry = new Entry($entry, $this->source); - if ($entry->getName() == $parent) { - $result = !$entry->isCtor(); - break; - } - } - } else { - $result = true; - } - } - $this->_isStatic = $result; - return $result; - } - - /** - * Resolves the entry's line number. - * - * @memberOf Entry - * @returns {number} The entry's line number. - */ - public function getLineNumber() { - if (!isset($this->_lineNumber)) { - preg_match_all('/\n/', substr($this->source, 0, strrpos($this->source, $this->entry) + strlen($this->entry)), $lines); - $this->_lineNumber = count(array_pop($lines)) + 1; - } - return $this->_lineNumber; - } - - /** - * Extracts the entry's `member` data. - * - * @memberOf Entry - * @param {number} $index The index of the array value to return. - * @returns {Array|string} The entry's `member` data. - */ - public function getMembers( $index = null ) { - if (!isset($this->_members)) { - preg_match('#\*[\t ]*@member(?:Of)?\s+(.+)#', $this->entry, $result); - if (count($result)) { - $result = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result[1])); - $result = preg_split('/,\s*/', $result); - natsort($result); - } - $this->_members = $result; - } - return $index !== null - ? @$this->_members[$index] - : $this->_members; - } - - /** - * Extracts the entry's `name` data. - * - * @memberOf Entry - * @returns {string} The entry's `name` data. - */ - public function getName() { - if (isset($this->_name)) { - return $this->_name; - } - - preg_match('#\*[\t ]*@name\s+(.+)#', $this->entry, $result); - if (count($result)) { - $result = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result[1])); - } else { - $result = array_shift(explode('(', $this->getCall())); - } - $this->_name = $result; - return $result; - } - - /** - * Extracts the entry's `param` data. - * - * @memberOf Entry - * @param {number} $index The index of the array value to return. - * @returns {Array} The entry's `param` data. - */ - public function getParams( $index = null ) { - if (!isset($this->_params)) { - preg_match_all('#\*[\t ]*@param\s+\{\(?([^})]+)\)?\}\s+(\[.+\]|[$\w|]+(?:\[.+\])?)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $matchTuples); - $matchTuples = array_filter(array_slice($matchTuples, 1)); - $result = array(); - - if (count($matchTuples)) { - foreach ($matchTuples as $tupleKey => $tuple) { - foreach ($tuple as $key => $value) { - if (!isset($result[$key])) { - $result[$key] = array(); - } - $result[$key][] = $tupleKey - ? trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]*/', ' ', $value)) - : trim($value); - } - } - } - $this->_params = $result; - } - return $index !== null - ? @$this->_params[$index] - : $this->_params; - } - - /** - * Extracts the entry's `returns` data. - * - * @memberOf Entry - * @returns {string} The entry's `returns` data. - */ - public function getReturns() { - if (isset($this->_returns)) { - return $this->_returns; - } - - preg_match('#\*[\t ]*@returns\s+\{([^}]+)\}\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result); - if (count($result)) { - $result = array_map('trim', array_slice($result, 1)); - $result[0] = str_replace('|', ', ', $result[0]); - $result[1] = preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result[1]); - } - $this->_returns = $result; - return $result; - } - - /** - * Extracts the entry's `type` data. - * - * @memberOf Entry - * @returns {string} The entry's `type` data. - */ - public function getType() { - if (isset($this->_type)) { - return $this->_type; - } - - preg_match('#\*[\t ]*@type\s(?:\{\(?)?([^)}\n]+)#', $this->entry, $result); - if (count($result)) { - $result = trim($result[1]); - if (preg_match('/^(?:array|function|object|regexp)$/', $result)) { - $result = ucfirst($result); - } - } else { - $result = $this->isFunction() ? 'Function' : 'unknown'; - } - $this->_type = $result; - return $result; - } -} -?> \ No newline at end of file diff --git a/vendor/docdown/src/DocDown/MarkdownGenerator.php b/vendor/docdown/src/DocDown/MarkdownGenerator.php deleted file mode 100644 index fd7fc15c0f..0000000000 --- a/vendor/docdown/src/DocDown/MarkdownGenerator.php +++ /dev/null @@ -1,648 +0,0 @@ -\n"; - - /** - * An array of JSDoc entries. - * - * @memberOf MarkdownGenerator - * @type Array - */ - public $entries = array(); - - /** - * The HTML for the open tag. - * - * @memberOf MarkdownGenerator - * @type string - */ - public $openTag = "\n\n"; - - /** - * An options array used to configure the generator. - * - * @memberOf MarkdownGenerator - * @type Array - */ - public $options = array(); - - /** - * The file's source code. - * - * @memberOf MarkdownGenerator - * @type string - */ - public $source = ''; - - /** - * The array of code snippets that are tokenized by `escape`. - * - * @private - * @memberOf MarkdownGenerator - * @type Array - */ - private $snippets = array(); - - /*--------------------------------------------------------------------------*/ - - /** - * The MarkdownGenerator constructor. - * - * @constructor - * @param {string} $source The source code to parse. - * @param {Array} $options The options array. - */ - public function __construct( $source, $options = array() ) { - // juggle arguments - if (is_array($source)) { - $options = $source; - } else { - $options['source'] = $source; - } - if (isset($options['source']) && realpath($options['source'])) { - $options['path'] = $options['source']; - } - if (isset($options['path'])) { - preg_match('/(?<=\.)[a-z]+$/', $options['path'], $ext); - $options['source'] = file_get_contents($options['path']); - $ext = array_pop($ext); - - if (!isset($options['lang']) && $ext) { - $options['lang'] = $ext; - } - if (!isset($options['title'])) { - $options['title'] = ucfirst(basename($options['path'])) . ' API documentation'; - } - } - if (!isset($options['lang'])) { - $options['lang'] = 'js'; - } - if (!isset($options['toc'])) { - $options['toc'] = 'properties'; - } - - $this->options = $options; - $this->source = str_replace(PHP_EOL, "\n", $options['source']); - $this->entries = Entry::getEntries($this->source); - - foreach ($this->entries as $index => $value) { - $this->entries[$index] = new Entry($value, $this->source, $options['lang']); - } - } - - /*--------------------------------------------------------------------------*/ - - /** - * Performs common string formatting operations. - * - * @private - * @static - * @memberOf MarkdownGenerator - * @param {string} $string The string to format. - * @returns {string} The formatted string. - */ - private static function format( $string ) { - $counter = 0; - - // tokenize inline code snippets - preg_match_all('/`[^`]+`/', $string, $tokenized); - $tokenized = $tokenized[0]; - foreach ($tokenized as $snippet) { - $string = str_replace($snippet, '__token' . ($counter++) .'__', $string); - } - - // italicize parentheses - $string = preg_replace('/(^|\s)(\([^)]+\))/', '$1*$2*', $string); - - // mark numbers as inline code - $string = preg_replace('/[\t ](-?\d+(?:.\d+)?)(?!\.[^\n])/', ' `$1`', $string); - - // detokenize inline code snippets - $counter = 0; - foreach ($tokenized as $snippet) { - $string = str_replace('__token' . ($counter++) . '__', $snippet, $string); - } - - return trim($string); - } - - /** - * Modify a string by replacing named tokens with matching assoc. array values. - * - * @private - * @static - * @memberOf MarkdownGenerator - * @param {string} $string The string to modify. - * @param {Array|Object} $object The template object. - * @returns {string} The modified string. - */ - private static function interpolate( $string, $object ) { - preg_match_all('/#\{([^}]+)\}/', $string, $tokens); - $tokens = array_unique(array_pop($tokens)); - - foreach ($tokens as $token) { - $pattern = '/#\{' . preg_replace('/([.*+?^${}()|[\]\\\])/', '\\\$1', $token) . '\}/'; - $replacement = ''; - - if (is_object($object)) { - preg_match('/\(([^)]+?)\)$/', $token, $args); - $args = preg_split('/,\s*/', array_pop($args)); - $method = 'get' . ucfirst(preg_replace('/\([^)]+?\)$/', '', $token)); - - if (method_exists($object, $method)) { - $replacement = (string) call_user_func_array(array($object, $method), $args); - } else if (isset($object->{$token})) { - $replacement = (string) $object->{$token}; - } - } else if (isset($object[$token])) { - $replacement = (string) $object[$token]; - } - $string = preg_replace($pattern, trim($replacement), $string); - } - return MarkdownGenerator::format($string); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Adds the given `$entries` to the `$result` array. - * - * @private - * @memberOf MarkdownGenerator - * @param {Array} $result The result array to modify. - * @param {Array} $entries The entries to add to the `$result`. - */ - private function addEntries( &$result, $entries ) { - foreach ($entries as $entry) { - // skip aliases - if ($entry->isAlias()) { - continue; - } - // name and description - array_push( - $result, - $this->openTag, - MarkdownGenerator::interpolate("### `#{member}#{separator}#{call}`\n# [Ⓢ](#{href} \"View in source\") [Ⓣ][1]\n\n#{desc}", array( - 'call' => $entry->getCall(), - 'desc' => $this->escape($entry->getDesc()), - 'hash' => $entry->hash, - 'href' => $entry->href, - 'member' => $entry->member, - 'separator' => $entry->separator - )) - ); - - // @alias - if (count($aliases = $entry->getAliases())) { - array_push($result, '', '#### Aliases'); - foreach ($aliases as $index => $alias) { - $aliases[$index] = MarkdownGenerator::interpolate('#{member}#{separator}#{name}', $alias); - } - $result[] = '*' . implode(', ', $aliases) . '*'; - } - // @param - if (count($params = $entry->getParams())) { - array_push($result, '', '#### Arguments'); - foreach ($params as $index => $param) { - $result[] = MarkdownGenerator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array( - 'desc' => $this->escape($param[2]), - 'name' => $param[1], - 'num' => $index + 1, - 'type' => $this->escape($param[0]) - )); - } - } - // @returns - if (count($returns = $entry->getReturns())) { - array_push( - $result, '', - '#### Returns', - MarkdownGenerator::interpolate('(#{type}): #{desc}', array( - 'desc' => $this->escape($returns[1]), - 'type' => $this->escape($returns[0]) - )) - ); - } - // @example - if ($example = $entry->getExample()) { - array_push($result, '', '#### Example', $example); - } - array_push($result, "\n* * *", $this->closeTag); - } - } - - /** - * Escapes special Markdown characters. - * - * @private - * @memberOf Entry - * @param {string} $string The string to escape. - * @returns {string} Returns the escaped string. - */ - private function escape( $string ) { - $string = preg_replace_callback('/`.*?\`/', array($this, 'swapSnippetsToTokens'), $string); - $string = preg_replace('/(?entries[$entry] : $entry; - $member = !$member ? $entry->getMembers(0) : $member; - - $result = ($member ? $member . ($entry->isPlugin() ? 'prototype' : '') : '') . $entry->getCall(); - $result = preg_replace('/\(\[|\[\]/', '', $result); - $result = preg_replace('/[\t =|\'"{}.()\]]/', '', $result); - $result = preg_replace('/[\[#,]+/', '-', $result); - return strtolower($result); - } - - /** - * Resolves the entry's url for the specific line number. - * - * @private - * @memberOf MarkdownGenerator - * @param {number|Object} $entry The entry object. - * @returns {string} The url. - */ - private function getLineUrl( $entry ) { - $entry = is_numeric($entry) ? $this->entries($entry) : $entry; - return $this->options['url'] . '#L' . $entry->getLineNumber(); - } - - /** - * Extracts the character used to separate the entry's name from its member. - * - * @private - * @memberOf MarkdownGenerator - * @param {number|Object} $entry The entry object. - * @returns {string} The separator. - */ - private function getSeparator( $entry ) { - $entry = is_numeric($entry) ? $this->entries($entry) : $entry; - return $entry->isPlugin() ? '.prototype.' : '.'; - } - - /** - * Swaps code snippets with tokens as a `preg_replace_callback` callback - * used by `escape`. - * - * @private - * @memberOf Entry - * @param {Array} $matches The array of regexp matches. - * @returns {string} Returns the token. - */ - private function swapSnippetsToTokens( $matches ) { - $this->snippets[] = $matches[0]; - return '@@token@@'; - } - - /** - * Swaps tokens with code snippets as a `preg_replace_callback` callback - * used by `escape`. - * - * @private - * @memberOf Entry - * @returns {string} Returns the code snippet. - */ - private function swapTokensToSnippets() { - return array_shift($this->snippets); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Generates Markdown from JSDoc entries. - * - * @memberOf MarkdownGenerator - * @returns {string} The rendered Markdown. - */ - public function generate() { - $api = array(); - $byCategory = $this->options['toc'] == 'categories'; - $categories = array(); - $closeTag = $this->closeTag; - $compiling = false; - $openTag = $this->openTag; - $result = array('# ' . $this->options['title']); - $toc = 'toc'; - - // initialize $api array - foreach ($this->entries as $entry) { - // skip invalid or private entries - $name = $entry->getName(); - if (!$name || $entry->isPrivate()) { - continue; - } - - $members = $entry->getMembers(); - $members = count($members) ? $members : array(''); - - foreach ($members as $member) { - // create api category arrays - if ($member && !isset($api[$member])) { - // create temporary entry to be replaced later - $api[$member] = new stdClass; - $api[$member]->static = array(); - $api[$member]->plugin = array(); - } - - // append entry to api member - if (!$member || $entry->isCtor() || ($entry->getType() == 'Object' && - !preg_match('/[=:]\s*(?:null|undefined)\s*[,;]?$/', $entry->entry))) { - - // assign the real entry, replacing the temporary entry if it exist - $member = ($member ? $member . ($entry->isPlugin() ? '#' : '.') : '') . $name; - $entry->static = @$api[$member] ? $api[$member]->static : array(); - $entry->plugin = @$api[$member] ? $api[$member]->plugin : array(); - - $api[$member] = $entry; - foreach ($entry->getAliases() as $alias) { - $api[$member]->static[] = $alias; - } - } - else if ($entry->isStatic()) { - $api[$member]->static[] = $entry; - foreach ($entry->getAliases() as $alias) { - $api[$member]->static[] = $alias; - } - } - else if (!$entry->isCtor()) { - $api[$member]->plugin[] = $entry; - foreach ($entry->getAliases() as $alias) { - $api[$member]->plugin[] = $alias; - } - } - } - } - - // add properties to each entry - foreach ($api as $entry) { - $entry->hash = $this->getHash($entry); - $entry->href = $this->getLineUrl($entry); - $entry->separator = ''; - - $member = $entry->getMembers(0); - $member = ($member ? $member . $this->getSeparator($entry) : '') . $entry->getName(); - $entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member); - - // add properties to static and plugin sub-entries - foreach (array('static', 'plugin') as $kind) { - foreach ($entry->{$kind} as $subentry) { - $subentry->hash = $this->getHash($subentry); - $subentry->href = $this->getLineUrl($subentry); - $subentry->member = $member; - $subentry->separator = $this->getSeparator($subentry); - } - } - } - - /*------------------------------------------------------------------------*/ - - // custom sort for root level entries - // TODO: see how well it handles deeper namespace traversal - function sortCompare($a, $b) { - $score = array( 'a' => 0, 'b' => 0); - foreach (array( 'a' => $a, 'b' => $b) as $key => $value) { - // capitalized properties are last - if (preg_match('/[#.][A-Z]/', $value)) { - $score[$key] = 0; - } - // lowercase prototype properties are next to last - else if (preg_match('/#[a-z]/', $value)) { - $score[$key] = 1; - } - // lowercase static properties next to first - else if (preg_match('/\.[a-z]/', $value)) { - $score[$key] = 2; - } - // root properties are first - else if (preg_match('/^[^#.]+$/', $value)) { - $score[$key] = 3; - } - } - $score = $score['b'] - $score['a']; - return $score ? $score : strcasecmp($a, $b); - } - - uksort($api, 'sortCompare'); - - // sort static and plugin sub-entries - foreach ($api as $entry) { - foreach (array('static', 'plugin') as $kind) { - $sortBy = array( 'a' => array(), 'b' => array(), 'c' => array() ); - foreach ($entry->{$kind} as $subentry) { - $name = $subentry->getName(); - // functions w/o ALL-CAPs names are last - $sortBy['a'][] = $subentry->getType() == 'Function' && !preg_match('/^[A-Z_]+$/', $name); - // ALL-CAPs properties first - $sortBy['b'][] = preg_match('/^[A-Z_]+$/', $name); - // lowercase alphanumeric sort - $sortBy['c'][] = strtolower($name); - } - array_multisort($sortBy['a'], SORT_ASC, $sortBy['b'], SORT_DESC, $sortBy['c'], SORT_ASC, $entry->{$kind}); - } - } - - /*------------------------------------------------------------------------*/ - - // add categories - foreach ($api as $entry) { - $categories[$entry->getCategory()][] = $entry; - foreach (array('static', 'plugin') as $kind) { - foreach ($entry->{$kind} as $subentry) { - $categories[$subentry->getCategory()][] = $subentry; - } - } - } - - // sort categories - ksort($categories); - - foreach(array('Methods', 'Properties') as $category) { - if (isset($categories[$category])) { - $entries = $categories[$category]; - unset($categories[$category]); - $categories[$category] = $entries; - } - } - - /*------------------------------------------------------------------------*/ - - // compile TOC - $result[] = $openTag; - - // compile TOC by categories - if ($byCategory) { - foreach ($categories as $category => $entries) { - if ($compiling) { - $result[] = $closeTag; - } else { - $compiling = true; - } - // assign TOC hash - if (count($result) == 2) { - $toc = strtolower($category); - } - // add category - array_push( - $result, - $openTag, '## ' . (count($result) == 2 ? '' : '') . '`' . $category . '`' - ); - // add entries - foreach ($entries as $entry) { - if ($entry->isAlias()) { - $result[] = MarkdownGenerator::interpolate('* `#{member}#{separator}#{name}` -> `#{realName}`', array( - 'hash' => $entry->hash, - 'member' => $entry->member, - 'name' => $entry->getName(), - 'realName' => $entry->owner->getName(), - 'separator' => $entry->separator - )); - } - else { - $result[] = MarkdownGenerator::interpolate('* `#{member}#{separator}#{name}`', $entry); - } - } - } - } - // compile TOC by namespace - else { - foreach ($api as $entry) { - if ($compiling) { - $result[] = $closeTag; - } else { - $compiling = true; - } - $member = $entry->member . $entry->getName(); - - // assign TOC hash - if (count($result) == 2) { - $toc = $member; - } - // add root entry - array_push( - $result, - $openTag, '## ' . (count($result) == 2 ? '' : '') . '`' . $member . '`', - MarkdownGenerator::interpolate('* [`' . $member . '`](##{hash})', $entry) - ); - - // add static and plugin sub-entries - foreach (array('static', 'plugin') as $kind) { - if ($kind == 'plugin' && count($entry->plugin)) { - array_push( - $result, - $closeTag, - $openTag, - '## `' . $member . ($entry->isCtor() ? '.prototype`' : '`') - ); - } - foreach ($entry->{$kind} as $subentry) { - $subentry->member = $member; - if ($subentry->isAlias()) { - $result[] = MarkdownGenerator::interpolate('* `#{member}#{separator}#{name}` -> `#{realName}`', array( - 'hash' => $subentry->hash, - 'member' => $subentry->member, - 'name' => $subentry->getName(), - 'realName' => $subentry->owner->getName(), - 'separator' => $subentry->separator - )); - } - else { - $result[] = MarkdownGenerator::interpolate('* `#{member}#{separator}#{name}`', $subentry); - } - } - } - } - } - - array_push($result, $closeTag, $closeTag); - - /*------------------------------------------------------------------------*/ - - // compile content - $compiling = false; - $result[] = $openTag; - - if ($byCategory) { - foreach ($categories as $category => $entries) { - if ($compiling) { - $result[] = $closeTag; - } else { - $compiling = true; - } - if ($category != 'Methods' && $category != 'Properties') { - $category = '“' . $category . '” Methods'; - } - array_push($result, $openTag, '## `' . $category . '`'); - $this->addEntries($result, $entries); - } - } - else { - foreach ($api as $entry) { - // skip aliases - if ($entry->isAlias()) { - continue; - } - if ($compiling) { - $result[] = $closeTag; - } else { - $compiling = true; - } - // add root entry name - $member = $entry->member . $entry->getName(); - array_push($result, $openTag, '## `' . $member . '`'); - - foreach (array($entry, 'static', 'plugin') as $kind) { - $subentries = is_string($kind) ? $entry->{$kind} : array($kind); - - // add sub-entry name - if ($kind != 'static' && $entry->getType() != 'Object' && - count($subentries) && $subentries[0] != $kind) { - if ($kind == 'plugin') { - $result[] = $closeTag; - } - array_push( - $result, - $openTag, - '## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`') - ); - } - $this->addEntries($result, $subentries); - } - } - } - - // close tags add TOC link reference - array_push($result, $closeTag, $closeTag, '', ' [1]: #' . $toc . ' "Jump back to the TOC."'); - - // cleanup whitespace - return trim(preg_replace('/[\t ]+\n/', "\n", join($result, "\n"))); - } -} -?> \ No newline at end of file From 0c89a8f145421ee529472aca604cd1b6215b85a2 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 31 May 2014 19:57:37 -0500 Subject: [PATCH 0730/1608] Remove narwhal from travis.yml testing. --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3981fa7d43..4e25e67b6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,6 @@ matrix: env: ISTANBUL=true BUILD="modern" - node_js: "0.10" env: BIN="phantomjs" BUILD="compat" - - node_js: "0.10" - env: BIN="narwhal" BUILD="compat" - node_js: "0.10" env: BIN="rhino" BUILD="compat" - node_js: "0.10" @@ -39,8 +37,6 @@ before_install: - "mkdir ~/.npm" - "[ $SAUCE_LABS == false ] || npm i chalk@\"^0.4.0\" ecstatic@\"^0.5.0\" request@\"^2.34.0\" sauce-tunnel@\"^2.0.0\"" - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.10.0\" && npm i istanbul@\"^0.2.0\")" - - "[ $BIN != 'narwhal' ] || (wget http://lodash.com/_travis/narwhal-0.3.2.zip && sudo unzip narwhal-0.3.2 -d /opt/ && rm narwhal-0.3.2.zip)" - - "[ $BIN != 'narwhal' ] || (sudo ln -s /opt/narwhal-0.3.2/bin/narwhal /usr/local/bin/narwhal && sudo chmod +x /usr/local/bin/narwhal)" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7R5 && sudo wget -O /opt/rhino-1.7R5/js.jar http://lodash.com/_travis/rhino-1.7R5.jar)" - "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7R5/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)" - "[ $BIN != 'ringo' ] || (wget http://lodash.com/_travis/ringojs-0.9.zip && sudo unzip ringojs-0.9 -d /opt && rm ringojs-0.9.zip)" From 8373d31013c92427b2402a1d87264791612aeb50 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 1 Jun 2014 14:26:16 -0700 Subject: [PATCH 0731/1608] Cleanup readme. [ci skip] --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 90c00b5f6f..29e6ef30e9 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). ## Documentation -* [Lo-Dash API Documentation](http://lodash.com/docs) -* [DevDocs – *a fast, organised, & searchable interface for our documentation*](http://devdocs.io/lodash/) +* [API Documentation](http://lodash.com/docs) +* [DevDocs – *a fast, organized, & searchable interface for our documentation*](http://devdocs.io/lodash/) ## Download @@ -22,7 +22,7 @@ Love modules? We’ve got you covered with [lodash-amd](https://github.com/lodas ## Dive in -Check out our [documentation](http://lodash.com/docs), [unit tests](http://lodash.com/tests), [benchmarks](http://lodash.com/benchmarks), [changelog](https://github.com/lodash/lodash/wiki/Changelog), [roadmap](https://github.com/lodash/lodash/wiki/Roadmap), as well as [community created podcasts, posts, & videos](https://github.com/lodash/lodash/wiki/Resources). +Check out our [unit tests](http://lodash.com/tests), [benchmarks](http://lodash.com/benchmarks), [changelog](https://github.com/lodash/lodash/wiki/Changelog), [roadmap](https://github.com/lodash/lodash/wiki/Roadmap), as well as [community created podcasts, posts, & videos](https://github.com/lodash/lodash/wiki/Resources). ## Installation @@ -116,7 +116,7 @@ Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl Tested in Chrome (19, 34-35), Firefox (3, 20, 28-29), IE 6-11, Opera 20-21, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. -Automated browser test results [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. +Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. ## Author From 10419366f959804020a0b80b86f6a9505657160c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 1 Jun 2014 20:00:31 -0700 Subject: [PATCH 0732/1608] Rename `num` to `n` in doc examples. [ci skip] --- lodash.js | 106 +++++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 61 deletions(-) diff --git a/lodash.js b/lodash.js index 4a6c8a78ba..ab3c28109c 100644 --- a/lodash.js +++ b/lodash.js @@ -754,15 +754,11 @@ * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value - * wrapped.reduce(function(sum, num) { - * return sum + num; - * }); + * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value - * var squares = wrapped.map(function(num) { - * return num * num; - * }); + * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false @@ -2735,9 +2731,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.dropRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); + * _.dropRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [1] * * var characters = [ @@ -2778,9 +2772,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.dropWhile([1, 2, 3], function(num) { - * return num < 3; - * }); + * _.dropWhile([1, 2, 3], function(n) { return n < 3; }); * // => [3] * * var characters = [ @@ -3302,7 +3294,7 @@ * @example * * var array = [1, 2, 3, 4]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * var evens = _.remove(array, function(n) { return n % 2 == 0; }); * * console.log(array); * // => [1, 3] @@ -3542,9 +3534,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.takeRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); + * _.takeRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [2, 3] * * var characters = [ @@ -3585,9 +3575,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.takeWhile([1, 2, 3], function(num) { - * return num < 3; - * }); + * _.takeWhile([1, 2, 3], function(n) { return n < 3; }); * // => [1, 2] * * var characters = [ @@ -3652,20 +3640,20 @@ * @returns {Array} Returns the new duplicate-value-free array. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] + * _.uniq([1, 2, 1]); + * // => [1, 2] * * // using `isSorted` - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] + * _.uniq([1, 1, 2], true); + * // => [1, 2] * * // using `callback` - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] + * _.uniq(['A', 'b', 'a', 'B'], function(chr) { return chr.toLowerCase(); }); + * // => ['A', 'b'] * * // using `callback` with `thisArg` - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] + * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); + * // => [1, 2.5] * * // using "_.pluck" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); @@ -4037,10 +4025,10 @@ * @returns {Object} Returns the composed aggregate object. * @example * - * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * - * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); @@ -4139,7 +4127,7 @@ * @returns {Array} Returns the new filtered array. * @example * - * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [2, 4] * * var characters = [ @@ -4246,9 +4234,7 @@ * @returns {*} Returns the matched element, else `undefined`. * @example * - * _.findLast([1, 2, 3, 4], function(num) { - * return num % 2 == 1; - * }); + * _.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1; }); * // => 3 */ function findLast(collection, predicate, thisArg) { @@ -4304,10 +4290,10 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEach(function(n) { console.log(n); }).join(','); * // => logs each number and returns '1,2,3' * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { console.log(n); }); * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { @@ -4330,7 +4316,7 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each number from right to left and returns '3,2,1' */ function forEachRight(collection, callback, thisArg) { @@ -4364,10 +4350,10 @@ * @returns {Object} Returns the composed aggregate object. * @example * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using "_.pluck" callback shorthand @@ -4475,10 +4461,10 @@ * @returns {Array} Returns the new mapped array. * @example * - * _.map([1, 2, 3], function(num) { return num * 3; }); + * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); * // => [3, 6, 9] (property order is not guaranteed across environments) * * var characters = [ @@ -4685,10 +4671,10 @@ * @returns {Array} Returns the array of grouped elements. * @example * - * _.partition([1, 2, 3], function(num) { return num % 2; }); + * _.partition([1, 2, 3], function(n) { return n % 2; }); * // => [[1, 3], [2]] * - * _.partition([1.2, 2.3, 3.4], function(num) { return this.floor(num) % 2; }, Math); + * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); * // => [[1, 3], [2]] * * var characters = [ @@ -4751,13 +4737,11 @@ * @returns {*} Returns the accumulated value. * @example * - * var sum = _.reduce([1, 2, 3], function(sum, num) { - * return sum + num; - * }); + * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * - * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } @@ -4839,7 +4823,7 @@ * @returns {Array} Returns the new filtered array. * @example * - * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [1, 3] * * var characters = [ @@ -5042,10 +5026,10 @@ * @returns {Array} Returns the new sorted array. * @example * - * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * - * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * * var characters = [ @@ -5687,8 +5671,8 @@ * @returns {Function} Returns the new function. * @example * - * function isEven(num) { - * return num % 2 == 0; + * function isEven(n) { + * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); @@ -6263,7 +6247,7 @@ * @returns {Object} Returns `object`. * @example * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) @@ -6288,7 +6272,7 @@ * @returns {Object} Returns `object`. * @example * - * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' @@ -7030,7 +7014,7 @@ * @returns {Object} Returns the new mapped object. * @example * - * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); + * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(n) { return n * 3; }); * // => { 'a': 3, 'b': 6, 'c': 9 } * * var characters = { @@ -7229,16 +7213,16 @@ * @returns {*} Returns the accumulated value. * @example * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; + * var squares = _.transform([1, 2, 3, 4, 5, 6], function(result, n) { + * n *= n; + * if (n % 2) { + * return result.push(n) < 3; * } * }); * // => [1, 9, 25] * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ From 35a0756e5adf1c07407bb4e98f93bbb3075b685c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 1 Jun 2014 23:02:23 -0700 Subject: [PATCH 0733/1608] Add fallback for `ArrayBuffer#slice`. --- lodash.js | 48 ++++++++++++++++++++++++++++++++++++++++-------- test/test.js | 2 +- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/lodash.js b/lodash.js index ab3c28109c..bb70bf7862 100644 --- a/lodash.js +++ b/lodash.js @@ -100,9 +100,10 @@ /** Used to assign default `context` object properties */ var contextProps = [ - 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', - 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', - 'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError' + 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Error', 'Float64Array', 'Function', + 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', + 'document', 'isFinite', 'isNaN','parseInt', 'setTimeout', 'TypeError', + 'Uint8Array', 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ @@ -625,8 +626,8 @@ /** Used to detect DOM support */ var document = (document = context.window) && document.document; - /** Used to restore the original `_` reference in `_.noConflict` */ - var oldDash = context._; + /** Used to resolve the decompiled source of functions */ + var fnToString = Function.prototype.toString; /** * Used as the maximum length of an array-like object. @@ -635,6 +636,9 @@ */ var maxSafeInteger = Math.pow(2, 53) - 1; + /** Used to restore the original `_` reference in `_.noConflict` */ + var oldDash = context._; + /** Used to resolve the internal `[[Class]]` of values */ var toString = objectProto.toString; @@ -645,10 +649,12 @@ ); /** Native method shortcuts */ - var ceil = Math.ceil, + var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, + bufferSlice = isNative(bufferSlice = ArrayBuffer && (new ArrayBuffer).slice) && bufferSlice, + ceil = Math.ceil, clearTimeout = context.clearTimeout, + Float64Array = isNative(Float64Array = context.Float64Array) && Float64Array, floor = Math.floor, - fnToString = Function.prototype.toString, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, @@ -656,6 +662,7 @@ Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, unshift = arrayProto.unshift; /** Used to set metadata on functions */ @@ -1217,7 +1224,7 @@ } switch (className) { case arrayBufferClass: - return value.slice(0); + return cloneBuffer(value); case boolClass: case dateClass: @@ -2514,6 +2521,31 @@ return typeof value == 'function' && reNative.test(fnToString.call(value)); } + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneBuffer(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + cloneBuffer = !(ArrayBuffer && Float64Array && Uint8Array) ? identity : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = floor(byteLength / 8), + offset = floatLength * 8, + result = new ArrayBuffer(byteLength), + resultView = new Float64Array(result, 0, floatLength); + + resultView.set(new Float64Array(buffer, 0, floatLength)); + resultView = new Uint8Array(result, offset); + resultView.set(new Uint8Array(buffer, offset)); + return result; + }; + } + /** * Sets wrapper metadata on a given function. * diff --git a/test/test.js b/test/test.js index e210f6f9df..3fc3df1335 100644 --- a/test/test.js +++ b/test/test.js @@ -1301,7 +1301,7 @@ test('`_.' + methodName + '` should clone array buffers', 2, function() { var buffer = ArrayBuffer && new ArrayBuffer(4); - if (buffer && buffer.slice) { + if (buffer) { var actual = func(buffer); strictEqual(actual.byteLength, buffer.byteLength); notStrictEqual(actual, buffer); From 3d93ed9059ef5b3be16e2407ffdab82a6d80863d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 2 Jun 2014 08:08:35 -0700 Subject: [PATCH 0734/1608] Fix failing tests in Safari > 5. --- lodash.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index bb70bf7862..3672b15fe5 100644 --- a/lodash.js +++ b/lodash.js @@ -64,6 +64,9 @@ /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; + /** Used to detect host constructors (Safari > 5) */ + var reHostCtor = /^\[object .+?Constructor\]$/; + /** Used to match latin-1 supplement letters */ var reLatin1 = /[\xC0-\xFF]/g; @@ -2518,7 +2521,10 @@ * @returns {boolean} Returns `true` if `value` is a native function, else `false`. */ function isNative(value) { - return typeof value == 'function' && reNative.test(fnToString.call(value)); + var type = typeof value; + return type == 'function' + ? reNative.test(fnToString.call(value)) + : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; } /** From b41826c332f96939894621f2baeb782b677a1d34 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 2 Jun 2014 09:28:45 -0700 Subject: [PATCH 0735/1608] Fixed `cloneBuffer` in PhantomJS. --- lodash.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lodash.js b/lodash.js index 3672b15fe5..8ce21c526b 100644 --- a/lodash.js +++ b/lodash.js @@ -2538,16 +2538,21 @@ return bufferSlice.call(buffer, 0); } if (!bufferSlice) { - cloneBuffer = !(ArrayBuffer && Float64Array && Uint8Array) ? identity : function(buffer) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` + cloneBuffer = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { var byteLength = buffer.byteLength, - floatLength = floor(byteLength / 8), + floatLength = Float64Array ? floor(byteLength / 8) : 0, offset = floatLength * 8, - result = new ArrayBuffer(byteLength), - resultView = new Float64Array(result, 0, floatLength); + result = new ArrayBuffer(byteLength); - resultView.set(new Float64Array(buffer, 0, floatLength)); - resultView = new Uint8Array(result, offset); - resultView.set(new Uint8Array(buffer, offset)); + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } return result; }; } From b2280b2d728ba587387b64affda1cc66e446c48d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 2 Jun 2014 09:29:16 -0700 Subject: [PATCH 0736/1608] Fixed `_.keys` in Safari 5.0.5. --- lodash.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index 8ce21c526b..d7e3780ba3 100644 --- a/lodash.js +++ b/lodash.js @@ -6954,8 +6954,9 @@ var Ctor = object && object.constructor, length = object ? object.length : 0; - if ((typeof length == 'number' && length > 0) || - (Ctor && object === Ctor.prototype)) { + if ((Ctor && object === Ctor.prototype) || + (typeof length == 'number' && length > 0) || + (support.enumPrototypes && typeof object == 'function')) { return shimKeys(object); } return isObject(object) ? nativeKeys(object) : []; From 7b4fd28ef1fee91e9bf960db2b2a0f7bfd03aa51 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 3 Jun 2014 09:26:47 -0700 Subject: [PATCH 0737/1608] Ensure `_.merge` ignores `undefined` values of `source` object properties. [closes #573] --- lodash.js | 23 +++++++++++------------ test/test.js | 34 ++++++++++++++++------------------ 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/lodash.js b/lodash.js index d7e3780ba3..e8b142dddb 100644 --- a/lodash.js +++ b/lodash.js @@ -1962,7 +1962,8 @@ * @returns {Object} Returns the destination object. */ function baseMerge(object, source, callback, stackA, stackB) { - (isArrayLike(source) ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { + var isSrcArr = isArrayLike(source); + (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { var isArr = srcValue && isArrayLike(srcValue), isObj = srcValue && isPlainObject(srcValue), value = object[key]; @@ -1972,10 +1973,9 @@ if (typeof result == 'undefined') { result = srcValue; } - if (typeof result != 'undefined') { - value = result; + if (isSrcArr || typeof result != 'undefined') { + object[key] = result; } - object[key] = value; return; } // avoid merging previously merged cyclic sources @@ -1992,22 +1992,21 @@ var result = callback ? callback(value, srcValue, key, object, source) : undefined, isShallow = typeof result != 'undefined'; - if (isShallow) { - value = result; - } else { - value = isArr + if (!isShallow) { + result = isArr ? (isArray(value) ? value : []) : (isPlainObject(value) ? value : {}); } - // add `source` and associated `value` to the stack of traversed objects + // add the source value to the stack of traversed objects + // and associate it with its merged value stackA.push(srcValue); - stackB.push(value); + stackB.push(result); // recursively merge objects and arrays (susceptible to call stack limits) if (!isShallow) { - baseMerge(value, srcValue, callback, stackA, stackB); + baseMerge(result, srcValue, callback, stackA, stackB); } - object[key] = value; + object[key] = result; }); return object; diff --git a/test/test.js b/test/test.js index 3fc3df1335..4679f53686 100644 --- a/test/test.js +++ b/test/test.js @@ -2580,22 +2580,6 @@ deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); }); - - if (methodName == 'merge') { - test('`_.' + methodName + '` should treat sparse arrays as dense', 2, function() { - var array = Array(3); - array[0] = 1; - array[2] = 3; - - var actual = func([], array), - expected = array.slice(); - - expected[1] = undefined; - - ok('1' in actual); - deepEqual(actual, expected); - }); - } }); /*--------------------------------------------------------------------------*/ @@ -6365,6 +6349,20 @@ ok(actual.bar.b === actual.foo.b && actual.foo.b.foo.c === actual.foo.b.foo.c.foo.b.foo.c); }); + test('should treat sources that are sparse arrays as dense', 2, function() { + var array = Array(3); + array[0] = 1; + array[2] = 3; + + var actual = _.merge([], array), + expected = array.slice(); + + expected[1] = undefined; + + ok('1' in actual); + deepEqual(actual, expected); + }); + test('should not treat `arguments` objects as plain objects', 1, function() { var object = { 'args': args @@ -6389,8 +6387,8 @@ }); test('should not assign `undefined` values', 1, function() { - var actual = _.merge({ 'a': 1 }, { 'a': undefined }); - strictEqual(actual.a, 1); + var actual = _.merge({ 'a': 1 }, { 'a': undefined, 'b': undefined }); + deepEqual(actual, { 'a': 1 }); }); test('should handle merging if `callback` returns `undefined`', 1, function() { From d14d7ade85bb55e218c27fd47f55e06e4fb11e7b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 3 Jun 2014 09:27:22 -0700 Subject: [PATCH 0738/1608] Fix `baseIsEqual` doc param typo. [ci skip] --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index e8b142dddb..9cbd9f95ff 100644 --- a/lodash.js +++ b/lodash.js @@ -1737,7 +1737,7 @@ * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. + * @param {boolean} [isWhere=false] A flag to indicate performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. From 0ce130efa7cd59f2b22962f20e8a73a234bfbc07 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 4 Jun 2014 06:47:29 -0700 Subject: [PATCH 0739/1608] Cleanup readme and update Opera versions. [ci skip] --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 29e6ef30e9..8a705b3c2e 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,14 @@ A utility library delivering consistency, [customization](http://lodash.com/cust ## Documentation * [API Documentation](http://lodash.com/docs) -* [DevDocs – *a fast, organized, & searchable interface for our documentation*](http://devdocs.io/lodash/) +* [DevDocs – *a searchable interface for our documentation*](http://devdocs.io/lodash/) ## Download Review the [build differences](https://github.com/lodash/lodash/wiki/build-differences) & pick the build that’s right for you. * [Modern build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js))
    - For new environments like Chrome ≥ 14, Firefox ≥ 10, IE ≥ 9, Node.js, Opera ≥ 12, & Safari ≥ 5.1 + For new environments like Chrome, Firefox, IE ≥ 9, & Safari ≥ 5.1 * [Compatibility build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js))
    For new & old environments like IE ≤ 8 & PhantomJS * [Underscore build](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) ([minified](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js))
    @@ -18,7 +18,7 @@ Review the [build differences](https://github.com/lodash/lodash/wiki/build-diffe CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash).
    Create [custom builds](http://lodash.com/custom-builds) with only the features you need.
    -Love modules? We’ve got you covered with [lodash-amd](https://github.com/lodash/lodash-amd/tree/2.4.1), [lodash-es6](https://github.com/lodash/lodash-es6), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method. +Love modules? We’ve got you covered with [lodash-amd](https://github.com/lodash/lodash-amd/tree/2.4.1), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method. ## Dive in @@ -114,7 +114,7 @@ Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl ## Support -Tested in Chrome (19, 34-35), Firefox (3, 20, 28-29), IE 6-11, Opera 20-21, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 34-35), Firefox (3, 20, 28-29), IE 6-11, Opera 21-22, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. From 681d3e09ba34d1ff78fb48b4bf53b3fe1542a1a1 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 4 Jun 2014 08:57:01 -0700 Subject: [PATCH 0740/1608] Rebuild dist. --- dist/lodash.compat.js | 867 +++++++++++++++++++--------------- dist/lodash.compat.min.js | 133 +++--- dist/lodash.js | 850 ++++++++++++++++++--------------- dist/lodash.min.js | 127 ++--- dist/lodash.underscore.js | 532 ++++++++++++--------- dist/lodash.underscore.min.js | 76 +-- 6 files changed, 1439 insertions(+), 1146 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 77e17cb8c2..dcc866ee47 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) + * Lo-Dash 2.5.0-pre (Custom Build) * Build: `lodash -o ./dist/lodash.compat.js` * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 @@ -21,7 +21,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.4.1'; + var version = '2.5.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; @@ -41,8 +41,8 @@ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, - reUnescapedHtml = /[&<>"']/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, + reUnescapedHtml = /[&<>"'`]/g; /** Used to match template delimiters */ var reEscape = /<%-([\s\S]+?)%>/g, @@ -65,6 +65,9 @@ /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; + /** Used to detect host constructors (Safari > 5) */ + var reHostCtor = /^\[object .+?Constructor\]$/; + /** Used to match latin-1 supplement letters */ var reLatin1 = /[\xC0-\xFF]/g; @@ -101,9 +104,10 @@ /** Used to assign default `context` object properties */ var contextProps = [ - 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', - 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', - 'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError' + 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Error', 'Float64Array', 'Function', + 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', + 'document', 'isFinite', 'isNaN','parseInt', 'setTimeout', 'TypeError', + 'Uint8Array', 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ @@ -122,18 +126,54 @@ dateClass = '[object Date]', errorClass = '[object Error]', funcClass = '[object Function]', + mapClass = '[object Map]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', - stringClass = '[object String]'; + setClass = '[object Set]', + stringClass = '[object String]', + weakMapClass = '[object WeakMap]'; + + var arrayBufferClass = '[object ArrayBuffer]', + float32Class = '[object Float32Array]', + float64Class = '[object Float64Array]', + int8Class = '[object Int8Array]', + int16Class = '[object Int16Array]', + int32Class = '[object Int32Array]', + uint8Class = '[object Uint8Array]', + uint8ClampedClass = '[object Uint8ClampedArray]', + uint16Class = '[object Uint16Array]', + uint32Class = '[object Uint32Array]'; + + /** Used to identify object classifications that are treated like arrays */ + var arrayLikeClasses = {}; + arrayLikeClasses[argsClass] = + arrayLikeClasses[arrayClass] = arrayLikeClasses[float32Class] = + arrayLikeClasses[float64Class] = arrayLikeClasses[int8Class] = + arrayLikeClasses[int16Class] = arrayLikeClasses[int32Class] = + arrayLikeClasses[uint8Class] = arrayLikeClasses[uint8ClampedClass] = + arrayLikeClasses[uint16Class] = arrayLikeClasses[uint32Class] = true; + arrayLikeClasses[arrayBufferClass] = arrayLikeClasses[boolClass] = + arrayLikeClasses[dateClass] = arrayLikeClasses[errorClass] = + arrayLikeClasses[funcClass] = arrayLikeClasses[mapClass] = + arrayLikeClasses[numberClass] = arrayLikeClasses[objectClass] = + arrayLikeClasses[regexpClass] = arrayLikeClasses[setClass] = + arrayLikeClasses[stringClass] = arrayLikeClasses[weakMapClass] = false; /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; - cloneableClasses[funcClass] = false; - cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[argsClass] = + cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] = + cloneableClasses[errorClass] = cloneableClasses[float32Class] = + cloneableClasses[float64Class] = cloneableClasses[int8Class] = + cloneableClasses[int16Class] = cloneableClasses[int32Class] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = - cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; + cloneableClasses[regexpClass] = cloneableClasses[stringClass] = + cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] = + cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true; + cloneableClasses[funcClass] = cloneableClasses[mapClass] = + cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false; /** Used as an internal `_.debounce` options object by `_.throttle` */ var debounceOptions = { @@ -154,17 +194,23 @@ * Used to convert characters to HTML entities. * * Note: Though the ">" character is escaped for symmetry, characters like - * ">", "`", and "/" don't require escaping in HTML and have no special meaning + * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. + * + * Backticks are escaped because in Internet Explorer < 9, they can be used to + * break out of attribute values or HTML comments. See [#102](http://html5sec.org/#102), + * [#108](http://html5sec.org/#108), and [#133](http://html5sec.org/#133) of + * the [HTML5 Security Cheatsheet](http://html5sec.org/) for more details. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', - "'": ''' + "'": ''', + '`': '`' }; /** Used to convert HTML entities to characters */ @@ -173,7 +219,8 @@ '<': '<', '>': '>', '"': '"', - ''': "'" + ''': "'", + '`': '`' }; /** @@ -565,12 +612,10 @@ /** Native constructor references */ var Array = context.Array, - Boolean = context.Boolean, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, - Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, @@ -585,8 +630,8 @@ /** Used to detect DOM support */ var document = (document = context.window) && document.document; - /** Used to restore the original `_` reference in `_.noConflict` */ - var oldDash = context._; + /** Used to resolve the decompiled source of functions */ + var fnToString = Function.prototype.toString; /** * Used as the maximum length of an array-like object. @@ -595,6 +640,9 @@ */ var maxSafeInteger = Math.pow(2, 53) - 1; + /** Used to restore the original `_` reference in `_.noConflict` */ + var oldDash = context._; + /** Used to resolve the internal `[[Class]]` of values */ var toString = objectProto.toString; @@ -605,10 +653,12 @@ ); /** Native method shortcuts */ - var ceil = Math.ceil, + var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, + bufferSlice = isNative(bufferSlice = ArrayBuffer && (new ArrayBuffer).slice) && bufferSlice, + ceil = Math.ceil, clearTimeout = context.clearTimeout, + Float64Array = isNative(Float64Array = context.Float64Array) && Float64Array, floor = Math.floor, - fnToString = Function.prototype.toString, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, @@ -616,6 +666,7 @@ Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, unshift = arrayProto.unshift; /** Used to set metadata on functions */ @@ -642,17 +693,6 @@ nativeParseInt = context.parseInt, nativeRandom = Math.random; - /** Used to lookup built-in constructors by `[[Class]]` */ - var ctorByClass = {}; - ctorByClass[arrayClass] = Array; - ctorByClass[boolClass] = Boolean; - ctorByClass[dateClass] = Date; - ctorByClass[funcClass] = Function; - ctorByClass[objectClass] = Object; - ctorByClass[numberClass] = Number; - ctorByClass[regexpClass] = RegExp; - ctorByClass[stringClass] = String; - /** Used to avoid iterating over non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; @@ -725,15 +765,11 @@ * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value - * wrapped.reduce(function(sum, num) { - * return sum + num; - * }); + * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value - * var squares = wrapped.map(function(num) { - * return num * num; - * }); + * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false @@ -773,12 +809,12 @@ var support = lodash.support = {}; (function(x) { - var ctor = function() { this.x = 1; }, + var Ctor = function() { this.x = 1; }, object = { '0': 1, 'length': 1 }, props = []; - ctor.prototype = { 'valueOf': 1, 'y': 1 }; - for (var key in new ctor) { props.push(key); } + Ctor.prototype = { 'valueOf': 1, 'y': 1 }; + for (var key in new Ctor) { props.push(key); } for (var argsKey in arguments) { } for (var strKey in 'x') { } @@ -821,7 +857,7 @@ * @memberOf _.support * @type boolean */ - support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype'); + support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype'); /** * Detect if functions can be decompiled by `Function#toString` @@ -1109,9 +1145,6 @@ * @returns {Object} Returns the destination object. */ function baseAssign(object, source, callback) { - if (!object) { - return object; - } var index = -1, props = keys(source), length = props.length; @@ -1189,18 +1222,32 @@ if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) { return value; } - var ctor = ctorByClass[className]; + var Ctor = value.constructor; + if (className == objectClass && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { + Ctor = Object; + } switch (className) { + case arrayBufferClass: + return cloneBuffer(value); + case boolClass: case dateClass: - return new ctor(+value); + return new Ctor(+value); + + case errorClass: + return new Ctor(value.message); + + case float32Class: case float64Class: + case int8Class: case int16Class: case int32Class: + case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: + return value.subarray(0); case numberClass: case stringClass: - return new ctor(value); + return new Ctor(value); case regexpClass: - result = ctor(value.source, reFlags.exec(value)); + result = Ctor(value.source, reFlags.exec(value)); result.lastIndex = value.lastIndex; return result; } @@ -1219,7 +1266,7 @@ return stackB[length]; } } - result = isArr ? ctor(value.length) : {}; + result = isArr ? Ctor(value.length) : Ctor(); } else { result = isArr ? slice(value) : baseAssign({}, value); @@ -1323,15 +1370,15 @@ case 1: return function(value) { return func.call(thisArg, value); }; - case 2: return function(value, other) { - return func.call(thisArg, value, other); - }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); }; case 4: return function(accumulator, value, index, collection) { return func.call(thisArg, accumulator, value, index, collection); }; + case 5: return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; } return bind(func, thisArg); } @@ -1691,7 +1738,7 @@ * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. + * @param {boolean} [isWhere=false] A flag to indicate performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. @@ -1742,13 +1789,15 @@ // but treat `-0` vs. `+0` as not equal : (value == 0 ? (1 / value == 1 / other) : value == +other); + case errorClass: case regexpClass: case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) + // coerce errors (http://es5.github.io/#x15.11.4.4) + // and regexes (http://es5.github.io/#x15.10.6.4) to strings // treat string primitives and their corresponding object instances as equal return value == String(other); } - var isArr = valClass == arrayClass; + var isArr = arrayLikeClasses[valClass]; if (!isArr) { // exit for functions and DOM nodes if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) { @@ -1914,11 +1963,9 @@ * @returns {Object} Returns the destination object. */ function baseMerge(object, source, callback, stackA, stackB) { - if (!object) { - return object; - } - (isArray(source) ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { - var isArr = srcValue && isArray(srcValue), + var isSrcArr = isArrayLike(source); + (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { + var isArr = srcValue && isArrayLike(srcValue), isObj = srcValue && isPlainObject(srcValue), value = object[key]; @@ -1927,10 +1974,9 @@ if (typeof result == 'undefined') { result = srcValue; } - if (typeof result != 'undefined') { - value = result; + if (isSrcArr || typeof result != 'undefined') { + object[key] = result; } - object[key] = value; return; } // avoid merging previously merged cyclic sources @@ -1947,22 +1993,21 @@ var result = callback ? callback(value, srcValue, key, object, source) : undefined, isShallow = typeof result != 'undefined'; - if (isShallow) { - value = result; - } else { - value = isArr + if (!isShallow) { + result = isArr ? (isArray(value) ? value : []) : (isPlainObject(value) ? value : {}); } - // add `source` and associated `value` to the stack of traversed objects + // add the source value to the stack of traversed objects + // and associate it with its merged value stackA.push(srcValue); - stackB.push(value); + stackB.push(result); // recursively merge objects and arrays (susceptible to call stack limits) if (!isShallow) { - baseMerge(value, srcValue, callback, stackA, stackB); + baseMerge(result, srcValue, callback, stackA, stackB); } - object[key] = value; + object[key] = result; }); return object; @@ -2125,7 +2170,7 @@ /** * Compiles a function from `source` using the `varNames` and `varValues` * pairs to import free variables into the compiled function. If `sourceURL` - * is provided it will be used as the sourceURL for the compiled function. + * is provided it is used as the sourceURL for the compiled function. * * @private * @param {string} source The source to compile. @@ -2214,7 +2259,7 @@ * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection * through a callback. The given setter function sets the keys and values of - * the accumulator object. If `initializer` is provided it will be used to + * the accumulator object. If `initializer` is provided it is used to * initialize the accumulator object. * * @private @@ -2267,7 +2312,7 @@ } // juggle arguments if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 2); + var callback = baseCreateCallback(args[--length - 1], args[length--], 5); } else if (length > 2 && typeof args[length - 1] == 'function') { callback = args[--length]; } @@ -2456,6 +2501,18 @@ return result === indexOf ? baseIndexOf : result; } + /** + * Checks if `value` is an array-like object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. + */ + function isArrayLike(value) { + return (value && typeof value == 'object' && typeof value.length == 'number' && + arrayLikeClasses[toString.call(value)]) || false; + } + /** * Checks if `value` is a native function. * @@ -2464,7 +2521,40 @@ * @returns {boolean} Returns `true` if `value` is a native function, else `false`. */ function isNative(value) { - return typeof value == 'function' && reNative.test(fnToString.call(value)); + var type = typeof value; + return type == 'function' + ? reNative.test(fnToString.call(value)) + : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; + } + + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneBuffer(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` + cloneBuffer = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / 8) : 0, + offset = floatLength * 8, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; } /** @@ -2490,13 +2580,13 @@ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { - var ctor, + var Ctor, result; // avoid non `Object` objects, `arguments` objects, and DOM elements if (!(value && toString.call(value) == objectClass) || (!hasOwnProperty.call(value, 'constructor') && - (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) || + (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor))) || (!support.argsClass && isArguments(value)) || (!support.nodeClass && isNode(value))) { return false; @@ -2664,14 +2754,14 @@ /** * Creates a slice of `array` excluding elements dropped from the end. - * Elements will be dropped until the predicate returns falsey. The predicate - * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * Elements are dropped until the predicate returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2684,9 +2774,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.dropRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); + * _.dropRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [1] * * var characters = [ @@ -2707,14 +2795,14 @@ /** * Creates a slice of `array` excluding elements dropped from the beginning. - * Elements will be dropped until the predicate returns falsey. The predicate - * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * Elements are dropped until the predicate returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2727,9 +2815,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.dropWhile([1, 2, 3], function(num) { - * return num < 3; - * }); + * _.dropWhile([1, 2, 3], function(n) { return n < 3; }); * // => [3] * * var characters = [ @@ -2753,10 +2839,10 @@ * element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2764,8 +2850,8 @@ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example @@ -2807,10 +2893,10 @@ * of a collection from right to left. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2818,8 +2904,8 @@ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example @@ -2896,16 +2982,16 @@ /** * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truthy, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before + * is truthy, the array is only flattened a single level. If a callback is + * provided each element of the array is passed through the callback before * flattening. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2914,7 +3000,7 @@ * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new flattened array. @@ -2962,7 +3048,7 @@ /** * Gets the index at which the first occurrence of `value` is found using * strict equality for comparisons, i.e. `===`. If the array is already sorted - * providing `true` for `fromIndex` will run a faster binary search. + * providing `true` for `fromIndex` performs a faster binary search. * * @static * @memberOf _ @@ -3231,10 +3317,10 @@ * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * Note: Unlike `_.filter`, this method mutates `array`. @@ -3244,14 +3330,14 @@ * @category Arrays * @param {Array} array The array to modify. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [1, 2, 3, 4]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * var evens = _.remove(array, function(n) { return n % 2 == 0; }); * * console.log(array); * // => [1, 3] @@ -3353,15 +3439,15 @@ /** * Uses a binary search to determine the smallest index at which a value * should be inserted into a given sorted array in order to maintain the sort - * order of the array. If a callback is provided it will be executed for - * `value` and each element of `array` to compute their sort ranking. The - * callback is bound to `thisArg` and invoked with one argument; (value). + * order of the array. If a callback is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The callback + * is bound to `thisArg` and invoked with one argument; (value). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3370,8 +3456,8 @@ * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. @@ -3470,15 +3556,15 @@ var takeRight = last; /** - * Creates a slice of `array` with elements taken from the end. Elements will - * be taken until the predicate returns falsey. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until the predicate returns falsey. The predicate is bound to `thisArg` + * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3491,9 +3577,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.takeRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); + * _.takeRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [2, 3] * * var characters = [ @@ -3514,14 +3598,14 @@ /** * Creates a slice of `array` with elements taken from the beginning. Elements - * will be taken until the predicate returns falsey. The predicate is bound - * to `thisArg` and invoked with three arguments; (value, index, array). + * are taken until the predicate returns falsey. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3534,9 +3618,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.takeWhile([1, 2, 3], function(num) { - * return num < 3; - * }); + * _.takeWhile([1, 2, 3], function(n) { return n < 3; }); * // => [1, 2] * * var characters = [ @@ -3575,17 +3657,17 @@ /** * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing `true` for - * `isSorted` will use a faster algorithm. If a callback is provided it will - * be executed for each value in the array to generate the criterion by which - * uniqueness is computed. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index, array). + * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a + * faster search algorithm for sorted arrays. If a callback is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3595,26 +3677,26 @@ * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new duplicate-value-free array. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] + * _.uniq([1, 2, 1]); + * // => [1, 2] * * // using `isSorted` - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] + * _.uniq([1, 1, 2], true); + * // => [1, 2] * * // using `callback` - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] + * _.uniq(['A', 'b', 'a', 'B'], function(chr) { return chr.toLowerCase(); }); + * // => ['A', 'b'] * * // using `callback` with `thisArg` - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] + * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); + * // => [1, 2.5] * * // using "_.pluck" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); @@ -3699,7 +3781,7 @@ * Creates an array of grouped elements, the first of which contains the first * elements of the given arrays, the second of which contains the second elements * of the given arrays, and so on. If a zipped value is provided its corresponding - * unzipped value will be returned. + * unzipped value is returned. * * @static * @memberOf _ @@ -3969,10 +4051,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3980,16 +4062,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * - * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); @@ -4005,10 +4087,10 @@ * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4017,8 +4099,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements passed the predicate check, * else `false`. @@ -4070,10 +4152,10 @@ * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4082,13 +4164,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * - * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [2, 4] * * var characters = [ @@ -4134,10 +4216,10 @@ * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4146,8 +4228,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example @@ -4189,15 +4271,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * - * _.findLast([1, 2, 3, 4], function(num) { - * return num % 2 == 1; - * }); + * _.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1; }); * // => 3 */ function findLast(collection, predicate, thisArg) { @@ -4253,10 +4333,10 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEach(function(n) { console.log(n); }).join(','); * // => logs each number and returns '1,2,3' * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { console.log(n); }); * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { @@ -4279,7 +4359,7 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each number from right to left and returns '3,2,1' */ function forEachRight(collection, callback, thisArg) { @@ -4296,10 +4376,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4307,16 +4387,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using "_.pluck" callback shorthand @@ -4339,10 +4419,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4350,8 +4430,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -4377,8 +4457,8 @@ /** * Invokes the method named by `methodName` on each element in the collection * returning an array of the results of each invoked method. Additional arguments - * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the collection. + * is provided to each invoked method. If `methodName` is a function it is + * invoked for, and `this` bound to, each element in the collection. * * @static * @memberOf _ @@ -4406,10 +4486,10 @@ * three arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4418,16 +4498,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new mapped array. * @example * - * _.map([1, 2, 3], function(num) { return num * 3; }); + * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); * // => [3, 6, 9] (property order is not guaranteed across environments) * * var characters = [ @@ -4455,17 +4535,17 @@ } /** - * Retrieves the maximum value of a collection. If the collection is empty or - * falsey `-Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Retrieves the maximum value of a collection. If the collection is empty + * or falsey `-Infinity` is returned. If a callback is provided it is executed + * for each value in the collection to generate the criterion by which the + * value is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4473,7 +4553,7 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the maximum value. @@ -4533,17 +4613,17 @@ } /** - * Retrieves the minimum value of a collection. If the collection is empty or - * falsey `Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Retrieves the minimum value of a collection. If the collection is empty + * or falsey `Infinity` is returned. If a callback is provided it is executed + * for each value in the collection to generate the criterion by which the + * value is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4551,7 +4631,7 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the minimum value. @@ -4617,10 +4697,10 @@ * to `thisArg` and invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4628,16 +4708,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the array of grouped elements. * @example * - * _.partition([1, 2, 3], function(num) { return num % 2; }); + * _.partition([1, 2, 3], function(n) { return n % 2; }); * // => [[1, 3], [2]] * - * _.partition([1.2, 2.3, 3.4], function(num) { return this.floor(num) % 2; }, Math); + * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); * // => [[1, 3], [2]] * * var characters = [ @@ -4685,9 +4765,9 @@ * Reduces a collection to a value which is the accumulated result of running * each element in the collection through the callback, where each successive * callback execution consumes the return value of the previous execution. If - * `accumulator` is not provided the first element of the collection will be - * used as the initial `accumulator` value. The callback is bound to `thisArg` - * and invoked with four arguments; (accumulator, value, index|key, collection). + * `accumulator` is not provided the first element of the collection is used + * as the initial `accumulator` value. The callback is bound to `thisArg` and + * invoked with four arguments; (accumulator, value, index|key, collection). * * @static * @memberOf _ @@ -4700,13 +4780,11 @@ * @returns {*} Returns the accumulated value. * @example * - * var sum = _.reduce([1, 2, 3], function(sum, num) { - * return sum + num; - * }); + * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * - * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } @@ -4771,10 +4849,10 @@ * the predicate does **not** return truthy for. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4782,13 +4860,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * - * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [1, 3] * * var characters = [ @@ -4904,10 +4982,10 @@ * with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4916,8 +4994,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. @@ -4966,18 +5044,18 @@ /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through the callback. This method - * performs a stable sort, that is, it will preserve the original sort order - * of equal elements. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an array of property names is provided for `callback` the collection - * will be sorted by each property value. + * is sorted by each property value. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4985,16 +5063,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it will - * be used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If a property name or object is provided it is + * used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example * - * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * - * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * * var characters = [ @@ -5177,7 +5255,7 @@ * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays * of method names. If no method names are provided all enumerable function - * properties, own and inherited, of `object` will be bound. + * properties, own and inherited, of `object` are bound. * * Note: This method does not set the `length` property of bound functions. * @@ -5229,7 +5307,7 @@ * Creates a function that invokes the method at `object[key]` and prepends * any additional `bindKey` arguments to those provided to the bound function. * This method differs from `_.bind` by allowing bound functions to reference - * methods that will be redefined or don't yet exist. + * methods that may be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * @@ -5355,14 +5433,15 @@ } /** - * Creates a function that will delay the execution of `func` until after - * `wait` milliseconds have elapsed since the last time it was invoked. - * 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 will return the result of the last `func` call. + * Creates a function that delays the execution of `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 calls. 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` call. * - * Note: If `leading` and `trailing` options are `true`, `func` will be called - * on the trailing edge of the timeout only if the the debounced function is + * Note: If `leading` and `trailing` options are `true`, `func` is called on + * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * * @static @@ -5378,8 +5457,7 @@ * @example * * // avoid costly calculations while the window size is in flux - * var lazyLayout = _.debounce(calculateLayout, 150); - * jQuery(window).on('resize', lazyLayout); + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // execute `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { @@ -5389,9 +5467,26 @@ * * // ensure `batchLog` is executed once after 1 second of debounced calls * var source = new EventSource('/stream'); - * source.addEventListener('message', _.debounce(batchLog, 250, { + * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * }, false); + * + * // cancel a debounced call + * var todoChanges = _.debounce(batchLog, 1000); + * Object.observe(models.todo, todoChanges); + * + * Object.observe(models, function(changes) { + * if (_.find(changes, { 'name': 'todo', 'type': 'delete'})) { + * todoChanges.cancel(); + * } + * }, ['delete']); + * + * // ...at some point `models.todo` is changed + * models.todo.completed = true; + * + * // ...before 1 second has passed `models.todo` is deleted + * // which cancels the debounced `todoChanges` call + * delete models.todo; */ function debounce(func, wait, options) { var args, @@ -5417,7 +5512,18 @@ maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); trailing = 'trailing' in options ? options.trailing : trailing; } - var delayed = function() { + + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + } + + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { if (maxTimeoutId) { @@ -5435,9 +5541,9 @@ } else { timeoutId = setTimeout(delayed, remaining); } - }; + } - var maxDelayed = function() { + function maxDelayed() { if (timeoutId) { clearTimeout(timeoutId); } @@ -5449,9 +5555,9 @@ args = thisArg = null; } } - }; + } - return function() { + function debounced() { args = arguments; stamp = now(); thisArg = this; @@ -5491,12 +5597,14 @@ args = thisArg = null; } return result; - }; + } + debounced.cancel = cancel; + return debounced; } /** - * Defers executing the `func` function until the current call stack has cleared. - * Additional arguments will be provided to `func` when it is invoked. + * Defers executing the `func` function until the current call stack has + * cleared. Additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -5519,7 +5627,7 @@ /** * Executes the `func` function after `wait` milliseconds. Additional arguments - * will be provided to `func` when it is invoked. + * are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -5543,11 +5651,11 @@ /** * Creates a function that memoizes the result of `func`. If `resolver` is - * provided it will be used to determine the cache key for storing the result - * based on the arguments provided to the memoized function. By default, the - * first argument provided to the memoized function is used as the cache key. - * The `func` is executed with the `this` binding of the memoized function. - * The result cache is exposed as the `cache` property on the memoized function. + * provided it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the cache key. The `func` is + * executed with the `this` binding of the memoized function. The result cache + * is exposed as the `cache` property on the memoized function. * * @static * @memberOf _ @@ -5606,8 +5714,8 @@ * @returns {Function} Returns the new function. * @example * - * function isEven(num) { - * return num % 2 == 0; + * function isEven(n) { + * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); @@ -5623,8 +5731,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls to - * the function will return the value of the first call. The `func` is executed + * Creates a function that is restricted to execute `func` once. Repeat calls + * to the function return the value of the first call. The `func` is executed * with the `this` binding of the created function. * * @static @@ -5726,14 +5834,15 @@ } /** - * Creates a function that, when executed, will only call the `func` function - * at most once per every `wait` milliseconds. 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 will - * return the result of the last `func` call. + * Creates a function that only calls the `func` function at most once per + * every `wait` milliseconds. The created function comes with a `cancel` method + * to cancel delayed calls. 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` will be called - * on the trailing edge of the timeout only if the the throttled function is + * Note: If `leading` and `trailing` options are `true`, `func` is called on + * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * * @static @@ -5748,13 +5857,14 @@ * @example * * // avoid excessively updating the position while scrolling - * var throttled = _.throttle(updatePosition, 100); - * jQuery(window).on('scroll', throttled); + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes - * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { - * 'trailing': false - * })); + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) + * jQuery('.interactive').on('click', throttled); + * + * // cancel a trailing throttled call + * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { var leading = true, @@ -5805,10 +5915,10 @@ /** * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with - * five arguments; (objectValue, sourceValue, key, object, source). + * object. Subsequent sources overwrite property assignments of previous + * sources. If a callback is provided it is executed to produce the assigned + * values. The callback is bound to `thisArg` and invoked with five arguments; + * (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -5821,24 +5931,24 @@ * @returns {Object} Returns the destination object. * @example * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } + * _.assign({ 'name': 'fred' }, { 'age': 40 }, { 'employer': 'slate' }); + * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' } * * var defaults = _.partialRight(_.assign, function(value, other) { * return typeof value == 'undefined' ? other : value; * }); * - * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ var assign = createAssigner(baseAssign); /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects will also - * be cloned, otherwise they will be assigned by reference. If a callback - * is provided it will be executed to produce the cloned values. If the - * callback returns `undefined` cloning will be handled by the method instead. - * The callback is bound to `thisArg` and invoked with two argument; (value, index|key). + * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, + * otherwise they are assigned by reference. If a callback is provided it is + * executed to produce the cloned values. If the callback returns `undefined` + * cloning is handled by the method instead. The callback is bound to `thisArg` + * and invoked with two argument; (value, index|key). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and @@ -5898,10 +6008,10 @@ } /** - * Creates a deep clone of `value`. If a callback is provided it will be - * executed to produce the cloned values. If the callback returns `undefined` - * cloning will be handled by the method instead. The callback is bound to - * `thisArg` and invoked with two argument; (value, index|key). + * Creates a deep clone of `value`. If a callback is provided it is executed + * to produce the cloned values. If the callback returns `undefined` cloning + * is handled by the method instead. The callback is bound to `thisArg` and + * invoked with two argument; (value, index|key). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and @@ -5983,7 +6093,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. + * property is set, additional defaults of the same property are ignored. * * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. @@ -5997,8 +6107,8 @@ * @returns {Object} Returns the destination object. * @example * - * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { if (!object) { @@ -6014,10 +6124,10 @@ * first element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -6025,8 +6135,8 @@ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example @@ -6060,10 +6170,10 @@ * a collection in the opposite order. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -6071,8 +6181,8 @@ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example @@ -6180,7 +6290,7 @@ * @returns {Object} Returns `object`. * @example * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) @@ -6205,7 +6315,7 @@ * @returns {Object} Returns `object`. * @example * - * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' @@ -6256,7 +6366,7 @@ /** * Creates an object composed of the inverted keys and values of the given * object. If the given object contains duplicate values, subsequent values - * will overwrite property assignments of previous values unless `multiValue` + * overwrite property assignments of previous values unless `multiValue` * is `true`. * * @static @@ -6467,10 +6577,10 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If a callback is provided it will be executed to compare - * values. If the callback returns `undefined` comparisons will be handled - * by the method instead. The callback is bound to `thisArg` and invoked - * with three arguments; (value, other, key). + * equivalent. If a callback is provided it is executed to compare values. + * If the callback returns `undefined` comparisons are handled by the method + * instead. The callback is bound to `thisArg` and invoked with three arguments; + * (value, other, key). * * Note: This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes @@ -6505,7 +6615,7 @@ * // => true */ function isEqual(value, other, callback, thisArg) { - callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2); + callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 3); if (!callback) { // exit early for identical values @@ -6549,7 +6659,7 @@ /** * Checks if `value` is, or can be coerced to, a finite number. * - * Note: This method is not the same as native `isFinite` which will return + * Note: This method is not the same as native `isFinite` which returns * `true` for booleans and empty strings. See the [ES5 spec](http://es5.github.io/#x15.1.2.5) * for more details. * @@ -6639,7 +6749,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which will return `true` + * Note: This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -6841,11 +6951,12 @@ * // => ['x', 'y'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { - var ctor = object && object.constructor, + var Ctor = object && object.constructor, length = object ? object.length : 0; - if ((typeof length == 'number' && length > 0) || - (ctor && object === ctor.prototype)) { + if ((Ctor && object === Ctor.prototype) || + (typeof length == 'number' && length > 0) || + (support.enumPrototypes && typeof object == 'function')) { return shimKeys(object); } return isObject(object) ? nativeKeys(object) : []; @@ -6881,9 +6992,9 @@ (support.nonEnumArgs && isArguments(object))) && length) >>> 0; var keyIndex, - ctor = object.constructor, + Ctor = object.constructor, index = -1, - isProto = ctor && object === ctor.prototype, + isProto = Ctor && object === Ctor.prototype, maxIndex = length - 1, result = Array(length), skipIndexes = length > 0, @@ -6893,6 +7004,10 @@ while (++index < length) { result[index] = String(index); } + // Lo-Dash skips the `constructor` property when it infers it's iterating + // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` + // attribute of an existing property and the `constructor` property of a + // prototype defaults to non-enumerable. for (var key in object) { if (!(isProto && key == 'constructor') && !(skipProto && key == 'prototype') && @@ -6901,10 +7016,6 @@ result.push(key); } } - // Lo-Dash skips the `constructor` property when it infers it's iterating - // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` - // attribute of an existing property and the `constructor` property of a - // prototype defaults to non-enumerable. if (support.nonEnumShadows && object !== objectProto) { index = -1; length = shadowedProps.length; @@ -6930,10 +7041,10 @@ * (value, key, object). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -6941,13 +7052,13 @@ * @category Objects * @param {Object} object The object to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the new mapped object. * @example * - * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); + * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(n) { return n * 3; }); * // => { 'a': 3, 'b': 6, 'c': 9 } * * var characters = { @@ -6972,11 +7083,11 @@ /** * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources - * will overwrite property assignments of previous sources. If a callback is - * provided it will be executed to produce the merged values of the destination - * and source properties. If the callback returns `undefined` merging will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with five arguments; (objectValue, sourceValue, key, object, source). + * overwrite property assignments of previous sources. If a callback is provided + * it is executed to produce the merged values of the destination and source + * properties. If the callback returns `undefined` merging is handled by the + * method instead. The callback is bound to `thisArg` and invoked with five + * arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -7025,9 +7136,9 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` omitting the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it is executed for each property + * of `object` omitting the properties the predicate returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static @@ -7095,9 +7206,9 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` picking the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it is executed for each property + * of `object` picking the properties the predicate returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static @@ -7146,28 +7257,28 @@ * @returns {*} Returns the accumulated value. * @example * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; + * var squares = _.transform([1, 2, 3, 4, 5, 6], function(result, n) { + * n *= n; + * if (n % 2) { + * return result.push(n) < 3; * } * }); * // => [1, 9, 25] * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); + var isArr = isArrayLike(object); if (accumulator == null) { if (isArr) { accumulator = []; } else { if (isObject(object)) { - var ctor = object.constructor, - proto = ctor && ctor.prototype; + var Ctor = object.constructor, + proto = Ctor && Ctor.prototype; } accumulator = baseCreate(proto); } @@ -7568,9 +7679,9 @@ * Creates a compiled template function that can interpolate data properties * in "interpolate" delimiters, HTML-escaped interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. If - * a data object is provided the interpolated template string will be returned. + * a data object is provided the interpolated template string is returned. * Data properties may be accessed as free variables in the template. If a - * settings object is provided it will override `_.templateSettings` for the + * settings object is provided it overrides `_.templateSettings` for the * template. * * Note: In the development build, `_.template` utilizes sourceURLs for easier debugging. @@ -7834,8 +7945,8 @@ /** * Truncates `string` if it is longer than the given maximum string length. - * The last characters of the truncated string will be replaced with the - * omission string which defaults to "...". + * The last characters of the truncated string are replaced with the omission + * string which defaults to "...". * * @static * @memberOf _ @@ -7848,22 +7959,22 @@ * @returns {string} Returns the truncated string. * @example * - * _.truncate('hi-diddly-ho there, neighborino'); + * _.trunc('hi-diddly-ho there, neighborino'); * // => 'hi-diddly-ho there, neighbo...' * - * _.truncate('hi-diddly-ho there, neighborino', 24); + * _.trunc('hi-diddly-ho there, neighborino', 24); * // => 'hi-diddly-ho there, n...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); * // => 'hi-diddly-ho there,...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); * //=> 'hi-diddly-ho there...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); + * _.trunc('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); * // => 'hi-diddly-ho there, neig [...]' */ - function truncate(string, options) { + function trunc(string, options) { var length = 30, omission = '...'; @@ -7962,9 +8073,9 @@ /** * Creates a function bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. + * name the created callback returns the property value for a given element. + * If `func` is an object the created callback returns `true` for elements + * that contain the equivalent object properties, otherwise it returns `false`. * * @static * @memberOf _ @@ -8085,7 +8196,7 @@ /** * Adds all own enumerable function properties of a source object to the - * destination object. If `object` is a function methods will be added to + * destination object. If `object` is a function then methods are added to * its prototype as well. * * @static @@ -8275,9 +8386,9 @@ /** * Produces a random number between `min` and `max` (inclusive). If only one - * argument is provided a number between `0` and the given number will be - * returned. If `floating` is truthy or either `min` or `max` are floats a - * floating-point number will be returned instead of an integer. + * argument is provided a number between `0` and the given number is returned. + * If `floating` is truthy, or either `min` or `max` are floats, a floating-point + * number is returned instead of an integer. * * @static * @memberOf _ @@ -8389,10 +8500,10 @@ /** * Resolves the value of property `key` on `object`. If `key` is a function - * it will be invoked with the `this` binding of `object` and its result - * returned, else the property value is returned. If `object` is `null` or - * `undefined` then `undefined` is returned. If a default value is provided - * it will be returned if the property value resolves to `undefined`. + * it is invoked with the `this` binding of `object` and its result returned, + * else the property value is returned. If `object` is `null` or `undefined` + * then `undefined` is returned. If a default value is provided it is returned + * if the property value resolves to `undefined`. * * @static * @memberOf _ @@ -8465,7 +8576,7 @@ } /** - * Generates a unique ID. If `prefix` is provided the ID will be appended to it. + * Generates a unique ID. If `prefix` is provided the ID is appended to it. * * @static * @memberOf _ @@ -8651,7 +8762,7 @@ lodash.trim = trim; lodash.trimLeft = trimLeft; lodash.trimRight = trimRight; - lodash.truncate = truncate; + lodash.trunc = trunc; lodash.unescape = unescape; lodash.uniqueId = uniqueId; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index faeb5016e9..b743d3c0ca 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -1,70 +1,71 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE + * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=Zr(e);++ri(t,l)&&f.push(l);return f}function Ct(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1o?0:o>>>0); -return Ct(n,function(n){var o=u?t:null!=n&&n[t];i[++e]=o?o.apply(n,r):m}),i}function Ft(n,t,r,e,u){return n?((Ze(t)?ct:It)(t,function(t,o,i){var a=t&&Ze(t),l=t&&Ke(t),f=n[o];if(a||l){for(e||(e=[]),u||(u=[]),l=e.length;l--;)if(e[l]==t)return void(n[o]=u[l]);i=r?r(f,t,o,n,i):m,f=(l=typeof i!="undefined")?i:a?Ze(f)?f:[]:Ke(f)?f:{},e.push(t),u.push(f),l||Ft(f,t,r,e,u)}else i=r?r(f,t,o,n,i):m,typeof i=="undefined"&&(i=t),typeof i!="undefined"&&(f=i);n[o]=f}),n):n}function Wt(n,t){var r={};if(typeof t=="function")return St(n,function(n,e,u){t(n,e,u)&&(r[e]=n) -}),r;for(var e=-1,u=t.length;++ea(s,g)&&((u||f)&&s.push(g),c.push(p))}return c}function Dt(n,t){for(var r=-1,e=t(n),u=e.length,o=Zr(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3o?0:o)}function Qt(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?Se(u+e,0):e||0;else if(e)return e=ur(n,t),u&&n[e]===t?e:-1;return r(n,t,e) -}function nr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),er(n,0,0>o?0:o)}function tr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=U.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:m;return o=e-(o||0),er(n,0>o?0:o)}function rr(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,r,3);++et?0:t;return er(n,o)}function er(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t?t=Se(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=Se(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=Zr(u);++e>>1,r(n[e])r?0:r);++tr?Se(e+r,0):r||0:0,typeof n=="string"||!Ze(n)&&Nr(n)?ro&&(o=a)}else t=null==t&&Nr(n)?u:U.createCallback(t,r,3),Ct(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function dr(n,t){return vr(n,qr(t))}function mr(n,t,r,e){var u=3>arguments.length;if(t=U.createCallback(t,e,4),Ze(n)){var o=-1,i=n.length;for(u&&i&&(r=n[++o]);++oarguments.length;return t=U.createCallback(t,e,4),jt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o) -}),r}function _r(n){var t=-1,r=n&&n.length,e=Zr(0>r?0:r>>>0);return Ct(n,function(n){var r=$t(0,++t);e[t]=e[r],e[r]=n}),e}function wr(n,t,r){var e;if((typeof t!="function"||typeof r!="undefined")&&(t=U.createCallback(t,r,3)),Ze(n)){r=-1;for(var u=n.length;++rarguments.length)return Kt(n,b,null,t);if(n)var r=n[O]?n[O][2]:n.length,e=er(arguments,2),r=r-e.length;return Kt(n,b|C,r,t,e)}function Cr(n,t,r){var e,u,o,i,a,l,f,c=0,s=false,p=true; -if(!Ar(n))throw new ne(E);if(t=0>t?0:t,true===r)var g=true,p=false;else Sr(r)&&(g=r.leading,s="maxWait"in r&&Se(t,+r.maxWait||0),p="trailing"in r?r.trailing:p);var h=function(){var r=t-(Ge()-i);0>=r||r>t?(u&&se(u),r=f,u=l=f=m,r&&(c=Ge(),o=n.apply(a,e),l||u||(e=a=null))):l=be(h,r)},v=function(){l&&se(l),u=l=f=m,(p||s!==t)&&(c=Ge(),o=n.apply(a,e),l||u||(e=a=null))};return function(){if(e=arguments,i=Ge(),a=this,f=p&&(l||!g),false===s)var r=g&&!l;else{u||g||(c=i);var y=s-(i-c),d=0>=y||y>s;d?(u&&(u=se(u)),c=i,o=n.apply(a,e)):u||(u=be(v,y)) -}return d&&l?l=se(l):l||t===s||(l=be(h,t)),r&&(d=true,o=n.apply(a,e)),!d||l||u||(e=a=null),o}}function jr(n){if(!Ar(n))throw new ne(E);return function(){return!n.apply(this,arguments)}}function kr(n){return Nt(n,Tr)}function Or(n){return n&&typeof n=="object"&&typeof n.length=="number"&&le.call(n)==G||false}function Er(n){return n&&typeof n=="object"&&1===n.nodeType&&(We.nodeClass?-1>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,i=r-1,e=Zr(r),a=0t||null==n||!Oe(t))return r;n=Qr(n);do t%2&&(r+=n),t=pe(t/2),n+=n;while(t);return r}function $r(n,t){return(n=null==n?"":Qr(n))?null==t?n.slice(h(n),v(n)+1):(t=Qr(t),n.slice(o(n,t),i(n,t)+1)):n -}function Pr(n,t,r){var e=typeof n,u="function"==e;return!u||typeof t!="undefined"&&"prototype"in n?u||null==n?_t(n,t,r):"object"==e?zr(n):qr(n):n}function Dr(n){return n}function zr(n){var t=Me(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||Sr(u)?function(e){var u=r;if(u&&!e)return false;for(;u--;){var o=t[u];if(!ve.call(e,o)||!Tt(e[o],n[o],null,true))return false}return true}:function(n){return n&&ve.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function Br(n,t,r){var e=true,u=t&&Nt(t,Me);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Nt(t,Me)),false===r?e=false:Sr(r)&&"chain"in r&&(e=r.chain),r=-1; -for(var o=Ar(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},U.assign=qe,U.at=function(t){return We.unindexedChars&&Nr(t)&&(t=t.split("")),n(t,Ot(arguments,true,false,1))},U.bind=xr,U.bindAll=function(n){for(var t=n,r=1arguments.length?Kt(t,b|_,null,n):Kt(t,b|_|C,null,n,er(arguments,2))},U.chain=function(n){return new V(n,true)},U.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?e(p,l):i(s,l))){for(t=u;--t;){var g=o[t]; -if(0>(g?e(g,l):i(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},U.invert=function(n,t){for(var r=-1,e=Me(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=U.createCallback(t,r,3)),Ct(n,function(n,r,u){if(o)for(r=t.length,u=Zr(r);r--;)u[r]=n[t[r]]; -else u=t(n,r,u);i[++e]={a:u,b:e,c:n}}),u=i.length,i.sort(o?l:a);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,r){return t.call(r,n),n},U.throttle=function(n,t,r){var e=true,u=true;if(!Ar(n))throw new ne(E);return false===r?e=false:Sr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),lt.leading=e,lt.maxWait=+t,lt.trailing=u,Cr(n,t,lt)},U.times=function(n,t,r){n=0>n?0:n>>>0,t=_t(t,r,1),r=-1;for(var e=Zr(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},U.escape=function(n){return null==n?"":Qr(n).replace(L,s)},U.escapeRegExp=Fr,U.every=cr,U.find=pr,U.findIndex=Gt,U.findKey=function(n,t,r){return t=U.createCallback(t,r,3),kt(n,t,It,true)},U.findLast=function(n,t,r){return t=U.createCallback(t,r,3),kt(n,t,jt) -},U.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=U.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},U.findLastKey=function(n,t,r){return t=U.createCallback(t,r,3),kt(n,t,Rt,true)},U.findWhere=function(n,t){return pr(n,zr(t))},U.has=function(n,t){return n?ve.call(n,t):false},U.identity=Dr,U.indexOf=Qt,U.isArguments=Or,U.isArray=Ze,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&le.call(n)==Q||false},U.isDate=function(n){return n&&typeof n=="object"&&le.call(n)==nt||false -},U.isElement=Er,U.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Se(e+r,0):Ie(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},U.noConflict=function(){return c._=ie,this},U.noop=Ur,U.now=Ge,U.pad=function(n,t,r){n=null==n?"":Qr(n),t=+t;var e=n.length; -return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},U.template=function(n,t,r){var e=U.templateSettings;r=qe({},r,e,gt),n=Qr(null==n?"":n);var u,o,i=qe({},r.imports,e.imports,gt),e=Me(i),i=Lr(i),a=0,l=r.interpolate||q,f="__p+='",l=Hr((r.escape||q).source+"|"+l.source+"|"+(l===$?P:q).source+"|"+(r.evaluate||q).source+"|$","g"); -return n.replace(l,function(t,r,e,i,l,c){return e||(e=i),f+=n.slice(a,c).replace(M,p),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),a=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(I,""):f).replace(R,"$1").replace(N,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}",r=zt(f,e,i,void 0),t?r(t):r -},U.trim=$r,U.trimLeft=function(n,t){return(n=null==n?"":Qr(n))?null==t?n.slice(h(n)):(t=Qr(t),n.slice(o(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Qr(n))?null==t?n.slice(0,v(n)+1):(t=Qr(t),n.slice(0,i(n,t)+1)):n},U.truncate=function(n,t){var r=30,e="...";if(t&&Sr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Qr(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Qr(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e; -if(Rr(u)){if(n.slice(o).search(u)){var i,a,l=n.slice(0,o);for(u.global||(u=Hr(u.source,(D.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(l);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(T,y))},U.uniqueId=function(n){var t=++A;return Qr(null==n?"":n)+t},U.all=cr,U.any=wr,U.detect=pr,U.foldl=mr,U.foldr=br,U.include=fr,U.inject=mr,Br(U,function(){var n={};return It(U,function(t,r){U.prototype[r]||(n[r]=t) -}),n}(),false),U.first=Ht,U.last=tr,U.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Lr(n):We.unindexedChars&&Nr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Ht,U.takeRight=tr,U.takeRightWhile=tr,U.takeWhile=Ht,U.head=Ht,It(U,function(n,t){var r="sample"!=t;U.prototype[t]||(U.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o}) -}),U.VERSION=k,U.prototype.chain=function(){return this.__chain__=true,this},U.prototype.toJSON=lr,U.prototype.toString=function(){return Qr(this.__wrapped__)},U.prototype.value=lr,U.prototype.valueOf=lr,ct(["join","pop","shift"],function(n){var t=te[n];U.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),ct(["push","reverse","sort","unshift"],function(n){var t=te[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ct(["concat","splice"],function(n){var t=te[n]; -U.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__)}}),We.spliceObjects||ct(["pop","shift","splice"],function(n){var t=te[n],r="splice"==n;U.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new V(u,n):u}}),U}var m,b=1,_=2,w=4,x=8,C=16,j=32,k="2.4.1",O="__lodash@"+k+"__",E="Expected a function",A=0,S=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,N=/(__e\(.*?\)|\b__t\))\+'';/g,T=/&(?:amp|lt|gt|quot|#39);/g,L=/[&<>"']/g,F=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,$=/<%=([\s\S]+?)%>/g,P=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,D=/\w*$/,z=/^\s*function[ \n\r\t]+\w/,B=/^0[xX]/,U=/[\xC0-\xFF]/g,q=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,M=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Y="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),G="[object Arguments]",H="[object Array]",Q="[object Boolean]",nt="[object Date]",tt="[object Error]",rt="[object Function]",et="[object Number]",ut="[object Object]",ot="[object RegExp]",it="[object String]",at={}; -at[rt]=false,at[G]=at[H]=at[Q]=at[nt]=at[et]=at[ut]=at[ot]=at[it]=true;var lt={leading:false,maxWait:0,trailing:false},ft={configurable:false,enumerable:false,value:null,writable:false},ct={"&":"&","<":"<",">":">",'"':""","'":"'"},st={"&":"&","<":"<",">":">",""":'"',"'":"'"},pt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},gt={"function":true,object:true},ht={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},vt=gt[typeof window]&&window||this,yt=gt[typeof exports]&&exports&&!exports.nodeType&&exports,gt=gt[typeof module]&&module&&!module.nodeType&&module,dt=yt&>&&typeof global=="object"&&global; -!dt||dt.global!==dt&&dt.window!==dt&&dt.self!==dt||(vt=dt);var dt=gt&>.exports===yt&&yt,mt=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(vt._=mt, define(function(){return mt})):yt&>?dt?(gt.exports=mt)._=mt:yt._=mt:vt._=mt}).call(this); \ No newline at end of file +;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=ue(e);++ra(t,l)&&f.push(l);return f}function Tt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1o?0:o>>>0);return Tt(n,function(n){var o=u?t:null!=n&&n[t];a[++e]=o?o.apply(n,r):m}),a}function Vt(n,t,r,e,u){var o=ar(t);return(o?jt:zt)(t,function(t,a,i){var l=t&&ar(t),f=t&&au(t),c=n[a];if(l||f){for(e||(e=[]),u||(u=[]),f=e.length;f--;)if(e[f]==t)return void(n[a]=u[f]);i=r?r(c,t,a,n,i):m,(f=typeof i!="undefined")||(i=l?ou(c)?c:[]:au(c)?c:{}),e.push(t),u.push(i),f||Vt(i,t,r,e,u),n[a]=i}else i=r?r(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i) +}),n}function Jt(n,t){var r={};if(typeof t=="function")return Dt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r;for(var e=-1,u=t.length;++ei(s,g)&&((u||f)&&s.push(g),c.push(p)) +}return c}function Gt(n,t){for(var r=-1,e=t(n),u=e.length,o=ue(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3o?0:o)}function gr(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?Ze(u+e,0):e||0;else if(e)return e=mr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function hr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),dr(n,0,0>o?0:o)}function vr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; +for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:m;return o=e-(o||0),dr(n,0>o?0:o)}function yr(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,r,3);++et?0:t;return dr(n,o)}function dr(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t?t=Ze(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=Ze(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=ue(u);++e>>1,r(n[e])r?0:r);++tr?Ze(e+r,0):r||0:0,typeof n=="string"||!ou(n)&&Kr(n)?ro&&(o=i)}else t=null==t&&Kr(n)?u:q.createCallback(t,r,3),Tt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Rr(n,t){return Sr(n,ee(t))}function Fr(n,t,r,e){var u=3>arguments.length; +if(t=q.createCallback(t,e,4),ou(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=q.createCallback(t,e,4),Wt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Lr(n){var t=-1,r=n&&n.length,e=ue(0>r?0:r>>>0);return Tt(n,function(n){var r=Xt(0,++t);e[t]=e[r],e[r]=n}),e}function Tr(n,t,r){var e;if((typeof t!="function"||typeof r!="undefined")&&(t=q.createCallback(t,r,3)),ou(n)){r=-1; +for(var u=n.length;++rarguments.length)return er(n,b,null,t);if(n)var r=n[A]?n[A][2]:n.length,e=dr(arguments,2),r=r-e.length;return er(n,b|x,r,t,e)}function Ur(n,t,r){function e(){var r=t-(pu()-f);0>=r||r>t?(i&&Ae(i),r=p,i=s=p=m,r&&(g=pu(),l=n.apply(c,a),s||i||(a=c=null))):s=Le(e,r)}function u(){s&&Ae(s),i=s=p=m,(v||h!==t)&&(g=pu(),l=n.apply(c,a),s||i||(a=c=null))}function o(){if(a=arguments,f=pu(),c=this,p=v&&(s||!y),false===h)var r=y&&!s; +else{i||y||(g=f);var o=h-(f-g),d=0>=o||o>h;d?(i&&(i=Ae(i)),g=f,l=n.apply(c,a)):i||(i=Le(u,o))}return d&&s?s=Ae(s):s||t===h||(s=Le(e,t)),r&&(d=true,l=n.apply(c,a)),!d||s||i||(a=c=null),l}var a,i,l,f,c,s,p,g=0,h=false,v=true;if(!zr(n))throw new pe(O);if(t=0>t?0:t,true===r)var y=true,v=false;else qr(r)&&(y=r.leading,h="maxWait"in r&&Ze(t,+r.maxWait||0),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&Ae(s),i&&Ae(i),i=s=p=m},o}function $r(n){if(!zr(n))throw new pe(O);return function(){return!n.apply(this,arguments) +}}function Pr(n){return Mt(n,Vr)}function Br(n){return n&&typeof n=="object"&&typeof n.length=="number"&&we.call(n)==H||false}function Dr(n){return n&&typeof n=="object"&&1===n.nodeType&&(Ge.nodeClass?-1>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,a=r-1,e=ue(r),i=0t||null==n||!ze(t))return r;n=se(n);do t%2&&(r+=n),t=Ee(t/2),n+=n;while(t);return r}function Gr(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n),v(n)+1):(t=se(t),n.slice(o(n,t),a(n,t)+1)):n}function Hr(n,t,r){var e=typeof n,u="function"==e;return!u||typeof t!="undefined"&&"prototype"in n?u||null==n?Ft(n,t,r):"object"==e?ne(n):ee(n):n +}function Qr(n){return n}function ne(n){var t=iu(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||qr(u)?function(e){var u=r;if(u&&!e)return false;for(;u--;){var o=t[u];if(!Ie.call(e,o)||!Zt(e[o],n[o],null,true))return false}return true}:function(n){return n&&Ie.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function te(n,t,r){var e=true,u=t&&Mt(t,iu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Mt(t,iu)),false===r?e=false:qr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=zr(n),a=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},q.assign=uu,q.at=function(t){return Ge.unindexedChars&&Kr(t)&&(t=t.split("")),n(t,$t(arguments,true,false,1))},q.bind=Wr,q.bindAll=function(n){for(var t=n,r=1arguments.length?er(t,b|_,null,n):er(t,b|_|x,null,n,dr(arguments,2)) +},q.chain=function(n){return new J(n,true)},q.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?e(p,l):a(s,l))){for(t=u;--t;){var g=o[t];if(0>(g?e(g,l):a(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},q.invert=function(n,t){for(var r=-1,e=iu(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=q.createCallback(t,r,3)),Tt(n,function(n,r,u){if(o)for(r=t.length,u=ue(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?l:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,r){return t.call(r,n),n},q.throttle=function(n,t,r){var e=true,u=true;if(!zr(n))throw new pe(O);return false===r?e=false:qr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),_t.leading=e,_t.maxWait=+t,_t.trailing=u,Ur(n,t,_t) +},q.times=function(n,t,r){n=0>n?0:n>>>0,t=Ft(t,r,1),r=-1;for(var e=ue(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},q.escape=function(n){return null==n?"":se(n).replace(L,s)},q.escapeRegExp=Xr,q.every=Cr,q.find=Ar,q.findIndex=sr,q.findKey=function(n,t,r){return t=q.createCallback(t,r,3),Ut(n,t,zt,true) +},q.findLast=function(n,t,r){return t=q.createCallback(t,r,3),Ut(n,t,Wt)},q.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=q.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},q.findLastKey=function(n,t,r){return t=q.createCallback(t,r,3),Ut(n,t,qt,true)},q.findWhere=function(n,t){return Ar(n,ne(t))},q.has=function(n,t){return n?Ie.call(n,t):false},q.identity=Qr,q.indexOf=gr,q.isArguments=Br,q.isArray=ou,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&we.call(n)==nt||false +},q.isDate=function(n){return n&&typeof n=="object"&&we.call(n)==tt||false},q.isElement=Dr,q.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Ze(e+r,0):Ke(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},q.noConflict=function(){return c._=_e,this},q.noop=re,q.now=pu,q.pad=function(n,t,r){n=null==n?"":se(n),t=+t; +var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},q.template=function(n,t,r){var e=q.templateSettings;r=uu({},r,e,kt),n=se(null==n?"":n);var u,o,a=uu({},r.imports,e.imports,kt),e=iu(a),a=Jr(a),i=0,l=r.interpolate||M,f="__p+='",l=ce((r.escape||M).source+"|"+l.source+"|"+(l===U?$:M).source+"|"+(r.evaluate||M).source+"|$","g"); +return n.replace(l,function(t,r,e,a,l,c){return e||(e=a),f+=n.slice(i,c).replace(V,p),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(I,""):f).replace(R,"$1").replace(F,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}",r=Ht(f,e,a),t?r(t):r +},q.trim=Gr,q.trimLeft=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n)):(t=se(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(0,v(n)+1):(t=se(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var r=30,e="...";if(t&&qr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?se(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":se(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e; +if(Zr(u)){if(n.slice(o).search(u)){var a,i,l=n.slice(0,o);for(u.global||(u=ce(u.source,(P.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(l);)i=a.index;r=r.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(N,y))},q.uniqueId=function(n){var t=++E;return se(null==n?"":n)+t},q.all=Cr,q.any=Tr,q.detect=Ar,q.foldl=Fr,q.foldr=Nr,q.include=xr,q.inject=Fr,te(q,function(){var n={};return zt(q,function(t,r){q.prototype[r]||(n[r]=t) +}),n}(),false),q.first=pr,q.last=vr,q.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Jr(n):Ge.unindexedChars&&Kr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=pr,q.takeRight=vr,q.takeRightWhile=vr,q.takeWhile=pr,q.head=pr,zt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o}) +}),q.VERSION=k,q.prototype.chain=function(){return this.__chain__=true,this},q.prototype.toJSON=jr,q.prototype.toString=function(){return se(this.__wrapped__)},q.prototype.value=jr,q.prototype.valueOf=jr,jt(["join","pop","shift"],function(n){var t=ge[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),jt(["push","reverse","sort","unshift"],function(n){var t=ge[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),jt(["concat","splice"],function(n){var t=ge[n]; +q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Ge.spliceObjects||jt(["pop","shift","splice"],function(n){var t=ge[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,x=16,C=32,k="2.5.0-pre",A="__lodash@"+k+"__",O="Expected a function",E=0,S=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,N=/&(?:amp|lt|gt|quot|#39|#96);/g,L=/[&<>"'`]/g,T=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,U=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float64Array Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",gt="[object Int32Array]",ht="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; +mt[H]=mt[Q]=mt[ft]=mt[ct]=mt[st]=mt[pt]=mt[gt]=mt[ht]=mt[vt]=mt[yt]=mt[dt]=true,mt[lt]=mt[nt]=mt[tt]=mt[rt]=mt[et]=mt["[object Map]"]=mt[ut]=mt[ot]=mt[at]=mt["[object Set]"]=mt[it]=mt["[object WeakMap]"]=false;var bt={};bt[H]=bt[Q]=bt[lt]=bt[nt]=bt[tt]=bt[rt]=bt[ft]=bt[ct]=bt[st]=bt[pt]=bt[gt]=bt[ut]=bt[ot]=bt[at]=bt[it]=bt[ht]=bt[vt]=bt[yt]=bt[dt]=true,bt[et]=bt["[object Map]"]=bt["[object Set]"]=bt["[object WeakMap]"]=false;var _t={leading:false,maxWait:0,trailing:false},wt={configurable:false,enumerable:false,value:null,writable:false},jt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},xt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},kt={"function":true,object:true},At={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ot=kt[typeof window]&&window||this,Et=kt[typeof exports]&&exports&&!exports.nodeType&&exports,kt=kt[typeof module]&&module&&!module.nodeType&&module,St=Et&&kt&&typeof global=="object"&&global; +!St||St.global!==St&&St.window!==St&&St.self!==St||(Ot=St);var St=kt&&kt.exports===Et&&Et,It=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ot._=It, define(function(){return It})):Et&&kt?St?(kt.exports=It)._=It:Et._=It:Ot._=It}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 7611f17dd8..034294890d 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) + * Lo-Dash 2.5.0-pre (Custom Build) * Build: `lodash modern -o ./dist/lodash.js` * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 @@ -21,7 +21,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.4.1'; + var version = '2.5.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; @@ -41,8 +41,8 @@ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, - reUnescapedHtml = /[&<>"']/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, + reUnescapedHtml = /[&<>"'`]/g; /** Used to match template delimiters */ var reEscape = /<%-([\s\S]+?)%>/g, @@ -65,6 +65,9 @@ /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; + /** Used to detect host constructors (Safari > 5) */ + var reHostCtor = /^\[object .+?Constructor\]$/; + /** Used to match latin-1 supplement letters */ var reLatin1 = /[\xC0-\xFF]/g; @@ -101,9 +104,10 @@ /** Used to assign default `context` object properties */ var contextProps = [ - 'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object', - 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', - 'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError' + 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Float64Array', 'Function', + 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', + 'document', 'isFinite', 'isNaN','parseInt', 'setTimeout', 'TypeError', + 'Uint8Array', 'window', 'WinRTError' ]; /** Used to make template sourceURLs easier to identify */ @@ -116,18 +120,54 @@ dateClass = '[object Date]', errorClass = '[object Error]', funcClass = '[object Function]', + mapClass = '[object Map]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', - stringClass = '[object String]'; + setClass = '[object Set]', + stringClass = '[object String]', + weakMapClass = '[object WeakMap]'; + + var arrayBufferClass = '[object ArrayBuffer]', + float32Class = '[object Float32Array]', + float64Class = '[object Float64Array]', + int8Class = '[object Int8Array]', + int16Class = '[object Int16Array]', + int32Class = '[object Int32Array]', + uint8Class = '[object Uint8Array]', + uint8ClampedClass = '[object Uint8ClampedArray]', + uint16Class = '[object Uint16Array]', + uint32Class = '[object Uint32Array]'; + + /** Used to identify object classifications that are treated like arrays */ + var arrayLikeClasses = {}; + arrayLikeClasses[argsClass] = + arrayLikeClasses[arrayClass] = arrayLikeClasses[float32Class] = + arrayLikeClasses[float64Class] = arrayLikeClasses[int8Class] = + arrayLikeClasses[int16Class] = arrayLikeClasses[int32Class] = + arrayLikeClasses[uint8Class] = arrayLikeClasses[uint8ClampedClass] = + arrayLikeClasses[uint16Class] = arrayLikeClasses[uint32Class] = true; + arrayLikeClasses[arrayBufferClass] = arrayLikeClasses[boolClass] = + arrayLikeClasses[dateClass] = arrayLikeClasses[errorClass] = + arrayLikeClasses[funcClass] = arrayLikeClasses[mapClass] = + arrayLikeClasses[numberClass] = arrayLikeClasses[objectClass] = + arrayLikeClasses[regexpClass] = arrayLikeClasses[setClass] = + arrayLikeClasses[stringClass] = arrayLikeClasses[weakMapClass] = false; /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; - cloneableClasses[funcClass] = false; - cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[argsClass] = + cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] = + cloneableClasses[errorClass] = cloneableClasses[float32Class] = + cloneableClasses[float64Class] = cloneableClasses[int8Class] = + cloneableClasses[int16Class] = cloneableClasses[int32Class] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = - cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; + cloneableClasses[regexpClass] = cloneableClasses[stringClass] = + cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] = + cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true; + cloneableClasses[funcClass] = cloneableClasses[mapClass] = + cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false; /** Used as an internal `_.debounce` options object by `_.throttle` */ var debounceOptions = { @@ -148,17 +188,23 @@ * Used to convert characters to HTML entities. * * Note: Though the ">" character is escaped for symmetry, characters like - * ">", "`", and "/" don't require escaping in HTML and have no special meaning + * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. + * + * Backticks are escaped because in Internet Explorer < 9, they can be used to + * break out of attribute values or HTML comments. See [#102](http://html5sec.org/#102), + * [#108](http://html5sec.org/#108), and [#133](http://html5sec.org/#133) of + * the [HTML5 Security Cheatsheet](http://html5sec.org/) for more details. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', - "'": ''' + "'": ''', + '`': '`' }; /** Used to convert HTML entities to characters */ @@ -167,7 +213,8 @@ '<': '<', '>': '>', '"': '"', - ''': "'" + ''': "'", + '`': '`' }; /** @@ -546,11 +593,9 @@ /** Native constructor references */ var Array = context.Array, - Boolean = context.Boolean, Date = context.Date, Function = context.Function, Math = context.Math, - Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, @@ -564,8 +609,8 @@ /** Used to detect DOM support */ var document = (document = context.window) && document.document; - /** Used to restore the original `_` reference in `_.noConflict` */ - var oldDash = context._; + /** Used to resolve the decompiled source of functions */ + var fnToString = Function.prototype.toString; /** * Used as the maximum length of an array-like object. @@ -574,6 +619,9 @@ */ var maxSafeInteger = Math.pow(2, 53) - 1; + /** Used to restore the original `_` reference in `_.noConflict` */ + var oldDash = context._; + /** Used to resolve the internal `[[Class]]` of values */ var toString = objectProto.toString; @@ -584,10 +632,12 @@ ); /** Native method shortcuts */ - var ceil = Math.ceil, + var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, + bufferSlice = isNative(bufferSlice = ArrayBuffer && (new ArrayBuffer).slice) && bufferSlice, + ceil = Math.ceil, clearTimeout = context.clearTimeout, + Float64Array = isNative(Float64Array = context.Float64Array) && Float64Array, floor = Math.floor, - fnToString = Function.prototype.toString, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, @@ -595,6 +645,7 @@ Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, unshift = arrayProto.unshift; /** Used to set metadata on functions */ @@ -621,17 +672,6 @@ nativeParseInt = context.parseInt, nativeRandom = Math.random; - /** Used to lookup built-in constructors by `[[Class]]` */ - var ctorByClass = {}; - ctorByClass[arrayClass] = Array; - ctorByClass[boolClass] = Boolean; - ctorByClass[dateClass] = Date; - ctorByClass[funcClass] = Function; - ctorByClass[objectClass] = Object; - ctorByClass[numberClass] = Number; - ctorByClass[regexpClass] = RegExp; - ctorByClass[stringClass] = String; - /*--------------------------------------------------------------------------*/ /** @@ -685,15 +725,11 @@ * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value - * wrapped.reduce(function(sum, num) { - * return sum + num; - * }); + * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value - * var squares = wrapped.map(function(num) { - * return num * num; - * }); + * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false @@ -951,9 +987,6 @@ * @returns {Object} Returns the destination object. */ function baseAssign(object, source, callback) { - if (!object) { - return object; - } var index = -1, props = keys(source), length = props.length; @@ -1031,18 +1064,32 @@ if (!cloneableClasses[className]) { return value; } - var ctor = ctorByClass[className]; + var Ctor = value.constructor; + if (className == objectClass && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { + Ctor = Object; + } switch (className) { + case arrayBufferClass: + return cloneBuffer(value); + case boolClass: case dateClass: - return new ctor(+value); + return new Ctor(+value); + + case errorClass: + return new Ctor(value.message); + + case float32Class: case float64Class: + case int8Class: case int16Class: case int32Class: + case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: + return value.subarray(0); case numberClass: case stringClass: - return new ctor(value); + return new Ctor(value); case regexpClass: - result = ctor(value.source, reFlags.exec(value)); + result = Ctor(value.source, reFlags.exec(value)); result.lastIndex = value.lastIndex; return result; } @@ -1061,7 +1108,7 @@ return stackB[length]; } } - result = isArr ? ctor(value.length) : {}; + result = isArr ? Ctor(value.length) : Ctor(); } else { result = isArr ? slice(value) : baseAssign({}, value); @@ -1165,15 +1212,15 @@ case 1: return function(value) { return func.call(thisArg, value); }; - case 2: return function(value, other) { - return func.call(thisArg, value, other); - }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); }; case 4: return function(accumulator, value, index, collection) { return func.call(thisArg, accumulator, value, index, collection); }; + case 5: return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; } return bind(func, thisArg); } @@ -1527,7 +1574,7 @@ * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. + * @param {boolean} [isWhere=false] A flag to indicate performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. @@ -1578,13 +1625,15 @@ // but treat `-0` vs. `+0` as not equal : (value == 0 ? (1 / value == 1 / other) : value == +other); + case errorClass: case regexpClass: case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) + // coerce errors (http://es5.github.io/#x15.11.4.4) + // and regexes (http://es5.github.io/#x15.10.6.4) to strings // treat string primitives and their corresponding object instances as equal return value == String(other); } - var isArr = valClass == arrayClass; + var isArr = arrayLikeClasses[valClass]; if (!isArr) { // exit for functions and DOM nodes if (valClass != objectClass) { @@ -1746,11 +1795,9 @@ * @returns {Object} Returns the destination object. */ function baseMerge(object, source, callback, stackA, stackB) { - if (!object) { - return object; - } - (isArray(source) ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { - var isArr = srcValue && isArray(srcValue), + var isSrcArr = isArrayLike(source); + (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { + var isArr = srcValue && isArrayLike(srcValue), isObj = srcValue && isPlainObject(srcValue), value = object[key]; @@ -1759,10 +1806,9 @@ if (typeof result == 'undefined') { result = srcValue; } - if (typeof result != 'undefined') { - value = result; + if (isSrcArr || typeof result != 'undefined') { + object[key] = result; } - object[key] = value; return; } // avoid merging previously merged cyclic sources @@ -1779,22 +1825,21 @@ var result = callback ? callback(value, srcValue, key, object, source) : undefined, isShallow = typeof result != 'undefined'; - if (isShallow) { - value = result; - } else { - value = isArr + if (!isShallow) { + result = isArr ? (isArray(value) ? value : []) : (isPlainObject(value) ? value : {}); } - // add `source` and associated `value` to the stack of traversed objects + // add the source value to the stack of traversed objects + // and associate it with its merged value stackA.push(srcValue); - stackB.push(value); + stackB.push(result); // recursively merge objects and arrays (susceptible to call stack limits) if (!isShallow) { - baseMerge(value, srcValue, callback, stackA, stackB); + baseMerge(result, srcValue, callback, stackA, stackB); } - object[key] = value; + object[key] = result; }); return object; @@ -1957,7 +2002,7 @@ /** * Compiles a function from `source` using the `varNames` and `varValues` * pairs to import free variables into the compiled function. If `sourceURL` - * is provided it will be used as the sourceURL for the compiled function. + * is provided it is used as the sourceURL for the compiled function. * * @private * @param {string} source The source to compile. @@ -2046,7 +2091,7 @@ * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection * through a callback. The given setter function sets the keys and values of - * the accumulator object. If `initializer` is provided it will be used to + * the accumulator object. If `initializer` is provided it is used to * initialize the accumulator object. * * @private @@ -2099,7 +2144,7 @@ } // juggle arguments if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 2); + var callback = baseCreateCallback(args[--length - 1], args[length--], 5); } else if (length > 2 && typeof args[length - 1] == 'function') { callback = args[--length]; } @@ -2288,6 +2333,18 @@ return result === indexOf ? baseIndexOf : result; } + /** + * Checks if `value` is an array-like object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. + */ + function isArrayLike(value) { + return (value && typeof value == 'object' && typeof value.length == 'number' && + arrayLikeClasses[toString.call(value)]) || false; + } + /** * Checks if `value` is a native function. * @@ -2296,7 +2353,40 @@ * @returns {boolean} Returns `true` if `value` is a native function, else `false`. */ function isNative(value) { - return typeof value == 'function' && reNative.test(fnToString.call(value)); + var type = typeof value; + return type == 'function' + ? reNative.test(fnToString.call(value)) + : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; + } + + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneBuffer(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` + cloneBuffer = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / 8) : 0, + offset = floatLength * 8, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; } /** @@ -2322,13 +2412,13 @@ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { - var ctor, + var Ctor, result; // avoid non `Object` objects, `arguments` objects, and DOM elements if (!(value && toString.call(value) == objectClass) || (!hasOwnProperty.call(value, 'constructor') && - (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor)))) { + (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor)))) { return false; } // In most environments an object's own properties are iterated before @@ -2483,14 +2573,14 @@ /** * Creates a slice of `array` excluding elements dropped from the end. - * Elements will be dropped until the predicate returns falsey. The predicate - * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * Elements are dropped until the predicate returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2503,9 +2593,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.dropRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); + * _.dropRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [1] * * var characters = [ @@ -2526,14 +2614,14 @@ /** * Creates a slice of `array` excluding elements dropped from the beginning. - * Elements will be dropped until the predicate returns falsey. The predicate - * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * Elements are dropped until the predicate returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2546,9 +2634,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.dropWhile([1, 2, 3], function(num) { - * return num < 3; - * }); + * _.dropWhile([1, 2, 3], function(n) { return n < 3; }); * // => [3] * * var characters = [ @@ -2572,10 +2658,10 @@ * element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2583,8 +2669,8 @@ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example @@ -2626,10 +2712,10 @@ * of a collection from right to left. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2637,8 +2723,8 @@ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example @@ -2715,16 +2801,16 @@ /** * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truthy, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before + * is truthy, the array is only flattened a single level. If a callback is + * provided each element of the array is passed through the callback before * flattening. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2733,7 +2819,7 @@ * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new flattened array. @@ -2781,7 +2867,7 @@ /** * Gets the index at which the first occurrence of `value` is found using * strict equality for comparisons, i.e. `===`. If the array is already sorted - * providing `true` for `fromIndex` will run a faster binary search. + * providing `true` for `fromIndex` performs a faster binary search. * * @static * @memberOf _ @@ -3050,10 +3136,10 @@ * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * Note: Unlike `_.filter`, this method mutates `array`. @@ -3063,14 +3149,14 @@ * @category Arrays * @param {Array} array The array to modify. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [1, 2, 3, 4]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * var evens = _.remove(array, function(n) { return n % 2 == 0; }); * * console.log(array); * // => [1, 3] @@ -3172,15 +3258,15 @@ /** * Uses a binary search to determine the smallest index at which a value * should be inserted into a given sorted array in order to maintain the sort - * order of the array. If a callback is provided it will be executed for - * `value` and each element of `array` to compute their sort ranking. The - * callback is bound to `thisArg` and invoked with one argument; (value). + * order of the array. If a callback is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The callback + * is bound to `thisArg` and invoked with one argument; (value). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3189,8 +3275,8 @@ * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. @@ -3289,15 +3375,15 @@ var takeRight = last; /** - * Creates a slice of `array` with elements taken from the end. Elements will - * be taken until the predicate returns falsey. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until the predicate returns falsey. The predicate is bound to `thisArg` + * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3310,9 +3396,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.takeRightWhile([1, 2, 3], function(num) { - * return num > 1; - * }); + * _.takeRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [2, 3] * * var characters = [ @@ -3333,14 +3417,14 @@ /** * Creates a slice of `array` with elements taken from the beginning. Elements - * will be taken until the predicate returns falsey. The predicate is bound - * to `thisArg` and invoked with three arguments; (value, index, array). + * are taken until the predicate returns falsey. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3353,9 +3437,7 @@ * @returns {Array} Returns the slice of `array`. * @example * - * _.takeWhile([1, 2, 3], function(num) { - * return num < 3; - * }); + * _.takeWhile([1, 2, 3], function(n) { return n < 3; }); * // => [1, 2] * * var characters = [ @@ -3394,17 +3476,17 @@ /** * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing `true` for - * `isSorted` will use a faster algorithm. If a callback is provided it will - * be executed for each value in the array to generate the criterion by which - * uniqueness is computed. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index, array). + * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a + * faster search algorithm for sorted arrays. If a callback is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3414,26 +3496,26 @@ * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new duplicate-value-free array. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] + * _.uniq([1, 2, 1]); + * // => [1, 2] * * // using `isSorted` - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] + * _.uniq([1, 1, 2], true); + * // => [1, 2] * * // using `callback` - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] + * _.uniq(['A', 'b', 'a', 'B'], function(chr) { return chr.toLowerCase(); }); + * // => ['A', 'b'] * * // using `callback` with `thisArg` - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] + * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); + * // => [1, 2.5] * * // using "_.pluck" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); @@ -3518,7 +3600,7 @@ * Creates an array of grouped elements, the first of which contains the first * elements of the given arrays, the second of which contains the second elements * of the given arrays, and so on. If a zipped value is provided its corresponding - * unzipped value will be returned. + * unzipped value is returned. * * @static * @memberOf _ @@ -3785,10 +3867,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3796,16 +3878,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * - * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); @@ -3821,10 +3903,10 @@ * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3833,8 +3915,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements passed the predicate check, * else `false`. @@ -3886,10 +3968,10 @@ * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3898,13 +3980,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * - * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [2, 4] * * var characters = [ @@ -3950,10 +4032,10 @@ * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3962,8 +4044,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example @@ -4007,15 +4089,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * - * _.findLast([1, 2, 3, 4], function(num) { - * return num % 2 == 1; - * }); + * _.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1; }); * // => 3 */ function findLast(collection, predicate, thisArg) { @@ -4071,10 +4151,10 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEach(function(n) { console.log(n); }).join(','); * // => logs each number and returns '1,2,3' * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { console.log(n); }); * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { @@ -4102,7 +4182,7 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each number from right to left and returns '3,2,1' */ function forEachRight(collection, callback, thisArg) { @@ -4124,10 +4204,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4135,16 +4215,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using "_.pluck" callback shorthand @@ -4167,10 +4247,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4178,8 +4258,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -4205,8 +4285,8 @@ /** * Invokes the method named by `methodName` on each element in the collection * returning an array of the results of each invoked method. Additional arguments - * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the collection. + * is provided to each invoked method. If `methodName` is a function it is + * invoked for, and `this` bound to, each element in the collection. * * @static * @memberOf _ @@ -4234,10 +4314,10 @@ * three arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4246,16 +4326,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new mapped array. * @example * - * _.map([1, 2, 3], function(num) { return num * 3; }); + * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); * // => [3, 6, 9] (property order is not guaranteed across environments) * * var characters = [ @@ -4284,17 +4364,17 @@ } /** - * Retrieves the maximum value of a collection. If the collection is empty or - * falsey `-Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Retrieves the maximum value of a collection. If the collection is empty + * or falsey `-Infinity` is returned. If a callback is provided it is executed + * for each value in the collection to generate the criterion by which the + * value is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4302,7 +4382,7 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the maximum value. @@ -4362,17 +4442,17 @@ } /** - * Retrieves the minimum value of a collection. If the collection is empty or - * falsey `Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Retrieves the minimum value of a collection. If the collection is empty + * or falsey `Infinity` is returned. If a callback is provided it is executed + * for each value in the collection to generate the criterion by which the + * value is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4380,7 +4460,7 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the minimum value. @@ -4446,10 +4526,10 @@ * to `thisArg` and invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4457,16 +4537,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the array of grouped elements. * @example * - * _.partition([1, 2, 3], function(num) { return num % 2; }); + * _.partition([1, 2, 3], function(n) { return n % 2; }); * // => [[1, 3], [2]] * - * _.partition([1.2, 2.3, 3.4], function(num) { return this.floor(num) % 2; }, Math); + * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); * // => [[1, 3], [2]] * * var characters = [ @@ -4514,9 +4594,9 @@ * Reduces a collection to a value which is the accumulated result of running * each element in the collection through the callback, where each successive * callback execution consumes the return value of the previous execution. If - * `accumulator` is not provided the first element of the collection will be - * used as the initial `accumulator` value. The callback is bound to `thisArg` - * and invoked with four arguments; (accumulator, value, index|key, collection). + * `accumulator` is not provided the first element of the collection is used + * as the initial `accumulator` value. The callback is bound to `thisArg` and + * invoked with four arguments; (accumulator, value, index|key, collection). * * @static * @memberOf _ @@ -4529,13 +4609,11 @@ * @returns {*} Returns the accumulated value. * @example * - * var sum = _.reduce([1, 2, 3], function(sum, num) { - * return sum + num; - * }); + * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * - * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } @@ -4600,10 +4678,10 @@ * the predicate does **not** return truthy for. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4611,13 +4689,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * - * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [1, 3] * * var characters = [ @@ -4731,10 +4809,10 @@ * with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4743,8 +4821,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. @@ -4793,18 +4871,18 @@ /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through the callback. This method - * performs a stable sort, that is, it will preserve the original sort order - * of equal elements. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an array of property names is provided for `callback` the collection - * will be sorted by each property value. + * is sorted by each property value. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -4812,16 +4890,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it will - * be used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If a property name or object is provided it is + * used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example * - * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * - * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * * var characters = [ @@ -5002,7 +5080,7 @@ * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays * of method names. If no method names are provided all enumerable function - * properties, own and inherited, of `object` will be bound. + * properties, own and inherited, of `object` are bound. * * Note: This method does not set the `length` property of bound functions. * @@ -5054,7 +5132,7 @@ * Creates a function that invokes the method at `object[key]` and prepends * any additional `bindKey` arguments to those provided to the bound function. * This method differs from `_.bind` by allowing bound functions to reference - * methods that will be redefined or don't yet exist. + * methods that may be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * @@ -5180,14 +5258,15 @@ } /** - * Creates a function that will delay the execution of `func` until after - * `wait` milliseconds have elapsed since the last time it was invoked. - * 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 will return the result of the last `func` call. + * Creates a function that delays the execution of `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 calls. 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` call. * - * Note: If `leading` and `trailing` options are `true`, `func` will be called - * on the trailing edge of the timeout only if the the debounced function is + * Note: If `leading` and `trailing` options are `true`, `func` is called on + * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * * @static @@ -5203,8 +5282,7 @@ * @example * * // avoid costly calculations while the window size is in flux - * var lazyLayout = _.debounce(calculateLayout, 150); - * jQuery(window).on('resize', lazyLayout); + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // execute `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { @@ -5214,9 +5292,26 @@ * * // ensure `batchLog` is executed once after 1 second of debounced calls * var source = new EventSource('/stream'); - * source.addEventListener('message', _.debounce(batchLog, 250, { + * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * }, false); + * + * // cancel a debounced call + * var todoChanges = _.debounce(batchLog, 1000); + * Object.observe(models.todo, todoChanges); + * + * Object.observe(models, function(changes) { + * if (_.find(changes, { 'name': 'todo', 'type': 'delete'})) { + * todoChanges.cancel(); + * } + * }, ['delete']); + * + * // ...at some point `models.todo` is changed + * models.todo.completed = true; + * + * // ...before 1 second has passed `models.todo` is deleted + * // which cancels the debounced `todoChanges` call + * delete models.todo; */ function debounce(func, wait, options) { var args, @@ -5242,7 +5337,18 @@ maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); trailing = 'trailing' in options ? options.trailing : trailing; } - var delayed = function() { + + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + } + + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { if (maxTimeoutId) { @@ -5260,9 +5366,9 @@ } else { timeoutId = setTimeout(delayed, remaining); } - }; + } - var maxDelayed = function() { + function maxDelayed() { if (timeoutId) { clearTimeout(timeoutId); } @@ -5274,9 +5380,9 @@ args = thisArg = null; } } - }; + } - return function() { + function debounced() { args = arguments; stamp = now(); thisArg = this; @@ -5316,12 +5422,14 @@ args = thisArg = null; } return result; - }; + } + debounced.cancel = cancel; + return debounced; } /** - * Defers executing the `func` function until the current call stack has cleared. - * Additional arguments will be provided to `func` when it is invoked. + * Defers executing the `func` function until the current call stack has + * cleared. Additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -5344,7 +5452,7 @@ /** * Executes the `func` function after `wait` milliseconds. Additional arguments - * will be provided to `func` when it is invoked. + * are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -5368,11 +5476,11 @@ /** * Creates a function that memoizes the result of `func`. If `resolver` is - * provided it will be used to determine the cache key for storing the result - * based on the arguments provided to the memoized function. By default, the - * first argument provided to the memoized function is used as the cache key. - * The `func` is executed with the `this` binding of the memoized function. - * The result cache is exposed as the `cache` property on the memoized function. + * provided it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the cache key. The `func` is + * executed with the `this` binding of the memoized function. The result cache + * is exposed as the `cache` property on the memoized function. * * @static * @memberOf _ @@ -5431,8 +5539,8 @@ * @returns {Function} Returns the new function. * @example * - * function isEven(num) { - * return num % 2 == 0; + * function isEven(n) { + * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); @@ -5448,8 +5556,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls to - * the function will return the value of the first call. The `func` is executed + * Creates a function that is restricted to execute `func` once. Repeat calls + * to the function return the value of the first call. The `func` is executed * with the `this` binding of the created function. * * @static @@ -5551,14 +5659,15 @@ } /** - * Creates a function that, when executed, will only call the `func` function - * at most once per every `wait` milliseconds. 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 will - * return the result of the last `func` call. + * Creates a function that only calls the `func` function at most once per + * every `wait` milliseconds. The created function comes with a `cancel` method + * to cancel delayed calls. 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` will be called - * on the trailing edge of the timeout only if the the throttled function is + * Note: If `leading` and `trailing` options are `true`, `func` is called on + * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * * @static @@ -5573,13 +5682,14 @@ * @example * * // avoid excessively updating the position while scrolling - * var throttled = _.throttle(updatePosition, 100); - * jQuery(window).on('scroll', throttled); + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes - * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { - * 'trailing': false - * })); + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) + * jQuery('.interactive').on('click', throttled); + * + * // cancel a trailing throttled call + * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { var leading = true, @@ -5630,10 +5740,10 @@ /** * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with - * five arguments; (objectValue, sourceValue, key, object, source). + * object. Subsequent sources overwrite property assignments of previous + * sources. If a callback is provided it is executed to produce the assigned + * values. The callback is bound to `thisArg` and invoked with five arguments; + * (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -5646,24 +5756,24 @@ * @returns {Object} Returns the destination object. * @example * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } + * _.assign({ 'name': 'fred' }, { 'age': 40 }, { 'employer': 'slate' }); + * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' } * * var defaults = _.partialRight(_.assign, function(value, other) { * return typeof value == 'undefined' ? other : value; * }); * - * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ var assign = createAssigner(baseAssign); /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects will also - * be cloned, otherwise they will be assigned by reference. If a callback - * is provided it will be executed to produce the cloned values. If the - * callback returns `undefined` cloning will be handled by the method instead. - * The callback is bound to `thisArg` and invoked with two argument; (value, index|key). + * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, + * otherwise they are assigned by reference. If a callback is provided it is + * executed to produce the cloned values. If the callback returns `undefined` + * cloning is handled by the method instead. The callback is bound to `thisArg` + * and invoked with two argument; (value, index|key). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and @@ -5723,10 +5833,10 @@ } /** - * Creates a deep clone of `value`. If a callback is provided it will be - * executed to produce the cloned values. If the callback returns `undefined` - * cloning will be handled by the method instead. The callback is bound to - * `thisArg` and invoked with two argument; (value, index|key). + * Creates a deep clone of `value`. If a callback is provided it is executed + * to produce the cloned values. If the callback returns `undefined` cloning + * is handled by the method instead. The callback is bound to `thisArg` and + * invoked with two argument; (value, index|key). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and @@ -5808,7 +5918,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. + * property is set, additional defaults of the same property are ignored. * * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. @@ -5822,8 +5932,8 @@ * @returns {Object} Returns the destination object. * @example * - * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { if (!object) { @@ -5839,10 +5949,10 @@ * first element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -5850,8 +5960,8 @@ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example @@ -5885,10 +5995,10 @@ * a collection in the opposite order. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -5896,8 +6006,8 @@ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example @@ -6005,7 +6115,7 @@ * @returns {Object} Returns `object`. * @example * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) @@ -6030,7 +6140,7 @@ * @returns {Object} Returns `object`. * @example * - * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' @@ -6081,7 +6191,7 @@ /** * Creates an object composed of the inverted keys and values of the given * object. If the given object contains duplicate values, subsequent values - * will overwrite property assignments of previous values unless `multiValue` + * overwrite property assignments of previous values unless `multiValue` * is `true`. * * @static @@ -6285,10 +6395,10 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If a callback is provided it will be executed to compare - * values. If the callback returns `undefined` comparisons will be handled - * by the method instead. The callback is bound to `thisArg` and invoked - * with three arguments; (value, other, key). + * equivalent. If a callback is provided it is executed to compare values. + * If the callback returns `undefined` comparisons are handled by the method + * instead. The callback is bound to `thisArg` and invoked with three arguments; + * (value, other, key). * * Note: This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes @@ -6323,7 +6433,7 @@ * // => true */ function isEqual(value, other, callback, thisArg) { - callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2); + callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 3); if (!callback) { // exit early for identical values @@ -6367,7 +6477,7 @@ /** * Checks if `value` is, or can be coerced to, a finite number. * - * Note: This method is not the same as native `isFinite` which will return + * Note: This method is not the same as native `isFinite` which returns * `true` for booleans and empty strings. See the [ES5 spec](http://es5.github.io/#x15.1.2.5) * for more details. * @@ -6451,7 +6561,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which will return `true` + * Note: This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -6653,11 +6763,11 @@ * // => ['x', 'y'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { - var ctor = object && object.constructor, + var Ctor = object && object.constructor, length = object ? object.length : 0; - if ((typeof length == 'number' && length > 0) || - (ctor && object === ctor.prototype)) { + if ((Ctor && object === Ctor.prototype) || + (typeof length == 'number' && length > 0)) { return shimKeys(object); } return isObject(object) ? nativeKeys(object) : []; @@ -6692,9 +6802,9 @@ (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) >>> 0; var keyIndex, - ctor = object.constructor, + Ctor = object.constructor, index = -1, - isProto = ctor && object === ctor.prototype, + isProto = Ctor && object === Ctor.prototype, maxIndex = length - 1, result = Array(length), skipIndexes = length > 0; @@ -6718,10 +6828,10 @@ * (value, key, object). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -6729,13 +6839,13 @@ * @category Objects * @param {Object} object The object to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the new mapped object. * @example * - * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); + * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(n) { return n * 3; }); * // => { 'a': 3, 'b': 6, 'c': 9 } * * var characters = { @@ -6760,11 +6870,11 @@ /** * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources - * will overwrite property assignments of previous sources. If a callback is - * provided it will be executed to produce the merged values of the destination - * and source properties. If the callback returns `undefined` merging will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with five arguments; (objectValue, sourceValue, key, object, source). + * overwrite property assignments of previous sources. If a callback is provided + * it is executed to produce the merged values of the destination and source + * properties. If the callback returns `undefined` merging is handled by the + * method instead. The callback is bound to `thisArg` and invoked with five + * arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -6813,9 +6923,9 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` omitting the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it is executed for each property + * of `object` omitting the properties the predicate returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static @@ -6883,9 +6993,9 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` picking the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it is executed for each property + * of `object` picking the properties the predicate returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static @@ -6934,28 +7044,28 @@ * @returns {*} Returns the accumulated value. * @example * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; + * var squares = _.transform([1, 2, 3, 4, 5, 6], function(result, n) { + * n *= n; + * if (n % 2) { + * return result.push(n) < 3; * } * }); * // => [1, 9, 25] * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); + var isArr = isArrayLike(object); if (accumulator == null) { if (isArr) { accumulator = []; } else { if (isObject(object)) { - var ctor = object.constructor, - proto = ctor && ctor.prototype; + var Ctor = object.constructor, + proto = Ctor && Ctor.prototype; } accumulator = baseCreate(proto); } @@ -7356,9 +7466,9 @@ * Creates a compiled template function that can interpolate data properties * in "interpolate" delimiters, HTML-escaped interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. If - * a data object is provided the interpolated template string will be returned. + * a data object is provided the interpolated template string is returned. * Data properties may be accessed as free variables in the template. If a - * settings object is provided it will override `_.templateSettings` for the + * settings object is provided it overrides `_.templateSettings` for the * template. * * Note: In the development build, `_.template` utilizes sourceURLs for easier debugging. @@ -7622,8 +7732,8 @@ /** * Truncates `string` if it is longer than the given maximum string length. - * The last characters of the truncated string will be replaced with the - * omission string which defaults to "...". + * The last characters of the truncated string are replaced with the omission + * string which defaults to "...". * * @static * @memberOf _ @@ -7636,22 +7746,22 @@ * @returns {string} Returns the truncated string. * @example * - * _.truncate('hi-diddly-ho there, neighborino'); + * _.trunc('hi-diddly-ho there, neighborino'); * // => 'hi-diddly-ho there, neighbo...' * - * _.truncate('hi-diddly-ho there, neighborino', 24); + * _.trunc('hi-diddly-ho there, neighborino', 24); * // => 'hi-diddly-ho there, n...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); * // => 'hi-diddly-ho there,...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); + * _.trunc('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); * //=> 'hi-diddly-ho there...' * - * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); + * _.trunc('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); * // => 'hi-diddly-ho there, neig [...]' */ - function truncate(string, options) { + function trunc(string, options) { var length = 30, omission = '...'; @@ -7750,9 +7860,9 @@ /** * Creates a function bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. + * name the created callback returns the property value for a given element. + * If `func` is an object the created callback returns `true` for elements + * that contain the equivalent object properties, otherwise it returns `false`. * * @static * @memberOf _ @@ -7873,7 +7983,7 @@ /** * Adds all own enumerable function properties of a source object to the - * destination object. If `object` is a function methods will be added to + * destination object. If `object` is a function then methods are added to * its prototype as well. * * @static @@ -8063,9 +8173,9 @@ /** * Produces a random number between `min` and `max` (inclusive). If only one - * argument is provided a number between `0` and the given number will be - * returned. If `floating` is truthy or either `min` or `max` are floats a - * floating-point number will be returned instead of an integer. + * argument is provided a number between `0` and the given number is returned. + * If `floating` is truthy, or either `min` or `max` are floats, a floating-point + * number is returned instead of an integer. * * @static * @memberOf _ @@ -8177,10 +8287,10 @@ /** * Resolves the value of property `key` on `object`. If `key` is a function - * it will be invoked with the `this` binding of `object` and its result - * returned, else the property value is returned. If `object` is `null` or - * `undefined` then `undefined` is returned. If a default value is provided - * it will be returned if the property value resolves to `undefined`. + * it is invoked with the `this` binding of `object` and its result returned, + * else the property value is returned. If `object` is `null` or `undefined` + * then `undefined` is returned. If a default value is provided it is returned + * if the property value resolves to `undefined`. * * @static * @memberOf _ @@ -8253,7 +8363,7 @@ } /** - * Generates a unique ID. If `prefix` is provided the ID will be appended to it. + * Generates a unique ID. If `prefix` is provided the ID is appended to it. * * @static * @memberOf _ @@ -8439,7 +8549,7 @@ lodash.trim = trim; lodash.trimLeft = trimLeft; lodash.trimRight = trimRight; - lodash.truncate = truncate; + lodash.trunc = trunc; lodash.unescape = unescape; lodash.uniqueId = uniqueId; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index e2ba8d833f..3b44b85bbc 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -1,67 +1,68 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE + * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){for(var e=-1,r=t.length,u=Array(r);++et||typeof n=="undefined")return 1;if(nr||13r||8202e||13e||8202>>0:0,u=qe(r);++ei(t,f)&&l.push(f);return l}function wt(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number"&&-1o?0:o>>>0);return wt(n,function(n){var o=u?t:null!=n&&n[t];i[++r]=o?o.apply(n,e):m}),i}function Tt(n,t,e,r,u){return n?((zr(t)?ft:Et)(t,function(t,o,i){var a=t&&zr(t),f=t&&Br(t),l=n[o];if(a||f){for(r||(r=[]),u||(u=[]),f=r.length;f--;)if(r[f]==t)return void(n[o]=u[f]);i=e?e(l,t,o,n,i):m,l=(f=typeof i!="undefined")?i:a?zr(l)?l:[]:Br(l)?l:{},r.push(t),u.push(l),f||Tt(l,t,e,r,u)}else i=e?e(l,t,o,n,i):m,typeof i=="undefined"&&(i=t),typeof i!="undefined"&&(l=i); -n[o]=l}),n):n}function Ft(n,t){var e={};if(typeof t=="function")return Ot(n,function(n,r,u){t(n,r,u)&&(e[r]=n)}),e;for(var r=-1,u=t.length;++ra(p,h)&&((u||l)&&p.push(h),c.push(s)) -}return c}function Lt(n,t){for(var e=-1,r=t(n),u=r.length,o=qe(u);++er)return t;var u=typeof e[2];if("number"!=u&&"string"!=u||!e[3]||e[3][e[2]]!==e[1]||(r=2),3o?0:o)}function Gt(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?Cr(u+r,0):r||0;else if(r)return r=ee(n,t),u&&n[r]===t?r:-1;return e(n,t,r) -}function Ht(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=U.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else o=null==t||e?1:t;return o=r-(o||0),te(n,0,0>o?0:o)}function Qt(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=U.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||e)return n?n[r-1]:m;return o=r-(o||0),te(n,0>o?0:o)}function ne(n,t,e){if(typeof t!="number"&&null!=t){var r=-1,u=n?n.length:0,o=0;for(t=U.createCallback(t,e,3);++rt?0:t;return te(n,o)}function te(n,t,e){var r=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t?t=Cr(u+t,0):t>u&&(t=u),e=typeof e=="undefined"?u:+e||0,0>e?e=Cr(u+e,0):e>u&&(e=u),u=t>e?0:e-t,e=qe(u);++r>>1,e(n[r])e?0:e);++te?Cr(r+e,0):e||0:0,typeof n=="string"||!zr(n)&&Re(n)?eo&&(o=a)}else t=null==t&&Re(n)?u:U.createCallback(t,e,3),wt(n,function(n,e,u){e=t(n,e,u),(e>r||-1/0===e&&e===o)&&(r=e,o=n)});return o}function ve(n,t){return he(n,Ue(t))}function ye(n,t,e,r){var u=3>arguments.length;t=U.createCallback(t,r,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return t=U.createCallback(t,r,4),jt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function de(n){var t=-1,e=n&&n.length,r=qe(0>e?0:e>>>0);return wt(n,function(n){var e=Wt(0,++t);r[t]=r[e],r[e]=n}),r}function be(n,t,e){var r;(typeof t!="function"||typeof e!="undefined")&&(t=U.createCallback(t,e,3)),e=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return Zt(n,d,null,t);if(n)var e=n[C]?n[C][2]:n.length,r=te(arguments,2),e=e-r.length;return Zt(n,d|j,e,t,r)}function we(n,t,e){var r,u,o,i,a,f,l,c=0,p=false,s=true;if(!Ae(n))throw new Ge(A);if(t=0>t?0:t,true===e)var h=true,s=false;else Oe(e)&&(h=e.leading,p="maxWait"in e&&Cr(t,+e.maxWait||0),s="trailing"in e?e.trailing:s);var g=function(){var e=t-(Mr()-i);0>=e||e>t?(u&&ar(u),e=l,u=f=l=m,e&&(c=Mr(),o=n.apply(a,r),f||u||(r=a=null))):f=vr(g,e) -},v=function(){f&&ar(f),u=f=l=m,(s||p!==t)&&(c=Mr(),o=n.apply(a,r),f||u||(r=a=null))};return function(){if(r=arguments,i=Mr(),a=this,l=s&&(f||!h),false===p)var e=h&&!f;else{u||h||(c=i);var y=p-(i-c),m=0>=y||y>p;m?(u&&(u=ar(u)),c=i,o=n.apply(a,r)):u||(u=vr(v,y))}return m&&f?f=ar(f):f||t===p||(f=vr(g,t)),e&&(m=true,o=n.apply(a,r)),!m||f||u||(r=a=null),o}}function je(n){if(!Ae(n))throw new Ge(A);return function(){return!n.apply(this,arguments)}}function xe(n){return Rt(n,Ne)}function ke(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ur.call(n)==X||false -}function Ce(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,i=qe(e),a=0t||null==n||!jr(t))return e;n=Ye(n);do t%2&&(e+=n),t=fr(t/2),n+=n;while(t);return e}function We(n,t){return(n=null==n?"":Ye(n))?null==t?n.slice(h(n),g(n)+1):(t=Ye(t),n.slice(o(n,t),i(n,t)+1)):n}function $e(n,t,e){var r=typeof n,u="function"==r;return!u||typeof t!="undefined"&&"prototype"in n?u||null==n?dt(n,t,e):"object"==r?De(n):Ue(n):n -}function Le(n){return n}function De(n){var t=Ur(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||Oe(u)?function(r){var u=e;if(u&&!r)return false;for(;u--;){var o=t[u];if(!pr.call(r,o)||!Nt(r[o],n[o],null,true))return false}return true}:function(n){return n&&pr.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function ze(n,t,e){var r=true,u=t&&Rt(t,Ur);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=Rt(t,Ur)),false===e?r=false:Oe(e)&&"chain"in e&&(r=e.chain),e=-1;for(var o=Ae(n),i=u?u.length:0;++e--n?t.apply(this,arguments):void 0}},U.assign=Dr,U.at=function(t){return n(t,kt(arguments,true,false,1))},U.bind=_e,U.bindAll=function(n){for(var t=n,e=1arguments.length?Zt(t,d|b,null,n):Zt(t,d|b|j,null,n,te(arguments,2))},U.chain=function(n){return new M(n,true)},U.compact=function(n){for(var t=-1,e=n?n.length:0,r=0,u=[];++t(s?r(s,f):i(p,f))){for(t=u;--t;){var h=o[t];if(0>(h?r(h,f):i(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},U.invert=function(n,t){for(var e=-1,r=Ur(n),u=r.length,o={};++eu?0:u>>>0);for(o||(t=U.createCallback(t,e,3)),wt(n,function(n,e,u){if(o)for(e=t.length,u=qe(e);e--;)u[e]=n[t[e]];else u=t(n,e,u);i[++r]={a:u,b:r,c:n}}),u=i.length,i.sort(o?f:a);u--;)i[u]=i[u].c;return i},U.tap=function(n,t,e){return t.call(e,n),n},U.throttle=function(n,t,e){var r=true,u=true;if(!Ae(n))throw new Ge(A);return false===e?r=false:Oe(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),it.leading=r,it.maxWait=+t,it.trailing=u,we(n,t,it) -},U.times=function(n,t,e){n=0>n?0:n>>>0,t=dt(t,e,1),e=-1;for(var r=qe(n);++ee?0:+e||0,r))-t.length,0<=e&&n.indexOf(t,e)==e},U.escape=function(n){return null==n?"":Ye(n).replace(T,p)},U.escapeRegExp=Te,U.every=fe,U.find=ce,U.findIndex=Xt,U.findKey=function(n,t,e){return t=U.createCallback(t,e,3),xt(n,t,Et,true) -},U.findLast=function(n,t,e){return t=U.createCallback(t,e,3),xt(n,t,jt)},U.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=U.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},U.findLastKey=function(n,t,e){return t=U.createCallback(t,e,3),xt(n,t,It,true)},U.findWhere=function(n,t){return ce(n,De(t))},U.has=function(n,t){return n?pr.call(n,t):false},U.identity=Le,U.indexOf=Gt,U.isArguments=ke,U.isArray=zr,U.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ur.call(n)==G||false -},U.isDate=function(n){return n&&typeof n=="object"&&ur.call(n)==H||false},U.isElement=Ce,U.isEmpty=function(n){var t=true;if(!n)return t;var e=n.length;return-1e?Cr(r+e,0):Ar(e||0,r-1))+1);r--;)if(n[r]===t)return r;return-1},U.noConflict=function(){return c._=er,this},U.noop=Be,U.now=Mr,U.pad=function(n,t,e){n=null==n?"":Ye(n),t=+t; -var r=n.length;return re?0:+e||0,n.length),n.lastIndexOf(t,e)==e},U.template=function(n,t,e){var r=U.templateSettings;e=Dr({},e,r,pt),n=Ye(null==n?"":n);var u,o,i=Dr({},e.imports,r.imports,pt),r=Ur(i),i=Se(i),a=0,f=e.interpolate||q,l="__p+='",f=Xe((e.escape||q).source+"|"+f.source+"|"+(f===$?L:q).source+"|"+(e.evaluate||q).source+"|$","g"); -return n.replace(f,function(t,e,r,i,f,c){return r||(r=i),l+=n.slice(a,c).replace(K,s),e&&(u=true,l+="'+__e("+e+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t}),l+="';",(e=e.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(I,""):l).replace(R,"$1").replace(N,"$1;"),l="function("+(e||"obj")+"){"+(e?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",e=Dt(l,r,i,void 0),t?e(t):e -},U.trim=We,U.trimLeft=function(n,t){return(n=null==n?"":Ye(n))?null==t?n.slice(h(n)):(t=Ye(t),n.slice(o(n,t))):n},U.trimRight=function(n,t){return(n=null==n?"":Ye(n))?null==t?n.slice(0,g(n)+1):(t=Ye(t),n.slice(0,i(n,t)+1)):n},U.truncate=function(n,t){var e=30,r="...";if(t&&Oe(t))var u="separator"in t?t.separator:u,e="length"in t?+t.length||0:e,r="omission"in t?Ye(t.omission):r;else null!=t&&(e=+t||0);if(n=null==n?"":Ye(n),e>=n.length)return n;var o=e-r.length;if(1>o)return r;if(e=n.slice(0,o),null==u)return e+r; -if(Ie(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Xe(u.source,(D.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;e=e.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=e.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(S,v))},U.uniqueId=function(n){var t=++O;return Ye(null==n?"":n)+t},U.all=fe,U.any=be,U.detect=ce,U.foldl=ye,U.foldr=me,U.include=ae,U.inject=ye,ze(U,function(){var n={};return Et(U,function(t,e){U.prototype[e]||(n[e]=t) -}),n}(),false),U.first=Yt,U.last=Qt,U.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Se(n)),null==t||e?(t=n?n.length:0,0t?0:+t||0,n.length),n)},U.take=Yt,U.takeRight=Qt,U.takeRightWhile=Qt,U.takeWhile=Yt,U.head=Yt,Et(U,function(n,t){var e="sample"!=t;U.prototype[t]||(U.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new M(o,u):o})}),U.VERSION=k,U.prototype.chain=function(){return this.__chain__=true,this -},U.prototype.toJSON=ie,U.prototype.toString=function(){return Ye(this.__wrapped__)},U.prototype.value=ie,U.prototype.valueOf=ie,ft(["join","pop","shift"],function(n){var t=He[n];U.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new M(e,n):e}}),ft(["push","reverse","sort","unshift"],function(n){var t=He[n];U.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),ft(["concat","splice"],function(n){var t=He[n];U.prototype[n]=function(){return new M(t.apply(this.__wrapped__,arguments),this.__chain__) -}}),U}var m,d=1,b=2,_=4,w=8,j=16,x=32,k="2.4.1",C="__lodash@"+k+"__",A="Expected a function",O=0,E=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,N=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39);/g,T=/[&<>"']/g,F=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,$=/<%=([\s\S]+?)%>/g,L=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,D=/\w*$/,z=/^\s*function[ \n\r\t]+\w/,B=/^0[xX]/,U=/[\xC0-\xFF]/g,q=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,M=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,V=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",J="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),X="[object Arguments]",Y="[object Array]",G="[object Boolean]",H="[object Date]",Q="[object Error]",nt="[object Function]",tt="[object Number]",et="[object Object]",rt="[object RegExp]",ut="[object String]",ot={}; -ot[nt]=false,ot[X]=ot[Y]=ot[G]=ot[H]=ot[tt]=ot[et]=ot[rt]=ot[ut]=true;var it={leading:false,maxWait:0,trailing:false},at={configurable:false,enumerable:false,value:null,writable:false},ft={"&":"&","<":"<",">":">",'"':""","'":"'"},lt={"&":"&","<":"<",">":">",""":'"',"'":"'"},ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},pt={"function":true,object:true},st={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ht=pt[typeof window]&&window||this,gt=pt[typeof exports]&&exports&&!exports.nodeType&&exports,pt=pt[typeof module]&&module&&!module.nodeType&&module,vt=gt&&pt&&typeof global=="object"&&global; -!vt||vt.global!==vt&&vt.window!==vt&&vt.self!==vt||(ht=vt);var vt=pt&&pt.exports===gt&>,yt=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ht._=yt, define(function(){return yt})):gt&&pt?vt?(pt.exports=yt)._=yt:gt._=yt:ht._=yt}).call(this); \ No newline at end of file +;(function(){function n(n,t){for(var e=-1,r=t.length,u=Array(r);++et||typeof n=="undefined")return 1;if(nr||13r||8202e||13e||8202>>0:0,u=tr(r);++ea(t,f)&&l.push(f);return l}function Ft(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number"&&-1o?0:o>>>0);return Ft(n,function(n){var o=u?t:null!=n&&n[t];a[++r]=o?o.apply(n,e):m}),a}function Zt(n,t,e,r,u){var o=re(t);return(o?bt:Bt)(t,function(t,a,i){var f=t&&re(t),l=t&&nu(t),c=n[a]; +if(f||l){for(r||(r=[]),u||(u=[]),l=r.length;l--;)if(r[l]==t)return void(n[a]=u[l]);i=e?e(c,t,a,n,i):m,(l=typeof i!="undefined")||(i=f?Qr(c)?c:[]:nu(c)?c:{}),r.push(t),u.push(i),l||Zt(i,t,e,r,u),n[a]=i}else i=e?e(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i)}),n}function Pt(n,t){var e={};if(typeof t=="function")return Lt(n,function(n,r,u){t(n,r,u)&&(e[r]=n)}),e;for(var r=-1,u=t.length;++ri(p,h)&&((u||l)&&p.push(h),c.push(s))}return c}function Jt(n,t){for(var e=-1,r=t(n),u=r.length,o=tr(u);++er)return t;var u=typeof e[2];if("number"!=u&&"string"!=u||!e[3]||e[3][e[2]]!==e[1]||(r=2),3o?0:o)}function ce(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?Dr(u+r,0):r||0;else if(r)return r=ve(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function pe(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0; +for(t=q.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else o=null==t||e?1:t;return o=r-(o||0),ge(n,0,0>o?0:o)}function se(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=q.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||e)return n?n[r-1]:m;return o=r-(o||0),ge(n,0>o?0:o)}function he(n,t,e){if(typeof t!="number"&&null!=t){var r=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,e,3);++rt?0:t;return ge(n,o)}function ge(n,t,e){var r=-1,u=n?n.length:0; +for(t=null==t?0:+t||0,0>t?t=Dr(u+t,0):t>u&&(t=u),e=typeof e=="undefined"?u:+e||0,0>e?e=Dr(u+e,0):e>u&&(e=u),u=t>e?0:e-t,e=tr(u);++r>>1,e(n[r])e?0:e);++te?Dr(r+e,0):e||0:0,typeof n=="string"||!Qr(n)&&Me(n)?eo&&(o=i)}else t=null==t&&Me(n)?u:q.createCallback(t,e,3),Ft(n,function(n,e,u){e=t(n,e,u),(e>r||-1/0===e&&e===o)&&(r=e,o=n)});return o}function Ee(n,t){return Ce(n,nr(t))}function Ie(n,t,e,r){var u=3>arguments.length;t=q.createCallback(t,r,4);var o=-1,a=n?n.length:0;if(typeof a=="number"&&-1arguments.length;return t=q.createCallback(t,r,4),Nt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Se(n){var t=-1,e=n&&n.length,r=tr(0>e?0:e>>>0);return Ft(n,function(n){var e=Kt(0,++t);r[t]=r[e],r[e]=n}),r}function Fe(n,t,e){var r;(typeof t!="function"||typeof e!="undefined")&&(t=q.createCallback(t,e,3)),e=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return ne(n,d,null,t);if(n)var e=n[A]?n[A][2]:n.length,r=ge(arguments,2),e=e-r.length;return ne(n,d|j,e,t,r)}function Te(n,t,e){function r(){var e=t-(au()-l);0>=e||e>t?(i&&wr(i),e=s,i=p=s=m,e&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))):p=Ir(r,e)}function u(){p&&wr(p),i=p=s=m,(v||g!==t)&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))}function o(){if(a=arguments,l=au(),c=this,s=v&&(p||!y),false===g)var e=y&&!p; +else{i||y||(h=l);var o=g-(l-h),m=0>=o||o>g;m?(i&&(i=wr(i)),h=l,f=n.apply(c,a)):i||(i=Ir(u,o))}return m&&p?p=wr(p):p||t===g||(p=Ir(r,t)),e&&(m=true,f=n.apply(c,a)),!m||p||i||(a=c=null),f}var a,i,f,l,c,p,s,h=0,g=false,v=true;if(!Be(n))throw new fr(C);if(t=0>t?0:t,true===e)var y=true,v=false;else De(e)&&(y=e.leading,g="maxWait"in e&&Dr(t,+e.maxWait||0),v="trailing"in e?e.trailing:v);return o.cancel=function(){p&&wr(p),i&&wr(i),i=p=s=m},o}function We(n){if(!Be(n))throw new fr(C);return function(){return!n.apply(this,arguments) +}}function Ue(n){return zt(n,Ze)}function $e(n){return n&&typeof n=="object"&&typeof n.length=="number"&&yr.call(n)==Y||false}function Le(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,a=tr(e),i=0t||null==n||!$r(t))return e;n=ir(n);do t%2&&(e+=n),t=kr(t/2),n+=n;while(t);return e}function Je(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n),g(n)+1):(t=ir(t),n.slice(o(n,t),a(n,t)+1)):n +}function Xe(n,t,e){var r=typeof n,u="function"==r;return!u||typeof t!="undefined"&&"prototype"in n?u||null==n?It(n,t,e):"object"==r?Ge(n):nr(n):n}function Ye(n){return n}function Ge(n){var t=tu(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||De(u)?function(r){var u=e;if(u&&!r)return false;for(;u--;){var o=t[u];if(!Ar.call(r,o)||!qt(r[o],n[o],null,true))return false}return true}:function(n){return n&&Ar.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function He(n,t,e){var r=true,u=t&&zt(t,tu);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=zt(t,tu)),false===e?r=false:De(e)&&"chain"in e&&(r=e.chain),e=-1; +for(var o=Be(n),a=u?u.length:0;++e--n?t.apply(this,arguments):void 0}},q.assign=Hr,q.at=function(t){return n(t,Wt(arguments,true,false,1))},q.bind=Ne,q.bindAll=function(n){for(var t=n,e=1arguments.length?ne(t,d|b,null,n):ne(t,d|b|j,null,n,ge(arguments,2))},q.chain=function(n){return new V(n,true) +},q.compact=function(n){for(var t=-1,e=n?n.length:0,r=0,u=[];++t(s?r(s,f):a(p,f))){for(t=u;--t;){var h=o[t];if(0>(h?r(h,f):a(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},q.invert=function(n,t){for(var e=-1,r=tu(n),u=r.length,o={};++eu?0:u>>>0);for(o||(t=q.createCallback(t,e,3)),Ft(n,function(n,e,u){if(o)for(e=t.length,u=tr(e);e--;)u[e]=n[t[e]];else u=t(n,e,u);a[++r]={a:u,b:r,c:n}}),u=a.length,a.sort(o?f:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,e){return t.call(e,n),n},q.throttle=function(n,t,e){var r=true,u=true;if(!Be(n))throw new fr(C);return false===e?r=false:De(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),mt.leading=r,mt.maxWait=+t,mt.trailing=u,Te(n,t,mt) +},q.times=function(n,t,e){n=0>n?0:n>>>0,t=It(t,e,1),e=-1;for(var r=tr(n);++ee?0:+e||0,r))-t.length,0<=e&&n.indexOf(t,e)==e},q.escape=function(n){return null==n?"":ir(n).replace(N,p)},q.escapeRegExp=Ke,q.every=we,q.find=ke,q.findIndex=fe,q.findKey=function(n,t,e){return t=q.createCallback(t,e,3),Tt(n,t,Bt,true) +},q.findLast=function(n,t,e){return t=q.createCallback(t,e,3),Tt(n,t,Nt)},q.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=q.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},q.findLastKey=function(n,t,e){return t=q.createCallback(t,e,3),Tt(n,t,Dt,true)},q.findWhere=function(n,t){return ke(n,Ge(t))},q.has=function(n,t){return n?Ar.call(n,t):false},q.identity=Ye,q.indexOf=ce,q.isArguments=$e,q.isArray=Qr,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&yr.call(n)==H||false +},q.isDate=function(n){return n&&typeof n=="object"&&yr.call(n)==Q||false},q.isElement=Le,q.isEmpty=function(n){var t=true;if(!n)return t;var e=n.length;return-1e?Dr(r+e,0):zr(e||0,r-1))+1);r--;)if(n[r]===t)return r;return-1},q.noConflict=function(){return c._=vr,this},q.noop=Qe,q.now=au,q.pad=function(n,t,e){n=null==n?"":ir(n),t=+t; +var r=n.length;return re?0:+e||0,n.length),n.lastIndexOf(t,e)==e},q.template=function(n,t,e){var r=q.templateSettings;e=Hr({},e,r,jt),n=ir(null==n?"":n);var u,o,a=Hr({},e.imports,r.imports,jt),r=tu(a),a=Pe(a),i=0,f=e.interpolate||M,l="__p+='",f=ar((e.escape||M).source+"|"+f.source+"|"+(f===U?$:M).source+"|"+(e.evaluate||M).source+"|$","g"); +return n.replace(f,function(t,e,r,a,f,c){return r||(r=a),l+=n.slice(i,c).replace(K,s),e&&(u=true,l+="'+__e("+e+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t}),l+="';",(e=e.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(I,""):l).replace(R,"$1").replace(S,"$1;"),l="function("+(e||"obj")+"){"+(e?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",e=Xt(l,r,a,void 0),t?e(t):e +},q.trim=Je,q.trimLeft=function(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n)):(t=ir(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(0,g(n)+1):(t=ir(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var e=30,r="...";if(t&&De(t))var u="separator"in t?t.separator:u,e="length"in t?+t.length||0:e,r="omission"in t?ir(t.omission):r;else null!=t&&(e=+t||0);if(n=null==n?"":ir(n),e>=n.length)return n;var o=e-r.length;if(1>o)return r;if(e=n.slice(0,o),null==u)return e+r; +if(qe(u)){if(n.slice(o).search(u)){var a,i,f=n.slice(0,o);for(u.global||(u=ar(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(f);)i=a.index;e=e.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=e.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(F,v))},q.uniqueId=function(n){var t=++O;return ir(null==n?"":n)+t},q.all=we,q.any=Fe,q.detect=ke,q.foldl=Ie,q.foldr=Re,q.include=_e,q.inject=Ie,He(q,function(){var n={};return Bt(q,function(t,e){q.prototype[e]||(n[e]=t) +}),n}(),false),q.first=le,q.last=se,q.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Pe(n)),null==t||e?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=le,q.takeRight=se,q.takeRightWhile=se,q.takeWhile=le,q.head=le,Bt(q,function(n,t){var e="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new V(o,u):o})}),q.VERSION=x,q.prototype.chain=function(){return this.__chain__=true,this +},q.prototype.toJSON=be,q.prototype.toString=function(){return ir(this.__wrapped__)},q.prototype.value=be,q.prototype.valueOf=be,bt(["join","pop","shift"],function(n){var t=lr[n];q.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new V(e,n):e}}),bt(["push","reverse","sort","unshift"],function(n){var t=lr[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),bt(["concat","splice"],function(n){var t=lr[n];q.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__) +}}),q}var m,d=1,b=2,_=4,w=8,j=16,k=32,x="2.5.0-pre",A="__lodash@"+x+"__",C="Expected a function",O=0,E=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,S=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,T=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,U=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float64Array Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",et="[object Object]",rt="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; +vt[Y]=vt[G]=vt[at]=vt[it]=vt[ft]=vt[lt]=vt[ct]=vt[pt]=vt[st]=vt[ht]=vt[gt]=true,vt[ot]=vt[H]=vt[Q]=vt[nt]=vt["[object Function]"]=vt["[object Map]"]=vt[tt]=vt[et]=vt[rt]=vt["[object Set]"]=vt[ut]=vt["[object WeakMap]"]=false;var yt={};yt[Y]=yt[G]=yt[ot]=yt[H]=yt[Q]=yt[nt]=yt[at]=yt[it]=yt[ft]=yt[lt]=yt[ct]=yt[tt]=yt[et]=yt[rt]=yt[ut]=yt[pt]=yt[st]=yt[ht]=yt[gt]=true,yt["[object Function]"]=yt["[object Map]"]=yt["[object Set]"]=yt["[object WeakMap]"]=false;var mt={leading:false,maxWait:0,trailing:false},dt={configurable:false,enumerable:false,value:null,writable:false},bt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},_t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},wt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},jt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},xt=jt[typeof window]&&window||this,At=jt[typeof exports]&&exports&&!exports.nodeType&&exports,jt=jt[typeof module]&&module&&!module.nodeType&&module,Ct=At&&jt&&typeof global=="object"&&global; +!Ct||Ct.global!==Ct&&Ct.window!==Ct&&Ct.self!==Ct||(xt=Ct);var Ct=jt&&jt.exports===At&&At,Ot=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(xt._=Ot, define(function(){return Ot})):At&&jt?Ct?(jt.exports=Ot)._=Ot:At._=Ot:xt._=Ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index bdc0aa3358..b52fd841e8 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) + * Lo-Dash 2.5.0-pre (Custom Build) * Build: `lodash underscore -o ./dist/lodash.underscore.js` * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 @@ -21,7 +21,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.4.1'; + var version = '2.5.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; @@ -36,14 +36,17 @@ var idCounter = 0; /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g, - reUnescapedHtml = /[&<>"']/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27|#96);/g, + reUnescapedHtml = /[&<>"'`]/g; /** Used to match template delimiters */ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + /** Used to detect host constructors (Safari > 5) */ + var reHostCtor = /^\[object .+?Constructor\]$/; + /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; @@ -62,27 +65,63 @@ arrayClass = '[object Array]', boolClass = '[object Boolean]', dateClass = '[object Date]', + errorClass = '[object Error]', funcClass = '[object Function]', + mapClass = '[object Map]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', - stringClass = '[object String]'; + setClass = '[object Set]', + stringClass = '[object String]', + weakMapClass = '[object WeakMap]'; + + var arrayBufferClass = '[object ArrayBuffer]', + float32Class = '[object Float32Array]', + float64Class = '[object Float64Array]', + int8Class = '[object Int8Array]', + int16Class = '[object Int16Array]', + int32Class = '[object Int32Array]', + uint8Class = '[object Uint8Array]', + uint8ClampedClass = '[object Uint8ClampedArray]', + uint16Class = '[object Uint16Array]', + uint32Class = '[object Uint32Array]'; + + /** Used to identify object classifications that are treated like arrays */ + var arrayLikeClasses = {}; + arrayLikeClasses[argsClass] = + arrayLikeClasses[arrayClass] = arrayLikeClasses[float32Class] = + arrayLikeClasses[float64Class] = arrayLikeClasses[int8Class] = + arrayLikeClasses[int16Class] = arrayLikeClasses[int32Class] = + arrayLikeClasses[uint8Class] = arrayLikeClasses[uint8ClampedClass] = + arrayLikeClasses[uint16Class] = arrayLikeClasses[uint32Class] = true; + arrayLikeClasses[arrayBufferClass] = arrayLikeClasses[boolClass] = + arrayLikeClasses[dateClass] = arrayLikeClasses[errorClass] = + arrayLikeClasses[funcClass] = arrayLikeClasses[mapClass] = + arrayLikeClasses[numberClass] = arrayLikeClasses[objectClass] = + arrayLikeClasses[regexpClass] = arrayLikeClasses[setClass] = + arrayLikeClasses[stringClass] = arrayLikeClasses[weakMapClass] = false; /** * Used to convert characters to HTML entities. * * Note: Though the ">" character is escaped for symmetry, characters like - * ">", "`", and "/" don't require escaping in HTML and have no special meaning + * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. + * + * Backticks are escaped because in Internet Explorer < 9, they can be used to + * break out of attribute values or HTML comments. See [#102](http://html5sec.org/#102), + * [#108](http://html5sec.org/#108), and [#133](http://html5sec.org/#133) of + * the [HTML5 Security Cheatsheet](http://html5sec.org/) for more details. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', - "'": ''' + "'": ''', + '`': '`' }; /** Used to convert HTML entities to characters */ @@ -91,7 +130,8 @@ '<': '<', '>': '>', '"': '"', - ''': "'" + ''': "'", + '`': '`' }; /** Used to determine if values are of the language type `Object` */ @@ -225,8 +265,8 @@ var arrayProto = Array.prototype, objectProto = Object.prototype; - /** Used to restore the original `_` reference in `_.noConflict` */ - var oldDash = root._; + /** Used to resolve the decompiled source of functions */ + var fnToString = Function.prototype.toString; /** * Used as the maximum length of an array-like object. @@ -235,6 +275,9 @@ */ var maxSafeInteger = Math.pow(2, 53) - 1; + /** Used to restore the original `_` reference in `_.noConflict` */ + var oldDash = root._; + /** Used to resolve the internal `[[Class]]` of values */ var toString = objectProto.toString; @@ -247,7 +290,6 @@ /** Native method shortcuts */ var ceil = Math.ceil, floor = Math.floor, - fnToString = Function.prototype.toString, hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, @@ -317,15 +359,11 @@ * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value - * wrapped.reduce(function(sum, num) { - * return sum + num; - * }); + * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value - * var squares = wrapped.map(function(num) { - * return num * num; - * }); + * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false @@ -481,9 +519,6 @@ * @returns {Object} Returns the destination object. */ function baseAssign(object, source, callback) { - if (!object) { - return object; - } var index = -1, props = keys(source), length = props.length; @@ -543,15 +578,15 @@ case 1: return function(value) { return func.call(thisArg, value); }; - case 2: return function(value, other) { - return func.call(thisArg, value, other); - }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); }; case 4: return function(accumulator, value, index, collection) { return func.call(thisArg, accumulator, value, index, collection); }; + case 5: return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; } return bind(func, thisArg); } @@ -864,7 +899,7 @@ * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. + * @param {boolean} [isWhere=false] A flag to indicate performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. @@ -900,7 +935,7 @@ case stringClass: return value == String(other); } - var isArr = valClass == arrayClass; + var isArr = arrayLikeClasses[valClass]; if (!isArr) { if (valClass != objectClass) { return false; @@ -1116,7 +1151,7 @@ /** * Compiles a function from `source` using the `varNames` and `varValues` * pairs to import free variables into the compiled function. If `sourceURL` - * is provided it will be used as the sourceURL for the compiled function. + * is provided it is used as the sourceURL for the compiled function. * * @private * @param {string} source The source to compile. @@ -1173,7 +1208,7 @@ * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection * through a callback. The given setter function sets the keys and values of - * the accumulator object. If `initializer` is provided it will be used to + * the accumulator object. If `initializer` is provided it is used to * initialize the accumulator object. * * @private @@ -1292,7 +1327,10 @@ * @returns {boolean} Returns `true` if `value` is a native function, else `false`. */ function isNative(value) { - return typeof value == 'function' && reNative.test(fnToString.call(value)); + var type = typeof value; + return type == 'function' + ? reNative.test(fnToString.call(value)) + : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; } /** @@ -1408,10 +1446,10 @@ * element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -1419,8 +1457,8 @@ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example @@ -1486,16 +1524,16 @@ /** * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truthy, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before + * is truthy, the array is only flattened a single level. If a callback is + * provided each element of the array is passed through the callback before * flattening. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -1504,7 +1542,7 @@ * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new flattened array. @@ -1541,7 +1579,7 @@ /** * Gets the index at which the first occurrence of `value` is found using * strict equality for comparisons, i.e. `===`. If the array is already sorted - * providing `true` for `fromIndex` will run a faster binary search. + * providing `true` for `fromIndex` performs a faster binary search. * * @static * @memberOf _ @@ -1775,15 +1813,15 @@ /** * Uses a binary search to determine the smallest index at which a value * should be inserted into a given sorted array in order to maintain the sort - * order of the array. If a callback is provided it will be executed for - * `value` and each element of `array` to compute their sort ranking. The - * callback is bound to `thisArg` and invoked with one argument; (value). + * order of the array. If a callback is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The callback + * is bound to `thisArg` and invoked with one argument; (value). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -1792,8 +1830,8 @@ * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. @@ -1885,17 +1923,17 @@ /** * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing `true` for - * `isSorted` will use a faster algorithm. If a callback is provided it will - * be executed for each value in the array to generate the criterion by which - * uniqueness is computed. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index, array). + * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a + * faster search algorithm for sorted arrays. If a callback is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The callback is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -1905,26 +1943,26 @@ * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new duplicate-value-free array. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] + * _.uniq([1, 2, 1]); + * // => [1, 2] * * // using `isSorted` - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] + * _.uniq([1, 1, 2], true); + * // => [1, 2] * * // using `callback` - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] + * _.uniq(['A', 'b', 'a', 'B'], function(chr) { return chr.toLowerCase(); }); + * // => ['A', 'b'] * * // using `callback` with `thisArg` - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] + * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); + * // => [1, 2.5] * * // using "_.pluck" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); @@ -1976,7 +2014,7 @@ * Creates an array of grouped elements, the first of which contains the first * elements of the given arrays, the second of which contains the second elements * of the given arrays, and so on. If a zipped value is provided its corresponding - * unzipped value will be returned. + * unzipped value is returned. * * @static * @memberOf _ @@ -2189,10 +2227,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2200,16 +2238,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * - * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); @@ -2225,10 +2263,10 @@ * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2237,8 +2275,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements passed the predicate check, * else `false`. @@ -2290,10 +2328,10 @@ * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2302,13 +2340,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * - * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [2, 4] * * var characters = [ @@ -2354,10 +2392,10 @@ * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2366,8 +2404,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example @@ -2450,10 +2488,10 @@ * @returns {Array|Object|string} Returns `collection`. * @example * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); + * _([1, 2, 3]).forEach(function(n) { console.log(n); }).join(','); * // => logs each number and returns '1,2,3' * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { console.log(n); }); * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { @@ -2475,10 +2513,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2486,16 +2524,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using "_.pluck" callback shorthand @@ -2518,10 +2556,10 @@ * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2529,8 +2567,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example @@ -2556,8 +2594,8 @@ /** * Invokes the method named by `methodName` on each element in the collection * returning an array of the results of each invoked method. Additional arguments - * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the collection. + * is provided to each invoked method. If `methodName` is a function it is + * invoked for, and `this` bound to, each element in the collection. * * @static * @memberOf _ @@ -2585,10 +2623,10 @@ * three arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2597,16 +2635,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new mapped array. * @example * - * _.map([1, 2, 3], function(num) { return num * 3; }); + * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); * // => [3, 6, 9] (property order is not guaranteed across environments) * * var characters = [ @@ -2635,17 +2673,17 @@ } /** - * Retrieves the maximum value of a collection. If the collection is empty or - * falsey `-Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Retrieves the maximum value of a collection. If the collection is empty + * or falsey `-Infinity` is returned. If a callback is provided it is executed + * for each value in the collection to generate the criterion by which the + * value is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2653,7 +2691,7 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the maximum value. @@ -2711,17 +2749,17 @@ } /** - * Retrieves the minimum value of a collection. If the collection is empty or - * falsey `Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three + * Retrieves the minimum value of a collection. If the collection is empty + * or falsey `Infinity` is returned. If a callback is provided it is executed + * for each value in the collection to generate the criterion by which the + * value is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2729,7 +2767,7 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it will be used to create a "_.pluck" + * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the minimum value. @@ -2793,10 +2831,10 @@ * to `thisArg` and invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2804,16 +2842,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the array of grouped elements. * @example * - * _.partition([1, 2, 3], function(num) { return num % 2; }); + * _.partition([1, 2, 3], function(n) { return n % 2; }); * // => [[1, 3], [2]] * - * _.partition([1.2, 2.3, 3.4], function(num) { return this.floor(num) % 2; }, Math); + * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); * // => [[1, 3], [2]] * * var characters = [ @@ -2861,9 +2899,9 @@ * Reduces a collection to a value which is the accumulated result of running * each element in the collection through the callback, where each successive * callback execution consumes the return value of the previous execution. If - * `accumulator` is not provided the first element of the collection will be - * used as the initial `accumulator` value. The callback is bound to `thisArg` - * and invoked with four arguments; (accumulator, value, index|key, collection). + * `accumulator` is not provided the first element of the collection is used + * as the initial `accumulator` value. The callback is bound to `thisArg` and + * invoked with four arguments; (accumulator, value, index|key, collection). * * @static * @memberOf _ @@ -2876,13 +2914,11 @@ * @returns {*} Returns the accumulated value. * @example * - * var sum = _.reduce([1, 2, 3], function(sum, num) { - * return sum + num; - * }); + * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * - * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { + * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } @@ -2947,10 +2983,10 @@ * the predicate does **not** return truthy for. * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -2958,13 +2994,13 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * - * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); + * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [1, 3] * * var characters = [ @@ -3078,10 +3114,10 @@ * with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3090,8 +3126,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback respectively. + * per iteration. If a property name or object is provided it is used to + * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. @@ -3140,18 +3176,18 @@ /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through the callback. This method - * performs a stable sort, that is, it will preserve the original sort order - * of equal elements. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The callback is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * callback returns the property value of the given element. * * If an array of property names is provided for `callback` the collection - * will be sorted by each property value. + * is sorted by each property value. * * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, + * returns `true` for elements that have the properties of the given object, * else `false`. * * @static @@ -3159,16 +3195,16 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it will - * be used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If a property name or object is provided it is + * used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example * - * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * - * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * * var characters = [ @@ -3335,7 +3371,7 @@ * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays * of method names. If no method names are provided all enumerable function - * properties, own and inherited, of `object` will be bound. + * properties, own and inherited, of `object` are bound. * * Note: This method does not set the `length` property of bound functions. * @@ -3435,14 +3471,15 @@ } /** - * Creates a function that will delay the execution of `func` until after - * `wait` milliseconds have elapsed since the last time it was invoked. - * 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 will return the result of the last `func` call. + * Creates a function that delays the execution of `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 calls. 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` call. * - * Note: If `leading` and `trailing` options are `true`, `func` will be called - * on the trailing edge of the timeout only if the the debounced function is + * Note: If `leading` and `trailing` options are `true`, `func` is called on + * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * * @static @@ -3458,8 +3495,7 @@ * @example * * // avoid costly calculations while the window size is in flux - * var lazyLayout = _.debounce(calculateLayout, 150); - * jQuery(window).on('resize', lazyLayout); + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // execute `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { @@ -3469,9 +3505,26 @@ * * // ensure `batchLog` is executed once after 1 second of debounced calls * var source = new EventSource('/stream'); - * source.addEventListener('message', _.debounce(batchLog, 250, { + * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * }, false); + * + * // cancel a debounced call + * var todoChanges = _.debounce(batchLog, 1000); + * Object.observe(models.todo, todoChanges); + * + * Object.observe(models, function(changes) { + * if (_.find(changes, { 'name': 'todo', 'type': 'delete'})) { + * todoChanges.cancel(); + * } + * }, ['delete']); + * + * // ...at some point `models.todo` is changed + * models.todo.completed = true; + * + * // ...before 1 second has passed `models.todo` is deleted + * // which cancels the debounced `todoChanges` call + * delete models.todo; */ function debounce(func, wait, options) { var args, @@ -3497,7 +3550,18 @@ maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); trailing = 'trailing' in options ? options.trailing : trailing; } - var delayed = function() { + + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + } + + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { if (maxTimeoutId) { @@ -3515,9 +3579,9 @@ } else { timeoutId = setTimeout(delayed, remaining); } - }; + } - var maxDelayed = function() { + function maxDelayed() { if (timeoutId) { clearTimeout(timeoutId); } @@ -3529,9 +3593,9 @@ args = thisArg = null; } } - }; + } - return function() { + function debounced() { args = arguments; stamp = now(); thisArg = this; @@ -3571,12 +3635,14 @@ args = thisArg = null; } return result; - }; + } + debounced.cancel = cancel; + return debounced; } /** - * Defers executing the `func` function until the current call stack has cleared. - * Additional arguments will be provided to `func` when it is invoked. + * Defers executing the `func` function until the current call stack has + * cleared. Additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -3599,7 +3665,7 @@ /** * Executes the `func` function after `wait` milliseconds. Additional arguments - * will be provided to `func` when it is invoked. + * are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -3623,11 +3689,11 @@ /** * Creates a function that memoizes the result of `func`. If `resolver` is - * provided it will be used to determine the cache key for storing the result - * based on the arguments provided to the memoized function. By default, the - * first argument provided to the memoized function is used as the cache key. - * The `func` is executed with the `this` binding of the memoized function. - * The result cache is exposed as the `cache` property on the memoized function. + * provided it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the cache key. The `func` is + * executed with the `this` binding of the memoized function. The result cache + * is exposed as the `cache` property on the memoized function. * * @static * @memberOf _ @@ -3684,8 +3750,8 @@ * @returns {Function} Returns the new function. * @example * - * function isEven(num) { - * return num % 2 == 0; + * function isEven(n) { + * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); @@ -3701,8 +3767,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls to - * the function will return the value of the first call. The `func` is executed + * Creates a function that is restricted to execute `func` once. Repeat calls + * to the function return the value of the first call. The `func` is executed * with the `this` binding of the created function. * * @static @@ -3763,14 +3829,15 @@ } /** - * Creates a function that, when executed, will only call the `func` function - * at most once per every `wait` milliseconds. 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 will - * return the result of the last `func` call. + * Creates a function that only calls the `func` function at most once per + * every `wait` milliseconds. The created function comes with a `cancel` method + * to cancel delayed calls. 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` will be called - * on the trailing edge of the timeout only if the the throttled function is + * Note: If `leading` and `trailing` options are `true`, `func` is called on + * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * * @static @@ -3785,13 +3852,14 @@ * @example * * // avoid excessively updating the position while scrolling - * var throttled = _.throttle(updatePosition, 100); - * jQuery(window).on('scroll', throttled); + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes - * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { - * 'trailing': false - * })); + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) + * jQuery('.interactive').on('click', throttled); + * + * // cancel a trailing throttled call + * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { var leading = true, @@ -3842,10 +3910,10 @@ /** * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with - * five arguments; (objectValue, sourceValue, key, object, source). + * object. Subsequent sources overwrite property assignments of previous + * sources. If a callback is provided it is executed to produce the assigned + * values. The callback is bound to `thisArg` and invoked with five arguments; + * (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -3858,15 +3926,15 @@ * @returns {Object} Returns the destination object. * @example * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } + * _.assign({ 'name': 'fred' }, { 'age': 40 }, { 'employer': 'slate' }); + * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' } * * var defaults = _.partialRight(_.assign, function(value, other) { * return typeof value == 'undefined' ? other : value; * }); * - * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function assign(object) { if (!object) { @@ -3890,11 +3958,11 @@ } /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects will also - * be cloned, otherwise they will be assigned by reference. If a callback - * is provided it will be executed to produce the cloned values. If the - * callback returns `undefined` cloning will be handled by the method instead. - * The callback is bound to `thisArg` and invoked with two argument; (value, index|key). + * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, + * otherwise they are assigned by reference. If a callback is provided it is + * executed to produce the cloned values. If the callback returns `undefined` + * cloning is handled by the method instead. The callback is bound to `thisArg` + * and invoked with two argument; (value, index|key). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and @@ -3944,7 +4012,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. + * property is set, additional defaults of the same property are ignored. * * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. @@ -3958,8 +4026,8 @@ * @returns {Object} Returns the destination object. * @example * - * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.defaults({ 'name': 'barney' }, { 'age': 36 }, { 'name': 'fred', 'employer': 'slate' }); + * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { if (!object) { @@ -4025,7 +4093,7 @@ /** * Creates an object composed of the inverted keys and values of the given * object. If the given object contains duplicate values, subsequent values - * will overwrite property assignments of previous values unless `multiValue` + * overwrite property assignments of previous values unless `multiValue` * is `true`. * * @static @@ -4216,10 +4284,10 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If a callback is provided it will be executed to compare - * values. If the callback returns `undefined` comparisons will be handled - * by the method instead. The callback is bound to `thisArg` and invoked - * with three arguments; (value, other, key). + * equivalent. If a callback is provided it is executed to compare values. + * If the callback returns `undefined` comparisons are handled by the method + * instead. The callback is bound to `thisArg` and invoked with three arguments; + * (value, other, key). * * Note: This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes @@ -4260,7 +4328,7 @@ /** * Checks if `value` is, or can be coerced to, a finite number. * - * Note: This method is not the same as native `isFinite` which will return + * Note: This method is not the same as native `isFinite` which returns * `true` for booleans and empty strings. See the [ES5 spec](http://es5.github.io/#x15.1.2.5) * for more details. * @@ -4350,7 +4418,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which will return `true` + * Note: This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -4546,9 +4614,9 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` omitting the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it is executed for each property + * of `object` omitting the properties the predicate returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static @@ -4613,9 +4681,9 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it will be executed for each - * property of `object` picking the properties the predicate returns truthy - * for. The predicate is bound to `thisArg` and invoked with three arguments; + * property names. If a predicate is provided it is executed for each property + * of `object` picking the properties the predicate returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static @@ -4716,9 +4784,9 @@ * Creates a compiled template function that can interpolate data properties * in "interpolate" delimiters, HTML-escaped interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. If - * a data object is provided the interpolated template string will be returned. + * a data object is provided the interpolated template string is returned. * Data properties may be accessed as free variables in the template. If a - * settings object is provided it will override `_.templateSettings` for the + * settings object is provided it overrides `_.templateSettings` for the * template. * * Note: In the development build, `_.template` utilizes sourceURLs for easier debugging. @@ -4898,9 +4966,9 @@ /** * Creates a function bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. + * name the created callback returns the property value for a given element. + * If `func` is an object the created callback returns `true` for elements + * that contain the equivalent object properties, otherwise it returns `false`. * * @static * @memberOf _ @@ -5006,7 +5074,7 @@ /** * Adds all own enumerable function properties of a source object to the - * destination object. If `object` is a function methods will be added to + * destination object. If `object` is a function then methods are added to * its prototype as well. * * @static @@ -5125,9 +5193,9 @@ /** * Produces a random number between `min` and `max` (inclusive). If only one - * argument is provided a number between `0` and the given number will be - * returned. If `floating` is truthy or either `min` or `max` are floats a - * floating-point number will be returned instead of an integer. + * argument is provided a number between `0` and the given number is returned. + * If `floating` is truthy, or either `min` or `max` are floats, a floating-point + * number is returned instead of an integer. * * @static * @memberOf _ @@ -5221,10 +5289,10 @@ /** * Resolves the value of property `key` on `object`. If `key` is a function - * it will be invoked with the `this` binding of `object` and its result - * returned, else the property value is returned. If `object` is `null` or - * `undefined` then `undefined` is returned. If a default value is provided - * it will be returned if the property value resolves to `undefined`. + * it is invoked with the `this` binding of `object` and its result returned, + * else the property value is returned. If `object` is `null` or `undefined` + * then `undefined` is returned. If a default value is provided it is returned + * if the property value resolves to `undefined`. * * @static * @memberOf _ @@ -5296,7 +5364,7 @@ } /** - * Generates a unique ID. If `prefix` is provided the ID will be appended to it. + * Generates a unique ID. If `prefix` is provided the ID is appended to it. * * @static * @memberOf _ diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index a94de725e0..a1d307caef 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -1,41 +1,43 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE + * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash underscore -o ./dist/lodash.underscore.js` */ -;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(t>>0:0,u=Array(e);++tu(r,i)&&o.push(i)}return o}function g(n,r){var t=-1,e=n?n.length:0;if(typeof e=="number"&&-1o?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):sr}),i}function w(n,r){var t={};if(typeof r=="function")return d(n,function(n,e,u){r(n,e,u)&&(t[e]=n)}),t;for(var e=-1,u=r.length;++eo(f,c)&&(t&&f.push(c),i.push(a))}return i}function T(n,r,t,e){try{var u=Function(r,"return "+n+(e?"\n/*\n//# sourceURL="+e+"\n*/":"")).apply(sr,t);u.source=n}catch(o){throw o.source=n,o}return u}function A(n,r){return function(t,e,u){var o=r?r():{};e=fr(e,u,3),u=-1;var i=t?t.length:0;if(typeof i=="number"&&-1r?0:r) -}function q(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?ot(u+e,0):e||0;else if(e)return e=B(r,t),u&&r[e]===t?e:-1;return n(r,t,e)}function F(n,r,t){return R(n,null==r||t?1:0>r?0:r)}function R(n,r,t){var e=-1,u=n?n.length:0;for(r=null==r?0:+r||0,0>r?r=ot(u+r,0):r>u&&(r=u),t=typeof t=="undefined"?u:+t||0,0>t?t=ot(u+t,0):t>u&&(t=u),u=r>t?0:t-r,t=Array(u);++e>>1,t(n[e])u&&(u=t);else r=fr(r,t,3),g(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function L(n,r){return U(n,pr(r))}function P(n,r,t,e){var u=3>arguments.length; -r=fr(r,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return r=fr(r,e,4),h(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function G(n){var r=-1,t=n&&n.length,e=Array(0>t?0:t>>>0);return g(n,function(n){var t=j(0,++r);e[r]=e[t],e[t]=n}),e}function H(n,r,t){var e;(typeof r!="function"||typeof t!="undefined")&&(r=fr(r,t,3)),t=-1;var u=n?n.length:0; -if(typeof u=="number"&&-1arguments.length?E(n,gr,null,r):E(n,gr|vr,null,r,R(arguments,2))}function K(n,r,t){var e,u,o,i,f,a,c,l=0,p=false,s=true;if(!rr(n))throw new TypeError(mr);if(r=0>r?0:r,true===t)var g=true,s=false;else tr(t)&&(g=t.leading,p="maxWait"in t&&ot(r,+t.maxWait||0),s="trailing"in t?t.trailing:s);var h=function(){var t=r-(dt()-i);0>=t||t>r?(u&&clearTimeout(u),t=c,u=a=c=sr,t&&(l=dt(),o=n.apply(f,e),a||u||(e=f=null))):a=setTimeout(h,t) -},v=function(){a&&clearTimeout(a),u=a=c=sr,(s||p!==r)&&(l=dt(),o=n.apply(f,e),a||u||(e=f=null))};return function(){if(e=arguments,i=dt(),f=this,c=s&&(a||!g),false===p)var t=g&&!a;else{u||g||(l=i);var y=p-(i-l),m=0>=y||y>p;m?(u&&(u=clearTimeout(u)),l=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function Q(n){if(!rr(n))throw new TypeError(mr);return function(){return!n.apply(this,arguments)}}function X(n){if(!n)return n; -var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++t"']/g,wr=/($^)/,jr=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Ar="[object Array]",Er="[object Boolean]",Or="[object Date]",kr="[object Number]",Sr="[object Object]",Nr="[object RegExp]",qr="[object String]",Fr={"&":"&","<":"<",">":">",'"':""","'":"'"},Rr={"&":"&","<":"<",">":">",""":'"',"'":"'"},Br={"function":true,object:true},Mr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$r=Br[typeof window]&&window||this,Ir=Br[typeof exports]&&exports&&!exports.nodeType&&exports,Dr=Br[typeof module]&&module&&!module.nodeType&&module,Wr=Ir&&Dr&&typeof global=="object"&&global; -!Wr||Wr.global!==Wr&&Wr.window!==Wr&&Wr.self!==Wr||($r=Wr);var zr=Dr&&Dr.exports===Ir&&Ir,Ur=Array.prototype,Cr=Object.prototype,Lr=$r._,Pr=Math.pow(2,53)-1,Vr=Cr.toString,Gr=RegExp("^"+(null==Vr?"":(Vr+"").replace(jr,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Hr=Math.ceil,Jr=Math.floor,Kr=Function.prototype.toString,Qr=Cr.hasOwnProperty,Xr=Ur.push,Yr=Cr.propertyIsEnumerable,Zr=Ur.splice,nt=k(nt=Object.create)&&nt,rt=k(rt=Array.isArray)&&rt,tt=$r.isFinite,et=$r.isNaN,ut=k(ut=Object.keys)&&ut,ot=Math.max,it=Math.min,ft=k(ft=Date.now)&&ft,at=Math.random; -i.prototype=o.prototype;var ct={};!function(n){n={0:1,length:1},ct.spliceObjects=(Zr.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},nt||(c=function(){function n(){}return function(r){if(tr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||$r.Object()}}());var lt=F,pt=N,st=A(function(n,r,t){Qr.call(n,t)?n[t]++:n[t]=1}),gt=A(function(n,r,t){Qr.call(n,t)?n[t].push(r):n[t]=[r]}),ht=A(function(n,r,t){n[t]=r -}),vt=A(function(n,r,t){n[t?0:1].push(r)},function(){return[[],[]]});nr(arguments)||(nr=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Qr.call(n,"callee")&&!Yr.call(n,"callee")||false});var yt=rt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Vr.call(n)==Ar||false};rr(/x/)&&(rr=function(n){return typeof n=="function"&&"[object Function]"==Vr.call(n)});var mt=ut?function(n){return tr(n)?ut(n):[]}:S,dt=ft||function(){return(new Date).getTime()};o.after=function(n,r){if(!rr(r))throw new TypeError(mr); -return n=tt(n=+n)?n:0,function(){return 1>--n?r.apply(this,arguments):void 0}},o.bind=J,o.bindAll=function(n){for(var r=n,t=1r?0:r)},o.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},o.invert=function(n){for(var r=-1,t=mt(n),e=t.length,u={};++ro?0:o>>>0);for(t=fr(t,e,3),g(n,function(n,r,e){i[++u]={a:t(n,r,e),b:u,c:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].c;return i -},o.tap=function(n,r){return r(n),n},o.throttle=function(n,r,t){var e=true,u=true;if(!rr(n))throw new TypeError(mr);return false===t?e=false:tr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),K(n,r,{leading:e,maxWait:r,trailing:u})},o.times=function(n,r,t){n=0>n?0:n>>>0,r=l(r,t,1),t=-1;for(var e=Array(n);++tr?0:r);++nt?ot(e+t,0):it(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},o.noConflict=function(){return $r._=Lr,this -},o.now=dt,o.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Jr(at()*(r-n+1))},o.reduce=P,o.reduceRight=V,o.result=function(n,r){if(null!=n){var t=n[r];return rr(t)?n[r]():t}},o.size=function(n){var r=n?n.length:0;return typeof r=="number"&&-1n.indexOf(";")?n:n.replace(br,u))},o.uniqueId=function(n){var r=++dr+"";return n?n+r:r},o.all=I,o.any=H,o.detect=W,o.foldl=P,o.foldr=V,o.include=$,o.inject=P,o.first=N,o.last=function(n,r,t){var e=n?n.length:0;return null==r||t?n?n[e-1]:sr:(r=e-(r||0),R(n,0>r?0:r)) -},o.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=ir(n)),null==r||t?(r=n?n.length:0,0r?0:+r||0,n.length),n)},o.take=pt,o.head=N,lr(function(n,r,t){if(!n)return n;for(var e=-1,u=mt(r),o=u.length;++ee||typeof t=="undefined"){t=1;break n}if(t>>0:0,u=Array(e);++tu(r,i)&&o.push(i)}return o}function g(n,r){var t=-1,e=n?n.length:0;if(typeof e=="number"&&-1o?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):sr}),i}function j(n,r){var t={};if(typeof r=="function")return b(n,function(n,e,u){r(n,e,u)&&(t[e]=n)}),t;for(var e=-1,u=r.length;++eo(f,c)&&(t&&f.push(c),i.push(a))}return i}function x(n,r){var t,e=["_"];try{var u=Function(e,"return "+n+(t?"\n/*\n//# sourceURL="+t+"\n*/":"")).apply(sr,r);u.source=n}catch(o){throw o.source=n,o}return u}function T(n,r){return function(t,e,u){var o=r?r():{};e=fr(e,u,3),u=-1;var i=t?t.length:0;if(typeof i=="number"&&-1r?0:r)}function I(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?it(u+e,0):e||0;else if(e)return e=q(r,t),u&&r[e]===t?e:-1;return n(r,t,e)}function M(n,r,t){return N(n,null==r||t?1:0>r?0:r)}function N(n,r,t){var e=-1,u=n?n.length:0;for(r=null==r?0:+r||0,0>r?r=it(u+r,0):r>u&&(r=u),t=typeof t=="undefined"?u:+t||0,0>t?t=it(u+t,0):t>u&&(t=u),u=r>t?0:t-r,t=Array(u);++e>>1,t(n[e])u&&(u=t);else r=fr(r,t,3),g(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function L(n,r){return z(n,pr(r))}function P(n,r,t,e){var u=3>arguments.length; +r=fr(r,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return r=fr(r,e,4),h(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function G(n){var r=-1,t=n&&n.length,e=Array(0>t?0:t>>>0);return g(n,function(n){var t=w(++r);e[r]=e[t],e[t]=n}),e}function H(n,r,t){var e;(typeof r!="function"||typeof t!="undefined")&&(r=fr(r,t,3)),t=-1;var u=n?n.length:0; +if(typeof u=="number"&&-1arguments.length?E(n,gr,r):E(n,gr|vr,r,N(arguments,2))}function K(n,r,t){function e(){var t=r-(dt()-c);0>=t||t>r?(f&&clearTimeout(f),t=s,f=p=s=sr,t&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),f=p=s=sr,(v||h!==r)&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=dt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p; +else{f||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(f&&(f=clearTimeout(f)),g=c,a=n.apply(l,i)):f||(f=setTimeout(u,o))}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,a=n.apply(l,i)),!m||p||f||(i=l=null),a}var i,f,a,c,l,p,s,g=0,h=false,v=true;if(!rr(n))throw new TypeError(mr);if(r=0>r?0:r,true===t)var y=true,v=false;else tr(t)&&(y=t.leading,h="maxWait"in t&&it(r,+t.maxWait||0),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=sr},o}function Q(n){if(!rr(n))throw new TypeError(mr); +return function(){return!n.apply(this,arguments)}}function X(n){if(!n)return n;var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++t"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={};Mr[Tr]=Mr["[object Array]"]=Mr["[object Float32Array]"]=Mr["[object Float64Array]"]=Mr["[object Int8Array]"]=Mr["[object Int16Array]"]=Mr["[object Int32Array]"]=Mr["[object Uint8Array]"]=Mr["[object Uint8ClampedArray]"]=Mr["[object Uint16Array]"]=Mr["[object Uint32Array]"]=true,Mr["[object ArrayBuffer]"]=Mr[Er]=Mr[kr]=Mr["[object Error]"]=Mr["[object Function]"]=Mr["[object Map]"]=Mr[Or]=Mr[Sr]=Mr[Fr]=Mr["[object Set]"]=Mr[Ir]=Mr["[object WeakMap]"]=false; +var Nr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Br={"function":true,object:true},Rr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$r=Br[typeof window]&&window||this,Ur=Br[typeof exports]&&exports&&!exports.nodeType&&exports,Wr=Br[typeof module]&&module&&!module.nodeType&&module,Dr=Ur&&Wr&&typeof global=="object"&&global;!Dr||Dr.global!==Dr&&Dr.window!==Dr&&Dr.self!==Dr||($r=Dr); +var zr=Wr&&Wr.exports===Ur&&Ur,Cr=Array.prototype,Lr=Object.prototype,Pr=Function.prototype.toString,Vr=Math.pow(2,53)-1,Gr=$r._,Hr=Lr.toString,Jr=RegExp("^"+(null==Hr?"":(Hr+"").replace(Ar,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Kr=Math.ceil,Qr=Math.floor,Xr=Lr.hasOwnProperty,Yr=Cr.push,Zr=Lr.propertyIsEnumerable,nt=Cr.splice,rt=O(rt=Object.create)&&rt,tt=O(tt=Array.isArray)&&tt,et=$r.isFinite,ut=$r.isNaN,ot=O(ot=Object.keys)&&ot,it=Math.max,ft=Math.min,at=O(at=Date.now)&&at,ct=Math.random; +i.prototype=o.prototype;var lt={};!function(){var n={0:1,length:1};lt.spliceObjects=(nt.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},rt||(c=function(){function n(){}return function(r){if(tr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||$r.Object()}}());var pt=M,st=F,gt=T(function(n,r,t){Xr.call(n,t)?n[t]++:n[t]=1}),ht=T(function(n,r,t){Xr.call(n,t)?n[t].push(r):n[t]=[r]}),vt=T(function(n,r,t){n[t]=r +}),yt=T(function(n,r,t){n[t?0:1].push(r)},function(){return[[],[]]});nr(arguments)||(nr=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Xr.call(n,"callee")&&!Zr.call(n,"callee")||false});var mt=tt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&"[object Array]"==Hr.call(n)||false};rr(/x/)&&(rr=function(n){return typeof n=="function"&&"[object Function]"==Hr.call(n)});var bt=ot?function(n){return tr(n)?ot(n):[]}:S,dt=at||function(){return(new Date).getTime()};o.after=function(n,r){if(!rr(r))throw new TypeError(mr); +return n=et(n=+n)?n:0,function(){return 1>--n?r.apply(this,arguments):void 0}},o.bind=J,o.bindAll=function(n){for(var r=n,t=1r?0:r)},o.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},o.invert=function(n){for(var r=-1,t=bt(n),e=t.length,u={};++ro?0:o>>>0);for(t=fr(t,e,3),g(n,function(n,r,e){i[++u]={a:t(n,r,e),b:u,c:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].c;return i +},o.tap=function(n,r){return r(n),n},o.throttle=function(n,r,t){var e=true,u=true;if(!rr(n))throw new TypeError(mr);return false===t?e=false:tr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),K(n,r,{leading:e,maxWait:r,trailing:u})},o.times=function(n,r,t){n=0>n?0:n>>>0,r=l(r,t,1),t=-1;for(var e=Array(n);++tr?0:r);++nt?it(e+t,0):ft(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},o.noConflict=function(){return $r._=Gr,this +},o.now=dt,o.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Qr(ct()*(r-n+1))},o.reduce=P,o.reduceRight=V,o.result=function(n,r){if(null!=n){var t=n[r];return rr(t)?n[r]():t}},o.size=function(n){var r=n?n.length:0;return typeof r=="number"&&-1n.indexOf(";")?n:n.replace(dr,u))},o.uniqueId=function(n){var r=++br+"";return n?n+r:r},o.all=$,o.any=H,o.detect=W,o.foldl=P,o.foldr=V,o.include=R,o.inject=P,o.first=F,o.last=function(n,r,t){var e=n?n.length:0;return null==r||t?n?n[e-1]:sr:(r=e-(r||0),N(n,0>r?0:r)) +},o.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=ir(n)),null==r||t?(r=n?n.length:0,0r?0:+r||0,n.length),n)},o.take=st,o.head=F,lr(function(n,r,t){for(var e=-1,u=bt(r),o=u.length;++e Date: Wed, 4 Jun 2014 22:20:49 -0700 Subject: [PATCH 0741/1608] Add Safari 4 to saucelabs.js. --- test/saucelabs.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/saucelabs.js b/test/saucelabs.js index 85d3fa634c..ee5b4cde0b 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -113,6 +113,7 @@ var platforms = [ ['Windows 7', 'opera', '12'], ['Windows 7', 'opera', '11'], ['OS X 10.9', 'ipad', '7.1'], + ['OS X 10.6', 'ipad', '4'], ['OS X 10.9', 'safari', '7'], ['OS X 10.8', 'safari', '6'], ['OS X 10.6', 'safari', '5'] @@ -153,6 +154,7 @@ if (isBackbone) { switch (browser) { case 'Firefox': return version >= 4; + case 'iPad': return version >= 5; case 'Opera': return version >= 12; } return true; @@ -168,6 +170,7 @@ if (isModern) { case 'Android': return version >= 4.1; case 'Firefox': return version >= 10; case 'Internet Explorer': return version >= 9; + case 'iPad': return version >= 6; case 'Opera': return version >= 12; case 'Safari': return version >= 6; } From 410969743f779c07a5b1992610526d0afe877fae Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 5 Jun 2014 00:42:09 -0700 Subject: [PATCH 0742/1608] Avoid `subarray` for mobile Safari. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 9cbd9f95ff..e9d8406fe4 100644 --- a/lodash.js +++ b/lodash.js @@ -1239,7 +1239,7 @@ case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - return value.subarray(0); + return new Ctor(value.buffer); case numberClass: case stringClass: From 036bf92223cba446e19e05a9719ea93ff171f3d2 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 5 Jun 2014 07:13:07 -0700 Subject: [PATCH 0743/1608] Ensure a byte length is passed. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index e9d8406fe4..ff37680b50 100644 --- a/lodash.js +++ b/lodash.js @@ -653,7 +653,7 @@ /** Native method shortcuts */ var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, - bufferSlice = isNative(bufferSlice = ArrayBuffer && (new ArrayBuffer).slice) && bufferSlice, + bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, ceil = Math.ceil, clearTimeout = context.clearTimeout, Float64Array = isNative(Float64Array = context.Float64Array) && Float64Array, From 8b8a9ae854a6977609c57c4889e1a1ec9adb7299 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 5 Jun 2014 08:51:21 -0700 Subject: [PATCH 0744/1608] Attempt to fix Safari 4. --- lodash.js | 25 +++++++++++++++++++------ test/test.js | 9 +++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/lodash.js b/lodash.js index ff37680b50..8a99891078 100644 --- a/lodash.js +++ b/lodash.js @@ -103,10 +103,11 @@ /** Used to assign default `context` object properties */ var contextProps = [ - 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Error', 'Float64Array', 'Function', - 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', - 'document', 'isFinite', 'isNaN','parseInt', 'setTimeout', 'TypeError', - 'Uint8Array', 'window', 'WinRTError' + 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', + 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', + 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', + 'Uint16Array', 'Uint32Array', 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ @@ -692,6 +693,18 @@ nativeParseInt = context.parseInt, nativeRandom = Math.random; + /** Used to lookup a built-in constructor by [[Class]] */ + var ctorByClass = {}; + ctorByClass[float32Class] = context.Float32Array; + ctorByClass[float64Class] = context.Float64Array; + ctorByClass[int8Class] = context.Int8Array; + ctorByClass[int16Class] = context.Int16Array; + ctorByClass[int32Class] = context.Int32Array; + ctorByClass[uint8Class] = context.Uint8Array; + ctorByClass[uint8ClampedClass] = context.Uint8ClampedArray; + ctorByClass[uint16Class] = context.Uint16Array; + ctorByClass[uint32Class] = context.Uint32Array; + /** Used to avoid iterating over non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; @@ -1239,7 +1252,7 @@ case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - return new Ctor(value.buffer); + return new ctorByClass[className](cloneBuffer(value.buffer)); case numberClass: case stringClass: @@ -1265,7 +1278,7 @@ return stackB[length]; } } - result = isArr ? Ctor(value.length) : Ctor(); + result = isArr ? Ctor(value.length) : new Ctor(); } else { result = isArr ? slice(value) : baseAssign({}, value); diff --git a/test/test.js b/test/test.js index 4679f53686..4716c809a6 100644 --- a/test/test.js +++ b/test/test.js @@ -210,6 +210,7 @@ /** Used to check whether methods support typed arrays */ var typedArrays = [ 'Float32Array', + 'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array', @@ -1287,10 +1288,10 @@ test('`_.' + methodName + '` should clone ' + type + ' arrays', 2, function() { var Ctor = root[type]; if (Ctor) { - var array = new Ctor(new ArrayBuffer(4)), + var array = new Ctor(new ArrayBuffer(8)), actual = func(array); - deepEqual(actual, array); + deepEqual(actual, array, ': ' + (array.constructor === ArrayBuffer)); notStrictEqual(actual, array); } else { @@ -1300,7 +1301,7 @@ }); test('`_.' + methodName + '` should clone array buffers', 2, function() { - var buffer = ArrayBuffer && new ArrayBuffer(4); + var buffer = ArrayBuffer && new ArrayBuffer(8); if (buffer) { var actual = func(buffer); strictEqual(actual.byteLength, buffer.byteLength); @@ -4891,7 +4892,7 @@ test('should perform comparisons between typed arrays', 1, function() { var pairs = _.map(typedArrays, function(type) { var Ctor = root[type] || Array, - buffer = Ctor == Array ? 4 : new ArrayBuffer(4); + buffer = Ctor == Array ? 4 : new ArrayBuffer(8); return [new Ctor(buffer), new Ctor(buffer)]; }); From 9940d73167670c0f8bce4acc0916e3efb6cdc77b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 7 Jun 2014 06:53:02 -0700 Subject: [PATCH 0745/1608] Update requires. --- vendor/requirejs/LICENSE | 2 +- vendor/requirejs/require.js | 88 ++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/vendor/requirejs/LICENSE b/vendor/requirejs/LICENSE index 668ac91618..d3b4181d59 100644 --- a/vendor/requirejs/LICENSE +++ b/vendor/requirejs/LICENSE @@ -37,7 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MIT License ----------- -Copyright (c) 2010-2013, The Dojo Foundation +Copyright (c) 2010-2014, The Dojo Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/requirejs/require.js b/vendor/requirejs/require.js index 24b061e620..7f31fa2041 100644 --- a/vendor/requirejs/require.js +++ b/vendor/requirejs/require.js @@ -1,5 +1,5 @@ /** vim: et:ts=4:sw=4:sts=4 - * @license RequireJS 2.1.11 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. + * @license RequireJS 2.1.14 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/requirejs for details */ @@ -12,7 +12,7 @@ var requirejs, require, define; (function (global) { var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, - version = '2.1.11', + version = '2.1.14', commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, jsSuffixRegExp = /\.js$/, @@ -180,7 +180,7 @@ var requirejs, require, define; if (typeof requirejs !== 'undefined') { if (isFunction(requirejs)) { - //Do not overwrite and existing requirejs instance. + //Do not overwrite an existing requirejs instance. return; } cfg = requirejs; @@ -232,21 +232,20 @@ var requirejs, require, define; * @param {Array} ary the array of path segments. */ function trimDots(ary) { - var i, part, length = ary.length; - for (i = 0; i < length; i++) { + var i, part; + for (i = 0; i < ary.length; i++) { part = ary[i]; if (part === '.') { ary.splice(i, 1); i -= 1; } else if (part === '..') { - if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - break; + // If at the start, or previous value is still .., + // keep them so that when converted to a path it may + // still work when converted to a path, even though + // as an ID it is less than ideal. In larger point + // releases, may be better to just kick out an error. + if (i === 0 || (i == 1 && ary[2] === '..') || ary[i - 1] === '..') { + continue; } else if (i > 0) { ary.splice(i - 1, 2); i -= 2; @@ -267,43 +266,37 @@ var requirejs, require, define; */ function normalize(name, baseName, applyMap) { var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex, - foundMap, foundI, foundStarMap, starI, - baseParts = baseName && baseName.split('/'), - normalizedBaseParts = baseParts, + foundMap, foundI, foundStarMap, starI, normalizedBaseParts, + baseParts = (baseName && baseName.split('/')), map = config.map, starMap = map && map['*']; //Adjust any relative paths. - if (name && name.charAt(0) === '.') { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { + if (name) { + name = name.split('/'); + lastIndex = name.length - 1; + + // If wanting node ID compatibility, strip .js from end + // of IDs. Have to do this here, and not in nameToUrl + // because node allows either .js or non .js to map + // to same file. + if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { + name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); + } + + // Starts with a '.' so need the baseName + if (name[0].charAt(0) === '.' && baseParts) { //Convert baseName to array, and lop off the last part, //so that . matches that 'directory' and not name of the baseName's //module. For instance, baseName of 'one/two/three', maps to //'one/two/three.js', but we want the directory, 'one/two' for //this normalization. normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); - name = name.split('/'); - lastIndex = name.length - 1; - - // If wanting node ID compatibility, strip .js from end - // of IDs. Have to do this here, and not in nameToUrl - // because node allows either .js or non .js to map - // to same file. - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - name = normalizedBaseParts.concat(name); - trimDots(name); - name = name.join('/'); - } else if (name.indexOf('./') === 0) { - // No baseName, so this is ID is resolved relative - // to baseUrl, pull off the leading dot. - name = name.substring(2); } + + trimDots(name); + name = name.join('/'); } //Apply map config if available. @@ -379,7 +372,13 @@ var requirejs, require, define; //retry pathConfig.shift(); context.require.undef(id); - context.require([id]); + + //Custom require that does not do map translation, since + //ID is "absolute", already mapped/resolved. + context.makeRequire(null, { + skipMap: true + })([id]); + return true; } } @@ -445,7 +444,16 @@ var requirejs, require, define; return normalize(name, parentName, applyMap); }); } else { - normalizedName = normalize(name, parentName, applyMap); + // If nested plugin references, then do not try to + // normalize, as it will not normalize correctly. This + // places a restriction on resourceIds, and the longer + // term solution is not to normalize until plugins are + // loaded and all normalizations to allow for async + // loading of a loader plugin. But for now, fixes the + // common uses. Details in #1131 + normalizedName = name.indexOf('!') === -1 ? + normalize(name, parentName, applyMap) : + name; } } else { //A regular module. From 8572445f5723c803bb96ceba473968c8fb28159c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 8 Jun 2014 13:14:23 -0700 Subject: [PATCH 0746/1608] Optimize `_.isEqual` by using `_.keys` and ensure `arguments` objects are compared correctly. --- lodash.js | 108 +++++++++++++++++++++++++-------------------------- test/test.js | 6 ++- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/lodash.js b/lodash.js index 8a99891078..a144a6dab3 100644 --- a/lodash.js +++ b/lodash.js @@ -1278,13 +1278,16 @@ return stackB[length]; } } - result = isArr ? Ctor(value.length) : new Ctor(); + result = isArr ? Ctor(value.length) : new Ctor; } else { result = isArr ? slice(value) : baseAssign({}, value); } + if (className == argsClass || (!support.argsClass && isArguments(value))) { + result.length = value.length; + } // add array properties assigned by `RegExp#exec` - if (isArr) { + else if (isArr) { if (hasOwnProperty.call(value, 'index')) { result.index = value.index; } @@ -1774,8 +1777,8 @@ return false; } var valClass = toString.call(value), - othClass = toString.call(other), valIsArg = valClass == argsClass, + othClass = toString.call(other), othIsArg = othClass == argsClass; if (valIsArg) { @@ -1809,6 +1812,10 @@ // treat string primitives and their corresponding object instances as equal return value == String(other); } + if (!support.argsObject) { + valIsArg = isArguments(value); + othIsArg = isArguments(other); + } var isArr = arrayLikeClasses[valClass]; if (!isArr) { // exit for functions and DOM nodes @@ -1822,10 +1829,6 @@ if (valWrapped || othWrapped) { return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, callback, isWhere, stackA, stackB); } - if (!support.argsObject) { - valIsArg = isArguments(value); - othIsArg = isArguments(other); - } var hasValCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), hasOthCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); @@ -1858,7 +1861,7 @@ return stackB[length] == other; } } - result = true; + var index = -1; // add `value` and `other` to the stack of traversed objects stackA.push(value); @@ -1866,76 +1869,71 @@ // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { - // compare lengths to determine if a deep comparison is necessary var othLength = other.length; length = value.length; - result = othLength == length; + result = length == othLength; if (result || isWhere) { - var othIndex = -1; - // deep compare the contents, ignoring non-numeric properties - while (++othIndex < othLength) { - var othValue = other[othIndex]; - + while (++index < length) { + var valValue = value[index]; if (isWhere) { - var index = -1; - while (++index < length) { - result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB); + var othIndex = -1; + while (++othIndex < othLength) { + var othValue = other[othIndex]; + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); if (result) { break; } } } else { - var valValue = value[othIndex]; - result = callback ? callback(valValue, othValue, othIndex) : undefined; - result = typeof result == 'undefined' - ? baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB) - : !!result; - } - if (!result) { - break; + othValue = other[index]; + result = callback ? callback(valValue, othValue, index) : undefined; + if (typeof result == 'undefined') { + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + } + if (!result) { + break; + } } } } } else { - var size = 0; - - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - baseForIn(other, function(othValue, key, other) { - if (hasOwnProperty.call(other, key)) { - result = false; - // count the number of properties - size++; - // deep compare each property value - if (hasOwnProperty.call(value, key)) { - var valValue = value[key]; + var valProps = keys(value), + othProps = keys(other); + + if (valIsArg) { + valProps.push('length'); + } + if (othIsArg) { + othProps.push('length'); + } + length = valProps.length; + result = length == othProps.length; + + if (result || isWhere) { + while (++index < length) { + var key = valProps[index]; + result = hasOwnProperty.call(other, key); + if (result) { + othValue = other[key]; + valValue = value[key]; result = callback ? callback(valValue, othValue, key) : undefined; - result = typeof result == 'undefined' - ? baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB) - : !!result; + if (typeof result == 'undefined') { + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + } } - return result; - } - }); - - if (result && !isWhere) { - // ensure both objects have the same number of properties - baseForIn(value, function(valValue, key, value) { - if (hasOwnProperty.call(value, key)) { - // `size` will be `-1` if `value` has more properties than `other` - result = --size > -1; - return result; + if (!result) { + break; } - }); + } } } stackA.pop(); stackB.pop(); - return result; + return !!result; } /** @@ -8198,7 +8196,7 @@ while (length--) { var key = props[length]; if (!(hasOwnProperty.call(object, key) && - baseIsEqual(object[key], source[key], null, true))) { + baseIsEqual(source[key], object[key], null, true))) { return false; } } diff --git a/test/test.js b/test/test.js index 4716c809a6..3a82b949f7 100644 --- a/test/test.js +++ b/test/test.js @@ -4661,7 +4661,7 @@ } }); - test('should treat `arguments` objects like `Object` objects', 2, function() { + test('should treat `arguments` objects like `Object` objects', 4, function() { var args = (function() { return arguments; }(1, 2, 3)), object = { '0': 1, '1': 2, '2': 3, 'length': 3 }; @@ -4669,12 +4669,14 @@ Foo.prototype = object; strictEqual(_.isEqual(args, object), true); + strictEqual(_.isEqual(object, args), true); if (!isPhantom) { strictEqual(_.isEqual(args, new Foo), false); + strictEqual(_.isEqual(new Foo, args), false); } else { - skipTest(); + skipTest(2); } }); From 9a152c23bb285c6596aa346adef6ae95abad4875 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 9 Jun 2014 00:17:25 -0700 Subject: [PATCH 0747/1608] Minor `_.sortBy` doc nit. [ci skip] --- lodash.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index a144a6dab3..8344b2db64 100644 --- a/lodash.js +++ b/lodash.js @@ -5073,8 +5073,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it is - * used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If property name(s) or an object is provided it + * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example From d2edf11726556803e38abec3b916292787f0f48d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 9 Jun 2014 01:40:02 -0700 Subject: [PATCH 0748/1608] Ensure `_.callback` supports binding built-in methods. [closes #576] --- lodash.js | 7 +++---- test/test.js | 23 +++++++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lodash.js b/lodash.js index 8344b2db64..ffa4646e48 100644 --- a/lodash.js +++ b/lodash.js @@ -1355,8 +1355,7 @@ if (typeof func != 'function') { return identity; } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { + if (typeof thisArg == 'undefined') { return func; } var data = func[expando]; @@ -1372,7 +1371,7 @@ } if (!data) { // checks if `func` references the `this` keyword and stores the result - data = reThis.test(source); + data = reThis.test(source) || isNative(func); setData(func, data); } } @@ -8117,7 +8116,7 @@ var type = typeof func, isFunc = type == 'function'; - if (isFunc && (typeof thisArg == 'undefined' || !('prototype' in func))) { + if (isFunc && typeof thisArg == 'undefined') { return func; } if (isFunc || func == null) { diff --git a/test/test.js b/test/test.js index 3a82b949f7..0090abf58a 100644 --- a/test/test.js +++ b/test/test.js @@ -1741,16 +1741,16 @@ (function() { test('should create a callback with a falsey `thisArg`', 1, function() { - var values = _.map(falsey, function(value) { + var expected = _.map(falsey, function(value) { return Object(value == null ? root : value); }); - var actual = _.map(values, function(value) { + var actual = _.map(falsey, function(value) { var callback = _.callback(function() { return this; }, value); return callback(); }); - deepEqual(actual, values); + ok(_.isEqual(actual, expected)); }); test('should return `_.identity` when `func` is nullish', 2, function() { @@ -1818,15 +1818,18 @@ deepEqual(callback(2), expected); }); - test('should return the function provided if already bound with `Function#bind`', 1, function() { - function a() {} + test('should support binding built-in methods', 2, function() { + var object = { 'a': 1 }, + callback = _.callback(Object.prototype.hasOwnProperty, object); - var object = {}, - bound = a.bind && a.bind(object); + strictEqual(callback('a'), true); + + var fn = function () {}, + bound = fn.bind && fn.bind(object); - if (bound && !('prototype' in bound)) { - var bound = a.bind(object); - strictEqual(_.callback(bound, object), bound); + if (bound) { + callback = _.callback(bound, object); + notStrictEqual(callback, bound); } else { skipTest(); From 52bb56ba43b3b727554d16aa568dcfe4366d272e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 9 Jun 2014 01:58:04 -0700 Subject: [PATCH 0749/1608] Remove `support.argsObject`. --- lodash.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lodash.js b/lodash.js index ffa4646e48..1a2cf8e1ab 100644 --- a/lodash.js +++ b/lodash.js @@ -839,15 +839,6 @@ */ support.argsClass = toString.call(arguments) == argsClass; - /** - * Detect if `arguments` objects are `Object` objects - * (all but Narwhal and Opera < 10.5). - * - * @memberOf _.support - * @type boolean - */ - support.argsObject = arguments.constructor == Object && !(arguments instanceof Array); - /** * Detect if `name` or `message` properties of `Error.prototype` are * enumerable by default (IE < 9, Safari < 5.1). @@ -1811,7 +1802,7 @@ // treat string primitives and their corresponding object instances as equal return value == String(other); } - if (!support.argsObject) { + if (!support.argsClass) { valIsArg = isArguments(value); othIsArg = isArguments(other); } From 5d2133a483a3d4b18222e9f67c273174822e32a9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 9 Jun 2014 08:35:25 -0700 Subject: [PATCH 0750/1608] Fix unit test for rhino/ringo. --- test/test.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index 0090abf58a..a6f5f7c382 100644 --- a/test/test.js +++ b/test/test.js @@ -1741,13 +1741,18 @@ (function() { test('should create a callback with a falsey `thisArg`', 1, function() { + var fn = function() { return this; }; + var expected = _.map(falsey, function(value) { - return Object(value == null ? root : value); + var result = fn.call(value); + return (result && result.Array) ? root : result; }); var actual = _.map(falsey, function(value) { - var callback = _.callback(function() { return this; }, value); - return callback(); + var callback = _.callback(fn, value), + result = callback(); + + return (result && result.Array) ? root : result; }); ok(_.isEqual(actual, expected)); From 3d1ee9dcf07289b5848e112071512a6942eb81e9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 9 Jun 2014 22:54:52 -0700 Subject: [PATCH 0751/1608] Clarify AMD exports comment. [ci skip] --- lodash.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index 1a2cf8e1ab..74aa205d54 100644 --- a/lodash.js +++ b/lodash.js @@ -8892,9 +8892,9 @@ // some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose Lo-Dash to the global object even when an AMD loader is present in - // case Lo-Dash is loaded with a RequireJS shim config. - // See http://requirejs.org/docs/api.html#config-shim + // Expose Lo-Dash to the global object when an AMD loader is present to avoid + // errors in cases where Lo-Dash is loaded by a script tag and not intended + // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch root._ = _; // define as an anonymous module so, through path mapping, it can be From 885b56000bb0775c86447793f85750170ab828f5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 10 Jun 2014 09:40:53 -0700 Subject: [PATCH 0752/1608] Make less stable tests leverage the retry count of `asyncTest`. --- test/test.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/test/test.js b/test/test.js index a6f5f7c382..b1adc65403 100644 --- a/test/test.js +++ b/test/test.js @@ -2152,7 +2152,7 @@ } }); - test('should support a `maxWait` option', 2, function() { + asyncTest('should support a `maxWait` option', 1, function() { if (!(isRhino && isModularize)) { var limit = (argv || isPhantom) ? 1000 : 320, withCount = 0, @@ -2171,11 +2171,16 @@ withMaxWait(); withoutMaxWait(); } - ok(withCount > 0); - ok(!withoutCount); + var actual = [Boolean(withCount), Boolean(withoutCount)]; + + setTimeout(function() { + deepEqual(actual, [true, false]); + QUnit.start(); + }, 1); } else { - skipTest(2); + skipTest(); + QUnit.start(); } }); @@ -9331,10 +9336,10 @@ }); _.times(2, function(index) { - test('should trigger a call when invoked repeatedly' + (index ? ' and `leading` is `false`' : ''), 1, function() { + asyncTest('should trigger a call when invoked repeatedly' + (index ? ' and `leading` is `false`' : ''), 1, function() { if (!(isRhino && isModularize)) { var count = 0, - limit = 256, + limit = (argv || isPhantom) ? 1000 : 320, options = index ? { 'leading': false } : {}; var throttled = _.throttle(function() { @@ -9345,10 +9350,16 @@ while ((new Date - start) < limit) { throttled(); } - ok(count > 1); + var actual = count > 1; + + setTimeout(function() { + ok(actual); + QUnit.start(); + }, 1); } else { skipTest(); + QUnit.start(); } }); }); @@ -9523,7 +9534,7 @@ setTimeout(function() { deepEqual(actual, expected); QUnit.start(); - }, 48); + }, 42); } else { skipTest(2); From c72171d1dada92c0f8843872d42b5a3c0456e350 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 10 Jun 2014 09:50:10 -0700 Subject: [PATCH 0753/1608] Add `_.once` tests for memorized return values. --- test/test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test.js b/test/test.js index b1adc65403..670f5aa1bf 100644 --- a/test/test.js +++ b/test/test.js @@ -6839,33 +6839,33 @@ QUnit.module('lodash.once'); (function() { - test('should execute `func` once', 1, function() { + test('should execute `func` once', 2, function() { var count = 0, - once = _.once(function() { count++; }); + once = _.once(function() { return ++count; }); once(); - once(); + strictEqual(once(), 1); strictEqual(count, 1); }); - test('should not set a `this` binding', 1, function() { - var once = _.once(function() { this.count++; }), + test('should not set a `this` binding', 2, function() { + var once = _.once(function() { return ++this.count; }), object = { 'count': 0, 'once': once }; object.once(); - object.once(); + strictEqual(object.once(), 1); strictEqual(object.count, 1); }); - test('should ignore recursive calls', 1, function() { + test('should ignore recursive calls', 2, function() { var count = 0; var once = _.once(function() { - count++; once(); + return ++count; }); - once(); + strictEqual(once(), 1); strictEqual(count, 1); }); From e8cfeec0cf8aa336c4ee66fbc4e0ebdbf1d72304 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 10 Jun 2014 17:33:50 -0700 Subject: [PATCH 0754/1608] Cleanup tests and ensure the Worker test waits no more than 30 seconds (including retries). --- test/test.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/test.js b/test/test.js index 670f5aa1bf..7481656f99 100644 --- a/test/test.js +++ b/test/test.js @@ -470,7 +470,7 @@ asyncTest('supports loading ' + basename + ' in a web worker', 1, function() { if (Worker) { - var limit = 15000, + var limit = 30000 / QUnit.config.asyncRetries, start = +new Date; var attempt = function() { @@ -1741,18 +1741,19 @@ (function() { test('should create a callback with a falsey `thisArg`', 1, function() { - var fn = function() { return this; }; + var fn = function() { return this; }, + object = {}; var expected = _.map(falsey, function(value) { var result = fn.call(value); - return (result && result.Array) ? root : result; + return (result && result.Array) ? object : result; }); var actual = _.map(falsey, function(value) { var callback = _.callback(fn, value), result = callback(); - return (result && result.Array) ? root : result; + return (result && result.Array) ? object : result; }); ok(_.isEqual(actual, expected)); @@ -7071,8 +7072,8 @@ }); test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() { - var fn = function(a, b) { return [a, b]; }, - expected = ['a', 'b'], + var expected = ['a', 'b'], + fn = function(a, b) { return [a, b]; }, par = func(fn, 'a'); deepEqual(par('b'), isPartial ? expected : expected.reverse()); From ff2fd45ff0996ca010c3dbb435778f70a4d52ceb Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 10 Jun 2014 17:38:10 -0700 Subject: [PATCH 0755/1608] Only use `ctorByClass` if typed array constructor is incorrect. --- lodash.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 74aa205d54..427f867396 100644 --- a/lodash.js +++ b/lodash.js @@ -1243,7 +1243,11 @@ case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - return new ctorByClass[className](cloneBuffer(value.buffer)); + // Safari 5 mobile incorrectly has `Object` as the constructor + if (Ctor instanceof Ctor) { + Ctor = ctorByClass[className]; + } + return new Ctor(cloneBuffer(value.buffer)); case numberClass: case stringClass: From 4a7873ef77b5dbf8e3ff1ed0e0ee28c8001f48ef Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 10 Jun 2014 21:15:29 -0700 Subject: [PATCH 0756/1608] Update tested Firefox in the readme. [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a705b3c2e..198f664bf5 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl ## Support -Tested in Chrome (19, 34-35), Firefox (3, 20, 28-29), IE 6-11, Opera 21-22, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 34-35), Firefox (3, 20, 29-30), IE 6-11, Opera 21-22, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. From ec89382e358c1847413118bb8882c1a1ce4627f4 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 11 Jun 2014 00:55:36 -0700 Subject: [PATCH 0757/1608] Add error object tests to `_.isEqual`. --- test/test.js | 328 +++++++++++++++++++++++++++++---------------------- 1 file changed, 184 insertions(+), 144 deletions(-) diff --git a/test/test.js b/test/test.js index 7481656f99..976cdc5ef7 100644 --- a/test/test.js +++ b/test/test.js @@ -180,6 +180,17 @@ /** Used to pass empty values to methods */ var empties = [[], {}].concat(falsey.slice(1)); + /** Used to check whether methods support error objects */ + var errorTypes = [ + 'Error', + 'EvalError', + 'RangeError', + 'ReferenceError', + 'SyntaxError', + 'TypeError', + 'URIError' + ]; + /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + _.VERSION + '__'; @@ -1213,17 +1224,10 @@ var objects = { 'an `arguments` object': arguments, - 'an array': ['a', 'b', 'c', ''], - 'an array-like-object': { '0': 'a', '1': 'b', '2': 'c', '3': '', 'length': 5 }, + 'an array': ['a', ''], + 'an array-like-object': { '0': 'a', '1': '', 'length': 3 }, 'boolean': false, 'boolean object': Object(false), - 'an Error object': new Error('text'), - 'an EvalError object': new EvalError('text'), - 'a RangeError object': new RangeError('text'), - 'a ReferenceError object': new ReferenceError('text'), - 'a SyntaxError object': new SyntaxError('text'), - 'a TypeError object': new TypeError('text'), - 'a URIError object': new URIError('text'), 'a Klass instance': new Klass, 'an object': { 'a': 0, 'b': 1, 'c': 3 }, 'an object with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } }, @@ -1237,7 +1241,7 @@ 'undefined': undefined }; - objects['an array'].length = 5; + objects['an array'].length = 3; test('`_.clone` should shallow clone by default', 2, function() { var expected = [{ 'a': 0 }, { 'b': 1 }], @@ -1267,13 +1271,13 @@ _.forOwn(objects, function(object, key) { test('`_.' + methodName + '` should clone ' + key, 2, function() { - var clone = func(object); - ok(_.isEqual(object, clone)); + var actual = func(object); + ok(_.isEqual(actual, object)); if (_.isObject(object)) { - notStrictEqual(clone, object); + notStrictEqual(actual, object); } else { - strictEqual(clone, object); + strictEqual(actual, object); } }); }); @@ -1284,6 +1288,17 @@ }); }); + _.each(errorTypes, function(type) { + test('`_.' + methodName + '` should clone ' + type + ' objects', 2, function() { + var Ctor = root[type], + error = new Ctor('text'), + actual = func(error); + + deepEqual(actual, error); + notStrictEqual(actual, error); + }); + }); + _.each(typedArrays, function(type) { test('`_.' + methodName + '` should clone ' + type + ' arrays', 2, function() { var Ctor = root[type]; @@ -1291,7 +1306,7 @@ var array = new Ctor(new ArrayBuffer(8)), actual = func(array); - deepEqual(actual, array, ': ' + (array.constructor === ArrayBuffer)); + deepEqual(actual, array); notStrictEqual(actual, array); } else { @@ -4473,20 +4488,6 @@ deepEqual(actual, expected); }); - test('should return `false` for objects with custom `toString` methods', 1, function() { - var primitive, - object = { 'toString': function() { return primitive; } }, - values = [true, null, 1, 'a', undefined], - expected = _.map(values, _.constant(false)); - - var actual = _.map(values, function(value) { - primitive = value; - return _.isEqual(object, value); - }); - - deepEqual(actual, expected); - }); - test('should perform comparisons between arrays', 6, function() { var array1 = [true, null, 1, 'a', undefined], array2 = [true, null, 1, 'a', undefined]; @@ -4546,19 +4547,12 @@ strictEqual(_.isEqual(array1, array2), true); }); - test('should perform comparisons between date objects', 4, function() { - strictEqual(_.isEqual(new Date(2012, 4, 23), new Date(2012, 4, 23)), true); - strictEqual(_.isEqual(new Date(2012, 4, 23), new Date(2013, 3, 25)), false); - strictEqual(_.isEqual(new Date(2012, 4, 23), { 'getTime': function() { return 1337756400000; } }), false); - strictEqual(_.isEqual(new Date('a'), new Date('a')), false); - }); - - test('should perform comparisons between functions', 2, function() { - function a() { return 1 + 2; } - function b() { return 1 + 2; } + test('should work with sparse arrays', 3, function() { + var array = Array(1); - strictEqual(_.isEqual(a, a), true); - strictEqual(_.isEqual(a, b), false); + strictEqual(_.isEqual(array, Array(1)), true); + strictEqual(_.isEqual(array, [undefined]), true); + strictEqual(_.isEqual(array, Array(2)), false); }); test('should perform comparisons between plain objects', 5, function() { @@ -4635,69 +4629,6 @@ strictEqual(_.isEqual({ 'value': 2 }, new Bar), false); }); - test('should perform comparisons between regexes', 5, function() { - strictEqual(_.isEqual(/x/gim, /x/gim), true); - strictEqual(_.isEqual(/x/gim, /x/mgi), true); - strictEqual(_.isEqual(/x/gi, /x/g), false); - strictEqual(_.isEqual(/x/, /y/), false); - strictEqual(_.isEqual(/x/g, { 'global': true, 'ignoreCase': false, 'multiline': false, 'source': 'x' }), false); - }); - - test('should avoid common type coercions', 9, function() { - strictEqual(_.isEqual(true, new Boolean(false)), false); - strictEqual(_.isEqual(new Boolean(false), new Number(0)), false); - strictEqual(_.isEqual(false, new String('')), false); - strictEqual(_.isEqual(new Number(36), new String(36)), false); - strictEqual(_.isEqual(0, ''), false); - strictEqual(_.isEqual(1, true), false); - strictEqual(_.isEqual(1337756400000, new Date(2012, 4, 23)), false); - strictEqual(_.isEqual('36', 36), false); - strictEqual(_.isEqual(36, '36'), false); - }); - - test('should work with sparse arrays', 2, function() { - strictEqual(_.isEqual(Array(3), Array(3)), true); - strictEqual(_.isEqual(Array(3), Array(6)), false); - }); - - test('should work with `arguments` objects (test in IE < 9)', 2, function() { - var args1 = (function() { return arguments; }(1, 2, 3)), - args2 = (function() { return arguments; }(1, 2, 3)), - args3 = (function() { return arguments; }(1, 2)); - - strictEqual(_.isEqual(args1, args2), true); - - if (!isPhantom) { - strictEqual(_.isEqual(args1, args3), false); - } - else { - skipTest(); - } - }); - - test('should treat `arguments` objects like `Object` objects', 4, function() { - var args = (function() { return arguments; }(1, 2, 3)), - object = { '0': 1, '1': 2, '2': 3, 'length': 3 }; - - function Foo() {} - Foo.prototype = object; - - strictEqual(_.isEqual(args, object), true); - strictEqual(_.isEqual(object, args), true); - - if (!isPhantom) { - strictEqual(_.isEqual(args, new Foo), false); - strictEqual(_.isEqual(new Foo, args), false); - } - else { - skipTest(2); - } - }); - - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { - strictEqual(_.isEqual(shadowedObject, {}), false); - }); - test('should perform comparisons between objects with constructor properties', 5, function() { strictEqual(_.isEqual({ 'constructor': 1 }, { 'constructor': 1 }), true); strictEqual(_.isEqual({ 'constructor': 1 }, { 'constructor': '1' }), false); @@ -4813,6 +4744,132 @@ strictEqual(_.isEqual(object1, object2), true); }); + test('should work with `arguments` objects (test in IE < 9)', 2, function() { + var args1 = (function() { return arguments; }(1, 2, 3)), + args2 = (function() { return arguments; }(1, 2, 3)), + args3 = (function() { return arguments; }(1, 2)); + + strictEqual(_.isEqual(args1, args2), true); + + if (!isPhantom) { + strictEqual(_.isEqual(args1, args3), false); + } + else { + skipTest(); + } + }); + + test('should treat `arguments` objects like `Object` objects', 4, function() { + var args = (function() { return arguments; }(1, 2, 3)), + object = { '0': 1, '1': 2, '2': 3, 'length': 3 }; + + function Foo() {} + Foo.prototype = object; + + strictEqual(_.isEqual(args, object), true); + strictEqual(_.isEqual(object, args), true); + + if (!isPhantom) { + strictEqual(_.isEqual(args, new Foo), false); + strictEqual(_.isEqual(new Foo, args), false); + } + else { + skipTest(2); + } + }); + + test('should perform comparisons between date objects', 4, function() { + strictEqual(_.isEqual(new Date(2012, 4, 23), new Date(2012, 4, 23)), true); + strictEqual(_.isEqual(new Date(2012, 4, 23), new Date(2013, 3, 25)), false); + strictEqual(_.isEqual(new Date(2012, 4, 23), { 'getTime': function() { return 1337756400000; } }), false); + strictEqual(_.isEqual(new Date('a'), new Date('a')), false); + }); + + test('should perform comparisons between error objects', 1, function() { + var pairs = _.map(errorTypes, function(type, index) { + var otherType = errorTypes[++index % errorTypes.length], + CtorA = root[type], + CtorB = root[otherType]; + + return [new CtorA('a'), new CtorA('a'), new CtorB('a'), new CtorB('b')]; + }); + + var expected = _.times(pairs.length, _.constant([true, false, false])); + + var actual = _.map(pairs, function(pair) { + return [_.isEqual(pair[0], pair[1]), _.isEqual(pair[0], pair[2]), _.isEqual(pair[2], pair[3])]; + }); + + deepEqual(actual, expected); + }); + + test('should perform comparisons between functions', 2, function() { + function a() { return 1 + 2; } + function b() { return 1 + 2; } + + strictEqual(_.isEqual(a, a), true); + strictEqual(_.isEqual(a, b), false); + }); + + test('should perform comparisons between regexes', 5, function() { + strictEqual(_.isEqual(/x/gim, /x/gim), true); + strictEqual(_.isEqual(/x/gim, /x/mgi), true); + strictEqual(_.isEqual(/x/gi, /x/g), false); + strictEqual(_.isEqual(/x/, /y/), false); + strictEqual(_.isEqual(/x/g, { 'global': true, 'ignoreCase': false, 'multiline': false, 'source': 'x' }), false); + }); + + test('should perform comparisons between typed arrays', 1, function() { + var pairs = _.map(typedArrays, function(type, index) { + var otherType = typedArrays[++index % typedArrays.length], + CtorA = root[type] || Array, + CtorB = root[otherType] || Array, + bufferA = CtorA == Array ? 8 : new ArrayBuffer(8), + bufferB = CtorB == Array ? 8 : new ArrayBuffer(8), + bufferC = CtorB == Array ? 16 : new ArrayBuffer(16); + + return [new CtorA(bufferA), new CtorA(bufferA), new CtorB(bufferB), new CtorB(bufferC)]; + }); + + var expected = _.times(pairs.length, _.constant([true, false, false])); + + var actual = _.map(pairs, function(pair) { + return [_.isEqual(pair[0], pair[1]), _.isEqual(pair[0], pair[2]), _.isEqual(pair[2], pair[3])]; + }); + + deepEqual(actual, expected); + }); + + test('should avoid common type coercions', 9, function() { + strictEqual(_.isEqual(true, new Boolean(false)), false); + strictEqual(_.isEqual(new Boolean(false), new Number(0)), false); + strictEqual(_.isEqual(false, new String('')), false); + strictEqual(_.isEqual(new Number(36), new String(36)), false); + strictEqual(_.isEqual(0, ''), false); + strictEqual(_.isEqual(1, true), false); + strictEqual(_.isEqual(1337756400000, new Date(2012, 4, 23)), false); + strictEqual(_.isEqual('36', 36), false); + strictEqual(_.isEqual(36, '36'), false); + }); + + test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + strictEqual(_.isEqual(shadowedObject, {}), false); + }); + + test('should return `false` for objects with custom `toString` methods', 1, function() { + var primitive, + object = { 'toString': function() { return primitive; } }, + values = [true, null, 1, 'a', undefined], + expected = _.map(values, _.constant(false)); + + var actual = _.map(values, function(value) { + primitive = value; + return _.isEqual(object, value); + }); + + deepEqual(actual, expected); + }); + test('should pass the correct `callback` arguments', 1, function() { var argsList = []; @@ -4905,21 +4962,31 @@ } }); - test('should perform comparisons between typed arrays', 1, function() { - var pairs = _.map(typedArrays, function(type) { - var Ctor = root[type] || Array, - buffer = Ctor == Array ? 4 : new ArrayBuffer(8); - - return [new Ctor(buffer), new Ctor(buffer)]; - }); - - var expected = _.times(pairs.length, _.constant(true)); + test('should return `true` for like-objects from different documents', 1, function() { + // ensure `_._object` is assigned (unassigned in Opera 10.00) + if (_._object) { + var object = { 'a': 1, 'b': 2, 'c': 3 }; + strictEqual(_.isEqual(object, _._object), true); + } + else { + skipTest(); + } + }); - var actual = _.map(pairs, function(pair) { - return _.isEqual(pair[0], pair[1]); - }); + test('should not error on DOM elements', 1, function() { + if (document) { + var element1 = document.createElement('div'), + element2 = element1.cloneNode(true); - deepEqual(actual, expected); + try { + strictEqual(_.isEqual(element1, element2), false); + } catch(e) { + ok(false); + } + } + else { + skipTest(); + } }); test('should perform comparisons between wrapped values', 4, function() { @@ -4962,33 +5029,6 @@ } }); - test('should return `true` for like-objects from different documents', 1, function() { - // ensure `_._object` is assigned (unassigned in Opera 10.00) - if (_._object) { - var object = { 'a': 1, 'b': 2, 'c': 3 }; - strictEqual(_.isEqual(object, _._object), true); - } - else { - skipTest(); - } - }); - - test('should not error on DOM elements', 1, function() { - if (document) { - var element1 = document.createElement('div'), - element2 = element1.cloneNode(true); - - try { - strictEqual(_.isEqual(element1, element2), false); - } catch(e) { - ok(false); - } - } - else { - skipTest(); - } - }); - test('should return an unwrapped value when intuitively chaining', 1, function() { if (!isNpm) { strictEqual(_('a').isEqual('a'), true); From e5ccfc44461913d91dac3f3a4f12c542ad1c5403 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 11 Jun 2014 09:26:21 -0700 Subject: [PATCH 0758/1608] Ensure `_.where` returns elements that contain all source array values. [closes #583] --- lodash.js | 19 ++++++++--------- test/test.js | 58 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/lodash.js b/lodash.js index 427f867396..2471d85bac 100644 --- a/lodash.js +++ b/lodash.js @@ -1867,28 +1867,27 @@ length = value.length; result = length == othLength; - if (result || isWhere) { + if (result || (isWhere && othLength > length)) { // deep compare the contents, ignoring non-numeric properties while (++index < length) { var valValue = value[index]; if (isWhere) { - var othIndex = -1; - while (++othIndex < othLength) { - var othValue = other[othIndex]; - result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + var othIndex = othLength; + while (othIndex--) { + result = baseIsEqual(valValue, other[othIndex], callback, isWhere, stackA, stackB); if (result) { break; } } } else { - othValue = other[index]; + var othValue = other[index]; result = callback ? callback(valValue, othValue, index) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); } - if (!result) { - break; - } + } + if (!result) { + break; } } } @@ -1911,8 +1910,8 @@ var key = valProps[index]; result = hasOwnProperty.call(other, key); if (result) { - othValue = other[key]; valValue = value[key]; + othValue = other[key]; result = callback ? callback(valValue, othValue, key) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); diff --git a/test/test.js b/test/test.js index 976cdc5ef7..4bf9c63230 100644 --- a/test/test.js +++ b/test/test.js @@ -10138,16 +10138,24 @@ { 'a': 3 } ]; - test('should filter by `source` properties', 6, function() { - deepEqual(_.where(objects, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]); - deepEqual(_.where(objects, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]); - deepEqual(_.where(objects, { 'a': 3 }), [{ 'a': 3 }]); - deepEqual(_.where(objects, { 'b': 1 }), []); - deepEqual(_.where(objects, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]); - deepEqual(_.where(objects, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]); + test('should filter by `source` properties', 12, function() { + var pairs = [ + [{ 'a': 1 }, [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]], + [{ 'a': 2 }, [{ 'a': 2, 'b': 2 }]], + [{ 'a': 3 }, [{ 'a': 3 }]], + [{ 'b': 1 }, []], + [{ 'b': 2 }, [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]], + [{ 'a': 1, 'b': 2 }, [{ 'a': 1, 'b': 2 }]] + ]; + + _.each(pairs, function(pair) { + var actual = _.where(objects, pair[0]); + deepEqual(actual, pair[1]); + ok(_.isEmpty(_.difference(actual, objects))); + }); }); - test('should not filter by inherited `source` properties', 2, function() { + test('should not filter by inherited `source` properties', 1, function() { function Foo() {} Foo.prototype = { 'a': 2 }; @@ -10158,7 +10166,6 @@ actual = _.where(objects, source); deepEqual(actual, expected); - ok(_.isEmpty(_.difference(actual, objects))); }); test('should filter by problem JScript properties (test in IE < 9)', 1, function() { @@ -10166,7 +10173,7 @@ deepEqual(_.where(collection, shadowedObject), [shadowedObject]); }); - test('should work with an object for `collection`', 2, function() { + test('should work with an object for `collection`', 1, function() { var collection = { 'x': { 'a': 1 }, 'y': { 'a': 3 }, @@ -10177,7 +10184,6 @@ actual = _.where(collection, { 'a': 1 }); deepEqual(actual, expected); - ok(_.isEmpty(_.difference(actual, _.values(collection)))); }); test('should work with a function for `source`', 1, function() { @@ -10198,32 +10204,38 @@ deepEqual(actual, expected); }); - test('should perform a deep partial comparison of `source`', 2, function() { + test('should perform a deep partial comparison of `source`', 1, function() { var collection = [{ 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4 }], expected = collection.slice(), actual = _.where(collection, { 'a': { 'b': { 'c': 1 } } }); deepEqual(actual, expected); - ok(_.isEmpty(_.difference(actual, collection))); }); - test('should search of arrays for values', 2, function() { - var collection = [{ 'a': [1, 2] }], - expected = collection.slice(); + test('should search arrays of `source` for values', 4, function() { + var collection = [{ 'a': ['b'] }, { 'a': ['c', 'd'] }], + actual = _.where(collection, { 'a': ['d'] }); - deepEqual(_.where(collection, { 'a': [] }), []); - deepEqual(_.where(collection, { 'a': [2] }), expected); + deepEqual(actual, [collection[1]]); + + actual = _.where(collection, { 'a': [] }); + deepEqual(actual, []); + + actual = _.where(collection, { 'a': ['b', 'd'] }); + deepEqual(actual, []); + + actual = _.where(collection, { 'a': ['d', 'b'] }); + deepEqual(actual, []); }); - test('should perform a partial comparison of *all* objects within arrays of `source`', 2, function() { + test('should perform a partial comparison of all objects within arrays of `source`', 1, function() { var collection = [ - { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 5, 'd': 6 }] }, - { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 6, 'd': 7 }] } + { 'a': [{ 'b': 1, 'c': 2 }, { 'b': 4, 'c': 5, 'd': 6 }] }, + { 'a': [{ 'b': 1, 'c': 2 }, { 'b': 4, 'c': 6, 'd': 7 }] } ]; - var actual = _.where(collection, { 'a': [{ 'b': 1, 'c': 2 }, { 'b': 4, 'c': 5 }] }); + var actual = _.where(collection, { 'a': [{ 'b': 1 }, { 'b': 4, 'c': 5 }] }); deepEqual(actual, [collection[0]]); - ok(_.isEmpty(_.difference(actual, collection))); }); test('should handle a `source` with `undefined` values', 4, function() { From 1f07f9d1275951b827f097860710781404f8c0c5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 11 Jun 2014 09:50:19 -0700 Subject: [PATCH 0759/1608] Fix `_.isEqual` test in environment w/o typed arrays. --- test/test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index 4bf9c63230..e80b28f822 100644 --- a/test/test.js +++ b/test/test.js @@ -4822,11 +4822,11 @@ test('should perform comparisons between typed arrays', 1, function() { var pairs = _.map(typedArrays, function(type, index) { var otherType = typedArrays[++index % typedArrays.length], - CtorA = root[type] || Array, - CtorB = root[otherType] || Array, - bufferA = CtorA == Array ? 8 : new ArrayBuffer(8), - bufferB = CtorB == Array ? 8 : new ArrayBuffer(8), - bufferC = CtorB == Array ? 16 : new ArrayBuffer(16); + CtorA = root[type] || function(n) { this.n = n; }, + CtorB = root[otherType] || function(n) { this.n = n; }, + bufferA = root[type] ? new ArrayBuffer(8) : 8, + bufferB = root[otherType] ? new ArrayBuffer(8) : 8, + bufferC = root[otherType] ? new ArrayBuffer(16) : 16; return [new CtorA(bufferA), new CtorA(bufferA), new CtorB(bufferB), new CtorB(bufferC)]; }); From 6ab04866ecc7891464e30ad1337ebb7184b3cbd4 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 11 Jun 2014 12:23:42 -0700 Subject: [PATCH 0760/1608] Fix failing tests. --- lodash.js | 10 ++++++---- test/test.js | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lodash.js b/lodash.js index 2471d85bac..d5039ce7b2 100644 --- a/lodash.js +++ b/lodash.js @@ -1791,6 +1791,10 @@ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +value == +other; + case errorClass: + // check properties instead of coercing to strings to support IE < 8 + return value.name === other.name && value.message === other.message; + case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) @@ -1798,12 +1802,10 @@ // but treat `-0` vs. `+0` as not equal : (value == 0 ? (1 / value == 1 / other) : value == +other); - case errorClass: case regexpClass: case stringClass: - // coerce errors (http://es5.github.io/#x15.11.4.4) - // and regexes (http://es5.github.io/#x15.10.6.4) to strings - // treat string primitives and their corresponding object instances as equal + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) + // treat string primitives and object instances as equal return value == String(other); } if (!support.argsClass) { diff --git a/test/test.js b/test/test.js index e80b28f822..059ecfd1d3 100644 --- a/test/test.js +++ b/test/test.js @@ -1272,6 +1272,7 @@ _.forOwn(objects, function(object, key) { test('`_.' + methodName + '` should clone ' + key, 2, function() { var actual = func(object); + ok(_.isEqual(actual, object)); if (_.isObject(object)) { @@ -1294,7 +1295,7 @@ error = new Ctor('text'), actual = func(error); - deepEqual(actual, error); + ok(_.isEqual(actual, error)); notStrictEqual(actual, error); }); }); From 3c5655fc3d7a97879f63dc6baf5e774c150f9aab Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 11 Jun 2014 12:29:06 -0700 Subject: [PATCH 0761/1608] Rebuild dist. --- dist/lodash.compat.js | 168 ++++++++++++++++++---------------- dist/lodash.compat.min.js | 124 ++++++++++++------------- dist/lodash.js | 135 ++++++++++++++------------- dist/lodash.min.js | 114 +++++++++++------------ dist/lodash.underscore.js | 48 +++++----- dist/lodash.underscore.min.js | 35 ++++--- 6 files changed, 311 insertions(+), 313 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index dcc866ee47..6794893c64 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -104,10 +104,11 @@ /** Used to assign default `context` object properties */ var contextProps = [ - 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Error', 'Float64Array', 'Function', - 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', - 'document', 'isFinite', 'isNaN','parseInt', 'setTimeout', 'TypeError', - 'Uint8Array', 'window', 'WinRTError' + 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', + 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', + 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', + 'Uint16Array', 'Uint32Array', 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ @@ -654,7 +655,7 @@ /** Native method shortcuts */ var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, - bufferSlice = isNative(bufferSlice = ArrayBuffer && (new ArrayBuffer).slice) && bufferSlice, + bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, ceil = Math.ceil, clearTimeout = context.clearTimeout, Float64Array = isNative(Float64Array = context.Float64Array) && Float64Array, @@ -693,6 +694,18 @@ nativeParseInt = context.parseInt, nativeRandom = Math.random; + /** Used to lookup a built-in constructor by [[Class]] */ + var ctorByClass = {}; + ctorByClass[float32Class] = context.Float32Array; + ctorByClass[float64Class] = context.Float64Array; + ctorByClass[int8Class] = context.Int8Array; + ctorByClass[int16Class] = context.Int16Array; + ctorByClass[int32Class] = context.Int32Array; + ctorByClass[uint8Class] = context.Uint8Array; + ctorByClass[uint8ClampedClass] = context.Uint8ClampedArray; + ctorByClass[uint16Class] = context.Uint16Array; + ctorByClass[uint32Class] = context.Uint32Array; + /** Used to avoid iterating over non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; @@ -827,15 +840,6 @@ */ support.argsClass = toString.call(arguments) == argsClass; - /** - * Detect if `arguments` objects are `Object` objects - * (all but Narwhal and Opera < 10.5). - * - * @memberOf _.support - * @type boolean - */ - support.argsObject = arguments.constructor == Object && !(arguments instanceof Array); - /** * Detect if `name` or `message` properties of `Error.prototype` are * enumerable by default (IE < 9, Safari < 5.1). @@ -1240,7 +1244,11 @@ case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - return value.subarray(0); + // Safari 5 mobile incorrectly has `Object` as the constructor + if (Ctor instanceof Ctor) { + Ctor = ctorByClass[className]; + } + return new Ctor(cloneBuffer(value.buffer)); case numberClass: case stringClass: @@ -1266,13 +1274,16 @@ return stackB[length]; } } - result = isArr ? Ctor(value.length) : Ctor(); + result = isArr ? Ctor(value.length) : new Ctor; } else { result = isArr ? slice(value) : baseAssign({}, value); } + if (className == argsClass || (!support.argsClass && isArguments(value))) { + result.length = value.length; + } // add array properties assigned by `RegExp#exec` - if (isArr) { + else if (isArr) { if (hasOwnProperty.call(value, 'index')) { result.index = value.index; } @@ -1340,8 +1351,7 @@ if (typeof func != 'function') { return identity; } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { + if (typeof thisArg == 'undefined') { return func; } var data = func[expando]; @@ -1357,7 +1367,7 @@ } if (!data) { // checks if `func` references the `this` keyword and stores the result - data = reThis.test(source); + data = reThis.test(source) || isNative(func); setData(func, data); } } @@ -1762,8 +1772,8 @@ return false; } var valClass = toString.call(value), - othClass = toString.call(other), valIsArg = valClass == argsClass, + othClass = toString.call(other), othIsArg = othClass == argsClass; if (valIsArg) { @@ -1782,6 +1792,10 @@ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +value == +other; + case errorClass: + // check properties instead of coercing to strings to support IE < 8 + return value.name === other.name && value.message === other.message; + case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) @@ -1789,14 +1803,16 @@ // but treat `-0` vs. `+0` as not equal : (value == 0 ? (1 / value == 1 / other) : value == +other); - case errorClass: case regexpClass: case stringClass: - // coerce errors (http://es5.github.io/#x15.11.4.4) - // and regexes (http://es5.github.io/#x15.10.6.4) to strings - // treat string primitives and their corresponding object instances as equal + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) + // treat string primitives and object instances as equal return value == String(other); } + if (!support.argsClass) { + valIsArg = isArguments(value); + othIsArg = isArguments(other); + } var isArr = arrayLikeClasses[valClass]; if (!isArr) { // exit for functions and DOM nodes @@ -1810,10 +1826,6 @@ if (valWrapped || othWrapped) { return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, callback, isWhere, stackA, stackB); } - if (!support.argsObject) { - valIsArg = isArguments(value); - othIsArg = isArguments(other); - } var hasValCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), hasOthCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); @@ -1846,7 +1858,7 @@ return stackB[length] == other; } } - result = true; + var index = -1; // add `value` and `other` to the stack of traversed objects stackA.push(value); @@ -1854,32 +1866,28 @@ // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { - // compare lengths to determine if a deep comparison is necessary var othLength = other.length; length = value.length; - result = othLength == length; - - if (result || isWhere) { - var othIndex = -1; + result = length == othLength; + if (result || (isWhere && othLength > length)) { // deep compare the contents, ignoring non-numeric properties - while (++othIndex < othLength) { - var othValue = other[othIndex]; - + while (++index < length) { + var valValue = value[index]; if (isWhere) { - var index = -1; - while (++index < length) { - result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB); + var othIndex = othLength; + while (othIndex--) { + result = baseIsEqual(valValue, other[othIndex], callback, isWhere, stackA, stackB); if (result) { break; } } } else { - var valValue = value[othIndex]; - result = callback ? callback(valValue, othValue, othIndex) : undefined; - result = typeof result == 'undefined' - ? baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB) - : !!result; + var othValue = other[index]; + result = callback ? callback(valValue, othValue, index) : undefined; + if (typeof result == 'undefined') { + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + } } if (!result) { break; @@ -1888,42 +1896,40 @@ } } else { - var size = 0; - - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - baseForIn(other, function(othValue, key, other) { - if (hasOwnProperty.call(other, key)) { - result = false; - // count the number of properties - size++; - // deep compare each property value - if (hasOwnProperty.call(value, key)) { - var valValue = value[key]; + var valProps = keys(value), + othProps = keys(other); + + if (valIsArg) { + valProps.push('length'); + } + if (othIsArg) { + othProps.push('length'); + } + length = valProps.length; + result = length == othProps.length; + + if (result || isWhere) { + while (++index < length) { + var key = valProps[index]; + result = hasOwnProperty.call(other, key); + if (result) { + valValue = value[key]; + othValue = other[key]; result = callback ? callback(valValue, othValue, key) : undefined; - result = typeof result == 'undefined' - ? baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB) - : !!result; + if (typeof result == 'undefined') { + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + } } - return result; - } - }); - - if (result && !isWhere) { - // ensure both objects have the same number of properties - baseForIn(value, function(valValue, key, value) { - if (hasOwnProperty.call(value, key)) { - // `size` will be `-1` if `value` has more properties than `other` - result = --size > -1; - return result; + if (!result) { + break; } - }); + } } } stackA.pop(); stackB.pop(); - return result; + return !!result; } /** @@ -5063,8 +5069,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it is - * used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If property name(s) or an object is provided it + * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example @@ -8107,7 +8113,7 @@ var type = typeof func, isFunc = type == 'function'; - if (isFunc && (typeof thisArg == 'undefined' || !('prototype' in func))) { + if (isFunc && typeof thisArg == 'undefined') { return func; } if (isFunc || func == null) { @@ -8186,7 +8192,7 @@ while (length--) { var key = props[length]; if (!(hasOwnProperty.call(object, key) && - baseIsEqual(object[key], source[key], null, true))) { + baseIsEqual(source[key], object[key], null, true))) { return false; } } @@ -8892,9 +8898,9 @@ // some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose Lo-Dash to the global object even when an AMD loader is present in - // case Lo-Dash is loaded with a RequireJS shim config. - // See http://requirejs.org/docs/api.html#config-shim + // Expose Lo-Dash to the global object when an AMD loader is present to avoid + // errors in cases where Lo-Dash is loaded by a script tag and not intended + // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch root._ = _; // define as an anonymous module so, through path mapping, it can be diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index b743d3c0ca..6a10a47621 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -4,68 +4,68 @@ * Build: `lodash -o ./dist/lodash.compat.js` */ ;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=ue(e);++ra(t,l)&&f.push(l);return f}function Tt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1o?0:o>>>0);return Tt(n,function(n){var o=u?t:null!=n&&n[t];a[++e]=o?o.apply(n,r):m}),a}function Vt(n,t,r,e,u){var o=ar(t);return(o?jt:zt)(t,function(t,a,i){var l=t&&ar(t),f=t&&au(t),c=n[a];if(l||f){for(e||(e=[]),u||(u=[]),f=e.length;f--;)if(e[f]==t)return void(n[a]=u[f]);i=r?r(c,t,a,n,i):m,(f=typeof i!="undefined")||(i=l?ou(c)?c:[]:au(c)?c:{}),e.push(t),u.push(i),f||Vt(i,t,r,e,u),n[a]=i}else i=r?r(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i) -}),n}function Jt(n,t){var r={};if(typeof t=="function")return Dt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r;for(var e=-1,u=t.length;++ei(s,g)&&((u||f)&&s.push(g),c.push(p)) -}return c}function Gt(n,t){for(var r=-1,e=t(n),u=e.length,o=ue(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3e||13e||8202r||13r||8202>>0:0,u=ue(e);++ra(t,l)&&f.push(l);return f}function Lt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1l)for(;++fo?0:o>>>0);return Lt(n,function(n){var o=u?t:null!=n&&n[t];a[++e]=o?o.apply(n,r):m}),a}function Vt(n,t,r,e,u){var o=ar(t);return(o?jt:zt)(t,function(t,a,i){var l=t&&ar(t),f=t&&iu(t),c=n[a];if(l||f){for(e||(e=[]),u||(u=[]),f=e.length;f--;)if(e[f]==t)return void(n[a]=u[f]);i=r?r(c,t,a,n,i):m,(f=typeof i!="undefined")||(i=l?au(c)?c:[]:iu(c)?c:{}),e.push(t),u.push(i),f||Vt(i,t,r,e,u),n[a]=i}else i=r?r(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i) +}),n}function Jt(n,t){var r={};if(typeof t=="function")return Dt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r;for(var e=-1,u=t.length;++ei(s,g)&&((u||f)&&s.push(g),c.push(p)) +}return c}function Gt(n,t){for(var r=-1,e=t(n),u=e.length,o=ue(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3o?0:o)}function gr(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?Ze(u+e,0):e||0;else if(e)return e=mr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function hr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),dr(n,0,0>o?0:o)}function vr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:m;return o=e-(o||0),dr(n,0>o?0:o)}function yr(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,r,3);++et?0:t;return dr(n,o)}function dr(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t?t=Ze(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=Ze(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=ue(u);++e>>1,r(n[e])r?0:r);++tr?Ze(e+r,0):r||0:0,typeof n=="string"||!ou(n)&&Kr(n)?ro&&(o=i)}else t=null==t&&Kr(n)?u:q.createCallback(t,r,3),Tt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Rr(n,t){return Sr(n,ee(t))}function Fr(n,t,r,e){var u=3>arguments.length; -if(t=q.createCallback(t,e,4),ou(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=q.createCallback(t,e,4),Wt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Lr(n){var t=-1,r=n&&n.length,e=ue(0>r?0:r>>>0);return Tt(n,function(n){var r=Xt(0,++t);e[t]=e[r],e[r]=n}),e}function Tr(n,t,r){var e;if((typeof t!="function"||typeof r!="undefined")&&(t=q.createCallback(t,r,3)),ou(n)){r=-1; -for(var u=n.length;++rarguments.length)return er(n,b,null,t);if(n)var r=n[A]?n[A][2]:n.length,e=dr(arguments,2),r=r-e.length;return er(n,b|x,r,t,e)}function Ur(n,t,r){function e(){var r=t-(pu()-f);0>=r||r>t?(i&&Ae(i),r=p,i=s=p=m,r&&(g=pu(),l=n.apply(c,a),s||i||(a=c=null))):s=Le(e,r)}function u(){s&&Ae(s),i=s=p=m,(v||h!==t)&&(g=pu(),l=n.apply(c,a),s||i||(a=c=null))}function o(){if(a=arguments,f=pu(),c=this,p=v&&(s||!y),false===h)var r=y&&!s; -else{i||y||(g=f);var o=h-(f-g),d=0>=o||o>h;d?(i&&(i=Ae(i)),g=f,l=n.apply(c,a)):i||(i=Le(u,o))}return d&&s?s=Ae(s):s||t===h||(s=Le(e,t)),r&&(d=true,l=n.apply(c,a)),!d||s||i||(a=c=null),l}var a,i,l,f,c,s,p,g=0,h=false,v=true;if(!zr(n))throw new pe(O);if(t=0>t?0:t,true===r)var y=true,v=false;else qr(r)&&(y=r.leading,h="maxWait"in r&&Ze(t,+r.maxWait||0),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&Ae(s),i&&Ae(i),i=s=p=m},o}function $r(n){if(!zr(n))throw new pe(O);return function(){return!n.apply(this,arguments) -}}function Pr(n){return Mt(n,Vr)}function Br(n){return n&&typeof n=="object"&&typeof n.length=="number"&&we.call(n)==H||false}function Dr(n){return n&&typeof n=="object"&&1===n.nodeType&&(Ge.nodeClass?-1>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,a=r-1,e=ue(r),i=0t||null==n||!ze(t))return r;n=se(n);do t%2&&(r+=n),t=Ee(t/2),n+=n;while(t);return r}function Gr(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n),v(n)+1):(t=se(t),n.slice(o(n,t),a(n,t)+1)):n}function Hr(n,t,r){var e=typeof n,u="function"==e;return!u||typeof t!="undefined"&&"prototype"in n?u||null==n?Ft(n,t,r):"object"==e?ne(n):ee(n):n -}function Qr(n){return n}function ne(n){var t=iu(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||qr(u)?function(e){var u=r;if(u&&!e)return false;for(;u--;){var o=t[u];if(!Ie.call(e,o)||!Zt(e[o],n[o],null,true))return false}return true}:function(n){return n&&Ie.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function te(n,t,r){var e=true,u=t&&Mt(t,iu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Mt(t,iu)),false===r?e=false:qr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=zr(n),a=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},q.assign=uu,q.at=function(t){return Ge.unindexedChars&&Kr(t)&&(t=t.split("")),n(t,$t(arguments,true,false,1))},q.bind=Wr,q.bindAll=function(n){for(var t=n,r=1arguments.length?er(t,b|_,null,n):er(t,b|_|x,null,n,dr(arguments,2)) -},q.chain=function(n){return new J(n,true)},q.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?e(p,l):a(s,l))){for(t=u;--t;){var g=o[t];if(0>(g?e(g,l):a(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},q.invert=function(n,t){for(var r=-1,e=iu(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=q.createCallback(t,r,3)),Tt(n,function(n,r,u){if(o)for(r=t.length,u=ue(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?l:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,r){return t.call(r,n),n},q.throttle=function(n,t,r){var e=true,u=true;if(!zr(n))throw new pe(O);return false===r?e=false:qr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),_t.leading=e,_t.maxWait=+t,_t.trailing=u,Ur(n,t,_t) -},q.times=function(n,t,r){n=0>n?0:n>>>0,t=Ft(t,r,1),r=-1;for(var e=ue(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},q.escape=function(n){return null==n?"":se(n).replace(L,s)},q.escapeRegExp=Xr,q.every=Cr,q.find=Ar,q.findIndex=sr,q.findKey=function(n,t,r){return t=q.createCallback(t,r,3),Ut(n,t,zt,true) -},q.findLast=function(n,t,r){return t=q.createCallback(t,r,3),Ut(n,t,Wt)},q.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=q.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},q.findLastKey=function(n,t,r){return t=q.createCallback(t,r,3),Ut(n,t,qt,true)},q.findWhere=function(n,t){return Ar(n,ne(t))},q.has=function(n,t){return n?Ie.call(n,t):false},q.identity=Qr,q.indexOf=gr,q.isArguments=Br,q.isArray=ou,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&we.call(n)==nt||false -},q.isDate=function(n){return n&&typeof n=="object"&&we.call(n)==tt||false},q.isElement=Dr,q.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Ze(e+r,0):Ke(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},q.noConflict=function(){return c._=_e,this},q.noop=re,q.now=pu,q.pad=function(n,t,r){n=null==n?"":se(n),t=+t; -var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},q.template=function(n,t,r){var e=q.templateSettings;r=uu({},r,e,kt),n=se(null==n?"":n);var u,o,a=uu({},r.imports,e.imports,kt),e=iu(a),a=Jr(a),i=0,l=r.interpolate||M,f="__p+='",l=ce((r.escape||M).source+"|"+l.source+"|"+(l===U?$:M).source+"|"+(r.evaluate||M).source+"|$","g"); -return n.replace(l,function(t,r,e,a,l,c){return e||(e=a),f+=n.slice(i,c).replace(V,p),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(I,""):f).replace(R,"$1").replace(F,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}",r=Ht(f,e,a),t?r(t):r +for(r=r?q.createCallback(r,e,1):Qr,t=r(t);u>>1,r(n[e])r?0:r);++tr?Ze(e+r,0):r||0:0,typeof n=="string"||!au(n)&&Kr(n)?ro&&(o=i)}else t=null==t&&Kr(n)?u:q.createCallback(t,r,3),Lt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Rr(n,t){return Ir(n,ee(t))}function Ur(n,t,r,e){var u=3>arguments.length; +if(t=q.createCallback(t,e,4),au(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=q.createCallback(t,e,4),Tt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Nr(n){var t=-1,r=n&&n.length,e=ue(0>r?0:r>>>0);return Lt(n,function(n){var r=Xt(0,++t);e[t]=e[r],e[r]=n}),e}function Lr(n,t,r){var e;if((typeof t!="function"||typeof r!="undefined")&&(t=q.createCallback(t,r,3)),au(n)){r=-1; +for(var u=n.length;++rarguments.length)return er(n,b,null,t);if(n)var r=n[k]?n[k][2]:n.length,e=dr(arguments,2),r=r-e.length;return er(n,b|A,r,t,e)}function Wr(n,t,r){function e(){var r=t-(gu()-f);0>=r||r>t?(i&&ke(i),r=p,i=s=p=m,r&&(g=gu(),l=n.apply(c,a),s||i||(a=c=null))):s=Ne(e,r)}function u(){s&&ke(s),i=s=p=m,(v||h!==t)&&(g=gu(),l=n.apply(c,a),s||i||(a=c=null))}function o(){if(a=arguments,f=gu(),c=this,p=v&&(s||!y),false===h)var r=y&&!s; +else{i||y||(g=f);var o=h-(f-g),d=0>=o||o>h;d?(i&&(i=ke(i)),g=f,l=n.apply(c,a)):i||(i=Ne(u,o))}return d&&s?s=ke(s):s||t===h||(s=Ne(e,t)),r&&(d=true,l=n.apply(c,a)),!d||s||i||(a=c=null),l}var a,i,l,f,c,s,p,g=0,h=false,v=true;if(!zr(n))throw new pe(O);if(t=0>t?0:t,true===r)var y=true,v=false;else qr(r)&&(y=r.leading,h="maxWait"in r&&Ze(t,+r.maxWait||0),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&ke(s),i&&ke(i),i=s=p=m},o}function $r(n){if(!zr(n))throw new pe(O);return function(){return!n.apply(this,arguments) +}}function Pr(n){return Mt(n,Vr)}function Br(n){return n&&typeof n=="object"&&typeof n.length=="number"&&we.call(n)==H||false}function Dr(n){return n&&typeof n=="object"&&1===n.nodeType&&(He.nodeClass?-1>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,a=r-1,e=ue(r),i=0t||null==n||!ze(t))return r;n=se(n);do t%2&&(r+=n),t=Ee(t/2),n+=n;while(t);return r}function Gr(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n),v(n)+1):(t=se(t),n.slice(o(n,t),a(n,t)+1)):n}function Hr(n,t,r){var e=typeof n,u="function"==e;return u&&typeof t=="undefined"?n:u||null==n?Ut(n,t,r):"object"==e?ne(n):ee(n) +}function Qr(n){return n}function ne(n){var t=lu(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||qr(u)?function(e){var u=r;if(u&&!e)return false;for(;u--;){var o=t[u];if(!Se.call(e,o)||!Zt(n[o],e[o],null,true))return false}return true}:function(n){return n&&Se.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function te(n,t,r){var e=true,u=t&&Mt(t,lu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Mt(t,lu)),false===r?e=false:qr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=zr(n),a=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},q.assign=ou,q.at=function(t){return He.unindexedChars&&Kr(t)&&(t=t.split("")),n(t,$t(arguments,true,false,1))},q.bind=Tr,q.bindAll=function(n){for(var t=n,r=1arguments.length?er(t,b|_,null,n):er(t,b|_|A,null,n,dr(arguments,2)) +},q.chain=function(n){return new J(n,true)},q.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?e(p,l):a(s,l))){for(t=u;--t;){var g=o[t];if(0>(g?e(g,l):a(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},q.invert=function(n,t){for(var r=-1,e=lu(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=q.createCallback(t,r,3)),Lt(n,function(n,r,u){if(o)for(r=t.length,u=ue(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?l:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,r){return t.call(r,n),n},q.throttle=function(n,t,r){var e=true,u=true;if(!zr(n))throw new pe(O);return false===r?e=false:qr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),_t.leading=e,_t.maxWait=+t,_t.trailing=u,Wr(n,t,_t) +},q.times=function(n,t,r){n=0>n?0:n>>>0,t=Ut(t,r,1),r=-1;for(var e=ue(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},q.escape=function(n){return null==n?"":se(n).replace(N,s)},q.escapeRegExp=Xr,q.every=Cr,q.find=kr,q.findIndex=sr,q.findKey=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,zt,true) +},q.findLast=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,Tt)},q.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=q.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},q.findLastKey=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,qt,true)},q.findWhere=function(n,t){return kr(n,ne(t))},q.has=function(n,t){return n?Se.call(n,t):false},q.identity=Qr,q.indexOf=gr,q.isArguments=Br,q.isArray=au,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&we.call(n)==nt||false +},q.isDate=function(n){return n&&typeof n=="object"&&we.call(n)==tt||false},q.isElement=Dr,q.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Ze(e+r,0):Ke(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},q.noConflict=function(){return c._=_e,this},q.noop=re,q.now=gu,q.pad=function(n,t,r){n=null==n?"":se(n),t=+t; +var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},q.template=function(n,t,r){var e=q.templateSettings;r=ou({},r,e,xt),n=se(null==n?"":n);var u,o,a=ou({},r.imports,e.imports,xt),e=lu(a),a=Jr(a),i=0,l=r.interpolate||M,f="__p+='",l=ce((r.escape||M).source+"|"+l.source+"|"+(l===W?$:M).source+"|"+(r.evaluate||M).source+"|$","g"); +return n.replace(l,function(t,r,e,a,l,c){return e||(e=a),f+=n.slice(i,c).replace(V,p),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(S,""):f).replace(R,"$1").replace(U,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}",r=Ht(f,e,a),t?r(t):r },q.trim=Gr,q.trimLeft=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n)):(t=se(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(0,v(n)+1):(t=se(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var r=30,e="...";if(t&&qr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?se(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":se(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e; -if(Zr(u)){if(n.slice(o).search(u)){var a,i,l=n.slice(0,o);for(u.global||(u=ce(u.source,(P.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(l);)i=a.index;r=r.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(N,y))},q.uniqueId=function(n){var t=++E;return se(null==n?"":n)+t},q.all=Cr,q.any=Tr,q.detect=Ar,q.foldl=Fr,q.foldr=Nr,q.include=xr,q.inject=Fr,te(q,function(){var n={};return zt(q,function(t,r){q.prototype[r]||(n[r]=t) -}),n}(),false),q.first=pr,q.last=vr,q.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Jr(n):Ge.unindexedChars&&Kr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=pr,q.takeRight=vr,q.takeRightWhile=vr,q.takeWhile=pr,q.head=pr,zt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o}) -}),q.VERSION=k,q.prototype.chain=function(){return this.__chain__=true,this},q.prototype.toJSON=jr,q.prototype.toString=function(){return se(this.__wrapped__)},q.prototype.value=jr,q.prototype.valueOf=jr,jt(["join","pop","shift"],function(n){var t=ge[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),jt(["push","reverse","sort","unshift"],function(n){var t=ge[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),jt(["concat","splice"],function(n){var t=ge[n]; -q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Ge.spliceObjects||jt(["pop","shift","splice"],function(n){var t=ge[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,x=16,C=32,k="2.5.0-pre",A="__lodash@"+k+"__",O="Expected a function",E=0,S=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,N=/&(?:amp|lt|gt|quot|#39|#96);/g,L=/[&<>"'`]/g,T=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,U=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float64Array Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",gt="[object Int32Array]",ht="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; -mt[H]=mt[Q]=mt[ft]=mt[ct]=mt[st]=mt[pt]=mt[gt]=mt[ht]=mt[vt]=mt[yt]=mt[dt]=true,mt[lt]=mt[nt]=mt[tt]=mt[rt]=mt[et]=mt["[object Map]"]=mt[ut]=mt[ot]=mt[at]=mt["[object Set]"]=mt[it]=mt["[object WeakMap]"]=false;var bt={};bt[H]=bt[Q]=bt[lt]=bt[nt]=bt[tt]=bt[rt]=bt[ft]=bt[ct]=bt[st]=bt[pt]=bt[gt]=bt[ut]=bt[ot]=bt[at]=bt[it]=bt[ht]=bt[vt]=bt[yt]=bt[dt]=true,bt[et]=bt["[object Map]"]=bt["[object Set]"]=bt["[object WeakMap]"]=false;var _t={leading:false,maxWait:0,trailing:false},wt={configurable:false,enumerable:false,value:null,writable:false},jt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},xt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},kt={"function":true,object:true},At={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ot=kt[typeof window]&&window||this,Et=kt[typeof exports]&&exports&&!exports.nodeType&&exports,kt=kt[typeof module]&&module&&!module.nodeType&&module,St=Et&&kt&&typeof global=="object"&&global; -!St||St.global!==St&&St.window!==St&&St.self!==St||(Ot=St);var St=kt&&kt.exports===Et&&Et,It=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ot._=It, define(function(){return It})):Et&&kt?St?(kt.exports=It)._=It:Et._=It:Ot._=It}).call(this); \ No newline at end of file +if(Zr(u)){if(n.slice(o).search(u)){var a,i,l=n.slice(0,o);for(u.global||(u=ce(u.source,(P.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(l);)i=a.index;r=r.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(F,y))},q.uniqueId=function(n){var t=++E;return se(null==n?"":n)+t},q.all=Cr,q.any=Lr,q.detect=kr,q.foldl=Ur,q.foldr=Fr,q.include=Ar,q.inject=Ur,te(q,function(){var n={};return zt(q,function(t,r){q.prototype[r]||(n[r]=t) +}),n}(),false),q.first=pr,q.last=vr,q.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Jr(n):He.unindexedChars&&Kr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=pr,q.takeRight=vr,q.takeRightWhile=vr,q.takeWhile=pr,q.head=pr,zt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o}) +}),q.VERSION=x,q.prototype.chain=function(){return this.__chain__=true,this},q.prototype.toJSON=jr,q.prototype.toString=function(){return se(this.__wrapped__)},q.prototype.value=jr,q.prototype.valueOf=jr,jt(["join","pop","shift"],function(n){var t=ge[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),jt(["push","reverse","sort","unshift"],function(n){var t=ge[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),jt(["concat","splice"],function(n){var t=ge[n]; +q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),He.spliceObjects||jt(["pop","shift","splice"],function(n){var t=ge[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,A=16,C=32,x="2.5.0-pre",k="__lodash@"+x+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,S=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,L=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",gt="[object Int32Array]",ht="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; +mt[H]=mt[Q]=mt[ft]=mt[ct]=mt[st]=mt[pt]=mt[gt]=mt[ht]=mt[vt]=mt[yt]=mt[dt]=true,mt[lt]=mt[nt]=mt[tt]=mt[rt]=mt[et]=mt["[object Map]"]=mt[ut]=mt[ot]=mt[at]=mt["[object Set]"]=mt[it]=mt["[object WeakMap]"]=false;var bt={};bt[H]=bt[Q]=bt[lt]=bt[nt]=bt[tt]=bt[rt]=bt[ft]=bt[ct]=bt[st]=bt[pt]=bt[gt]=bt[ut]=bt[ot]=bt[at]=bt[it]=bt[ht]=bt[vt]=bt[yt]=bt[dt]=true,bt[et]=bt["[object Map]"]=bt["[object Set]"]=bt["[object WeakMap]"]=false;var _t={leading:false,maxWait:0,trailing:false},wt={configurable:false,enumerable:false,value:null,writable:false},jt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},At={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},xt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ot=xt[typeof window]&&window||this,Et=xt[typeof exports]&&exports&&!exports.nodeType&&exports,xt=xt[typeof module]&&module&&!module.nodeType&&module,It=Et&&xt&&typeof global=="object"&&global; +!It||It.global!==It&&It.window!==It&&It.self!==It||(Ot=It);var It=xt&&xt.exports===Et&&Et,St=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ot._=St, define(function(){return St})):Et&&xt?It?(xt.exports=St)._=St:Et._=St:Ot._=St}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 034294890d..ab8f859f1d 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -104,10 +104,11 @@ /** Used to assign default `context` object properties */ var contextProps = [ - 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Float64Array', 'Function', - 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', - 'document', 'isFinite', 'isNaN','parseInt', 'setTimeout', 'TypeError', - 'Uint8Array', 'window', 'WinRTError' + 'Array', 'ArrayBuffer', 'Boolean', 'Date', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', + 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', + 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', + 'Uint16Array', 'Uint32Array', 'window', 'WinRTError' ]; /** Used to make template sourceURLs easier to identify */ @@ -633,7 +634,7 @@ /** Native method shortcuts */ var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, - bufferSlice = isNative(bufferSlice = ArrayBuffer && (new ArrayBuffer).slice) && bufferSlice, + bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, ceil = Math.ceil, clearTimeout = context.clearTimeout, Float64Array = isNative(Float64Array = context.Float64Array) && Float64Array, @@ -1082,7 +1083,7 @@ case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - return value.subarray(0); + return new Ctor(cloneBuffer(value.buffer)); case numberClass: case stringClass: @@ -1108,13 +1109,16 @@ return stackB[length]; } } - result = isArr ? Ctor(value.length) : Ctor(); + result = isArr ? Ctor(value.length) : new Ctor; } else { result = isArr ? slice(value) : baseAssign({}, value); } + if (className == argsClass) { + result.length = value.length; + } // add array properties assigned by `RegExp#exec` - if (isArr) { + else if (isArr) { if (hasOwnProperty.call(value, 'index')) { result.index = value.index; } @@ -1182,8 +1186,7 @@ if (typeof func != 'function') { return identity; } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { + if (typeof thisArg == 'undefined') { return func; } var data = func[expando]; @@ -1199,7 +1202,7 @@ } if (!data) { // checks if `func` references the `this` keyword and stores the result - data = reThis.test(source); + data = reThis.test(source) || isNative(func); setData(func, data); } } @@ -1598,8 +1601,8 @@ return false; } var valClass = toString.call(value), - othClass = toString.call(other), valIsArg = valClass == argsClass, + othClass = toString.call(other), othIsArg = othClass == argsClass; if (valIsArg) { @@ -1618,6 +1621,10 @@ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +value == +other; + case errorClass: + // check properties instead of coercing to strings to support IE < 8 + return value.name === other.name && value.message === other.message; + case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) @@ -1625,12 +1632,10 @@ // but treat `-0` vs. `+0` as not equal : (value == 0 ? (1 / value == 1 / other) : value == +other); - case errorClass: case regexpClass: case stringClass: - // coerce errors (http://es5.github.io/#x15.11.4.4) - // and regexes (http://es5.github.io/#x15.10.6.4) to strings - // treat string primitives and their corresponding object instances as equal + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) + // treat string primitives and object instances as equal return value == String(other); } var isArr = arrayLikeClasses[valClass]; @@ -1678,7 +1683,7 @@ return stackB[length] == other; } } - result = true; + var index = -1; // add `value` and `other` to the stack of traversed objects stackA.push(value); @@ -1686,32 +1691,28 @@ // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { - // compare lengths to determine if a deep comparison is necessary var othLength = other.length; length = value.length; - result = othLength == length; - - if (result || isWhere) { - var othIndex = -1; + result = length == othLength; + if (result || (isWhere && othLength > length)) { // deep compare the contents, ignoring non-numeric properties - while (++othIndex < othLength) { - var othValue = other[othIndex]; - + while (++index < length) { + var valValue = value[index]; if (isWhere) { - var index = -1; - while (++index < length) { - result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB); + var othIndex = othLength; + while (othIndex--) { + result = baseIsEqual(valValue, other[othIndex], callback, isWhere, stackA, stackB); if (result) { break; } } } else { - var valValue = value[othIndex]; - result = callback ? callback(valValue, othValue, othIndex) : undefined; - result = typeof result == 'undefined' - ? baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB) - : !!result; + var othValue = other[index]; + result = callback ? callback(valValue, othValue, index) : undefined; + if (typeof result == 'undefined') { + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + } } if (!result) { break; @@ -1720,42 +1721,40 @@ } } else { - var size = 0; - - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - baseForIn(other, function(othValue, key, other) { - if (hasOwnProperty.call(other, key)) { - result = false; - // count the number of properties - size++; - // deep compare each property value - if (hasOwnProperty.call(value, key)) { - var valValue = value[key]; + var valProps = keys(value), + othProps = keys(other); + + if (valIsArg) { + valProps.push('length'); + } + if (othIsArg) { + othProps.push('length'); + } + length = valProps.length; + result = length == othProps.length; + + if (result || isWhere) { + while (++index < length) { + var key = valProps[index]; + result = hasOwnProperty.call(other, key); + if (result) { + valValue = value[key]; + othValue = other[key]; result = callback ? callback(valValue, othValue, key) : undefined; - result = typeof result == 'undefined' - ? baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB) - : !!result; + if (typeof result == 'undefined') { + result = baseIsEqual(valValue, othValue, callback, isWhere, stackA, stackB); + } } - return result; - } - }); - - if (result && !isWhere) { - // ensure both objects have the same number of properties - baseForIn(value, function(valValue, key, value) { - if (hasOwnProperty.call(value, key)) { - // `size` will be `-1` if `value` has more properties than `other` - result = --size > -1; - return result; + if (!result) { + break; } - }); + } } } stackA.pop(); stackB.pop(); - return result; + return !!result; } /** @@ -4890,8 +4889,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it is - * used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If property name(s) or an object is provided it + * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example @@ -7894,7 +7893,7 @@ var type = typeof func, isFunc = type == 'function'; - if (isFunc && (typeof thisArg == 'undefined' || !('prototype' in func))) { + if (isFunc && typeof thisArg == 'undefined') { return func; } if (isFunc || func == null) { @@ -7973,7 +7972,7 @@ while (length--) { var key = props[length]; if (!(hasOwnProperty.call(object, key) && - baseIsEqual(object[key], source[key], null, true))) { + baseIsEqual(source[key], object[key], null, true))) { return false; } } @@ -8658,9 +8657,9 @@ // some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose Lo-Dash to the global object even when an AMD loader is present in - // case Lo-Dash is loaded with a RequireJS shim config. - // See http://requirejs.org/docs/api.html#config-shim + // Expose Lo-Dash to the global object when an AMD loader is present to avoid + // errors in cases where Lo-Dash is loaded by a script tag and not intended + // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch root._ = _; // define as an anonymous module so, through path mapping, it can be diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 3b44b85bbc..973b119b32 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -4,65 +4,65 @@ * Build: `lodash modern -o ./dist/lodash.js` */ ;(function(){function n(n,t){for(var e=-1,r=t.length,u=Array(r);++et||typeof n=="undefined")return 1;if(nr||13r||8202e||13e||8202>>0:0,u=tr(r);++ea(t,f)&&l.push(f);return l}function Ft(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number"&&-1o?0:o>>>0);return Ft(n,function(n){var o=u?t:null!=n&&n[t];a[++r]=o?o.apply(n,e):m}),a}function Zt(n,t,e,r,u){var o=re(t);return(o?bt:Bt)(t,function(t,a,i){var f=t&&re(t),l=t&&nu(t),c=n[a]; -if(f||l){for(r||(r=[]),u||(u=[]),l=r.length;l--;)if(r[l]==t)return void(n[a]=u[l]);i=e?e(c,t,a,n,i):m,(l=typeof i!="undefined")||(i=f?Qr(c)?c:[]:nu(c)?c:{}),r.push(t),u.push(i),l||Zt(i,t,e,r,u),n[a]=i}else i=e?e(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i)}),n}function Pt(n,t){var e={};if(typeof t=="function")return Lt(n,function(n,r,u){t(n,r,u)&&(e[r]=n)}),e;for(var r=-1,u=t.length;++rr||13r||8202e||13e||8202>>0:0,u=tr(r);++ea(t,f)&&l.push(f);return l}function St(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number"&&-1f)for(;++lo?0:o>>>0);return St(n,function(n){var o=u?t:null!=n&&n[t];a[++r]=o?o.apply(n,e):m}),a}function Zt(n,t,e,r,u){var o=re(t);return(o?dt:Bt)(t,function(t,a,i){var f=t&&re(t),l=t&&nu(t),c=n[a]; +if(f||l){for(r||(r=[]),u||(u=[]),l=r.length;l--;)if(r[l]==t)return void(n[a]=u[l]);i=e?e(c,t,a,n,i):m,(l=typeof i!="undefined")||(i=f?Qr(c)?c:[]:nu(c)?c:{}),r.push(t),u.push(i),l||Zt(i,t,e,r,u),n[a]=i}else i=e?e(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i)}),n}function Pt(n,t){var e={};if(typeof t=="function")return Lt(n,function(n,r,u){t(n,r,u)&&(e[r]=n)}),e;for(var r=-1,u=t.length;++ri(p,h)&&((u||l)&&p.push(h),c.push(s))}return c}function Jt(n,t){for(var e=-1,r=t(n),u=r.length,o=tr(u);++er)return t;var u=typeof e[2];if("number"!=u&&"string"!=u||!e[3]||e[3][e[2]]!==e[1]||(r=2),3r)return t;var u=typeof e[2];if("number"!=u&&"string"!=u||!e[3]||e[3][e[2]]!==e[1]||(r=2),3o?0:o)}function ce(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?Dr(u+r,0):r||0;else if(r)return r=ve(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function pe(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0; for(t=q.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else o=null==t||e?1:t;return o=r-(o||0),ge(n,0,0>o?0:o)}function se(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=q.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||e)return n?n[r-1]:m;return o=r-(o||0),ge(n,0>o?0:o)}function he(n,t,e){if(typeof t!="number"&&null!=t){var r=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,e,3);++rt?0:t;return ge(n,o)}function ge(n,t,e){var r=-1,u=n?n.length:0; -for(t=null==t?0:+t||0,0>t?t=Dr(u+t,0):t>u&&(t=u),e=typeof e=="undefined"?u:+e||0,0>e?e=Dr(u+e,0):e>u&&(e=u),u=t>e?0:e-t,e=tr(u);++r>>1,e(n[r])e?0:e);++te?Dr(r+e,0):e||0:0,typeof n=="string"||!Qr(n)&&Me(n)?eo&&(o=i)}else t=null==t&&Me(n)?u:q.createCallback(t,e,3),Ft(n,function(n,e,u){e=t(n,e,u),(e>r||-1/0===e&&e===o)&&(r=e,o=n)});return o}function Ee(n,t){return Ce(n,nr(t))}function Ie(n,t,e,r){var u=3>arguments.length;t=q.createCallback(t,r,4);var o=-1,a=n?n.length:0;if(typeof a=="number"&&-1arguments.length;return t=q.createCallback(t,r,4),Nt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Se(n){var t=-1,e=n&&n.length,r=tr(0>e?0:e>>>0);return Ft(n,function(n){var e=Kt(0,++t);r[t]=r[e],r[e]=n}),r}function Fe(n,t,e){var r;(typeof t!="function"||typeof e!="undefined")&&(t=q.createCallback(t,e,3)),e=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return ne(n,d,null,t);if(n)var e=n[A]?n[A][2]:n.length,r=ge(arguments,2),e=e-r.length;return ne(n,d|j,e,t,r)}function Te(n,t,e){function r(){var e=t-(au()-l);0>=e||e>t?(i&&wr(i),e=s,i=p=s=m,e&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))):p=Ir(r,e)}function u(){p&&wr(p),i=p=s=m,(v||g!==t)&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))}function o(){if(a=arguments,l=au(),c=this,s=v&&(p||!y),false===g)var e=y&&!p; -else{i||y||(h=l);var o=g-(l-h),m=0>=o||o>g;m?(i&&(i=wr(i)),h=l,f=n.apply(c,a)):i||(i=Ir(u,o))}return m&&p?p=wr(p):p||t===g||(p=Ir(r,t)),e&&(m=true,f=n.apply(c,a)),!m||p||i||(a=c=null),f}var a,i,f,l,c,p,s,h=0,g=false,v=true;if(!Be(n))throw new fr(C);if(t=0>t?0:t,true===e)var y=true,v=false;else De(e)&&(y=e.leading,g="maxWait"in e&&Dr(t,+e.maxWait||0),v="trailing"in e?e.trailing:v);return o.cancel=function(){p&&wr(p),i&&wr(i),i=p=s=m},o}function We(n){if(!Be(n))throw new fr(C);return function(){return!n.apply(this,arguments) -}}function Ue(n){return zt(n,Ze)}function $e(n){return n&&typeof n=="object"&&typeof n.length=="number"&&yr.call(n)==Y||false}function Le(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,a=tr(e),i=0t||null==n||!$r(t))return e;n=ir(n);do t%2&&(e+=n),t=kr(t/2),n+=n;while(t);return e}function Je(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n),g(n)+1):(t=ir(t),n.slice(o(n,t),a(n,t)+1)):n -}function Xe(n,t,e){var r=typeof n,u="function"==r;return!u||typeof t!="undefined"&&"prototype"in n?u||null==n?It(n,t,e):"object"==r?Ge(n):nr(n):n}function Ye(n){return n}function Ge(n){var t=tu(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||De(u)?function(r){var u=e;if(u&&!r)return false;for(;u--;){var o=t[u];if(!Ar.call(r,o)||!qt(r[o],n[o],null,true))return false}return true}:function(n){return n&&Ar.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function He(n,t,e){var r=true,u=t&&zt(t,tu);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=zt(t,tu)),false===e?r=false:De(e)&&"chain"in e&&(r=e.chain),e=-1; -for(var o=Be(n),a=u?u.length:0;++e--n?t.apply(this,arguments):void 0}},q.assign=Hr,q.at=function(t){return n(t,Wt(arguments,true,false,1))},q.bind=Ne,q.bindAll=function(n){for(var t=n,e=1arguments.length?ne(t,d|b,null,n):ne(t,d|b|j,null,n,ge(arguments,2))},q.chain=function(n){return new V(n,true) -},q.compact=function(n){for(var t=-1,e=n?n.length:0,r=0,u=[];++t(s?r(s,f):a(p,f))){for(t=u;--t;){var h=o[t];if(0>(h?r(h,f):a(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},q.invert=function(n,t){for(var e=-1,r=tu(n),u=r.length,o={};++eu?0:u>>>0);for(o||(t=q.createCallback(t,e,3)),Ft(n,function(n,e,u){if(o)for(e=t.length,u=tr(e);e--;)u[e]=n[t[e]];else u=t(n,e,u);a[++r]={a:u,b:r,c:n}}),u=a.length,a.sort(o?f:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,e){return t.call(e,n),n},q.throttle=function(n,t,e){var r=true,u=true;if(!Be(n))throw new fr(C);return false===e?r=false:De(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),mt.leading=r,mt.maxWait=+t,mt.trailing=u,Te(n,t,mt) -},q.times=function(n,t,e){n=0>n?0:n>>>0,t=It(t,e,1),e=-1;for(var r=tr(n);++ee?0:+e||0,r))-t.length,0<=e&&n.indexOf(t,e)==e},q.escape=function(n){return null==n?"":ir(n).replace(N,p)},q.escapeRegExp=Ke,q.every=we,q.find=ke,q.findIndex=fe,q.findKey=function(n,t,e){return t=q.createCallback(t,e,3),Tt(n,t,Bt,true) -},q.findLast=function(n,t,e){return t=q.createCallback(t,e,3),Tt(n,t,Nt)},q.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=q.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},q.findLastKey=function(n,t,e){return t=q.createCallback(t,e,3),Tt(n,t,Dt,true)},q.findWhere=function(n,t){return ke(n,Ge(t))},q.has=function(n,t){return n?Ar.call(n,t):false},q.identity=Ye,q.indexOf=ce,q.isArguments=$e,q.isArray=Qr,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&yr.call(n)==H||false -},q.isDate=function(n){return n&&typeof n=="object"&&yr.call(n)==Q||false},q.isElement=Le,q.isEmpty=function(n){var t=true;if(!n)return t;var e=n.length;return-1t?t=Dr(u+t,0):t>u&&(t=u),e=typeof e=="undefined"?u:+e||0,0>e?e=Dr(u+e,0):e>u&&(e=u),u=t>e?0:e-t,e=tr(u);++r>>1,e(n[r])e?0:e);++te?Dr(r+e,0):e||0:0,typeof n=="string"||!Qr(n)&&Me(n)?eo&&(o=i)}else t=null==t&&Me(n)?u:q.createCallback(t,e,3),St(n,function(n,e,u){e=t(n,e,u),(e>r||-1/0===e&&e===o)&&(r=e,o=n)});return o}function Ie(n,t){return Ce(n,nr(t))}function Ee(n,t,e,r){var u=3>arguments.length;t=q.createCallback(t,r,4);var o=-1,a=n?n.length:0;if(typeof a=="number"&&-1arguments.length;return t=q.createCallback(t,r,4),Ut(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Fe(n){var t=-1,e=n&&n.length,r=tr(0>e?0:e>>>0);return St(n,function(n){var e=Kt(0,++t);r[t]=r[e],r[e]=n}),r}function Se(n,t,e){var r;(typeof t!="function"||typeof e!="undefined")&&(t=q.createCallback(t,e,3)),e=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return ne(n,b,null,t);if(n)var e=n[x]?n[x][2]:n.length,r=ge(arguments,2),e=e-r.length;return ne(n,b|j,e,t,r)}function Ne(n,t,e){function r(){var e=t-(au()-l);0>=e||e>t?(i&&wr(i),e=s,i=p=s=m,e&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))):p=Er(r,e)}function u(){p&&wr(p),i=p=s=m,(v||g!==t)&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))}function o(){if(a=arguments,l=au(),c=this,s=v&&(p||!y),false===g)var e=y&&!p; +else{i||y||(h=l);var o=g-(l-h),m=0>=o||o>g;m?(i&&(i=wr(i)),h=l,f=n.apply(c,a)):i||(i=Er(u,o))}return m&&p?p=wr(p):p||t===g||(p=Er(r,t)),e&&(m=true,f=n.apply(c,a)),!m||p||i||(a=c=null),f}var a,i,f,l,c,p,s,h=0,g=false,v=true;if(!Be(n))throw new fr(C);if(t=0>t?0:t,true===e)var y=true,v=false;else De(e)&&(y=e.leading,g="maxWait"in e&&Dr(t,+e.maxWait||0),v="trailing"in e?e.trailing:v);return o.cancel=function(){p&&wr(p),i&&wr(i),i=p=s=m},o}function Te(n){if(!Be(n))throw new fr(C);return function(){return!n.apply(this,arguments) +}}function We(n){return zt(n,Ze)}function $e(n){return n&&typeof n=="object"&&typeof n.length=="number"&&yr.call(n)==Y||false}function Le(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,a=tr(e),i=0t||null==n||!$r(t))return e;n=ir(n);do t%2&&(e+=n),t=Ar(t/2),n+=n;while(t);return e}function Je(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n),g(n)+1):(t=ir(t),n.slice(o(n,t),a(n,t)+1)):n +}function Xe(n,t,e){var r=typeof n,u="function"==r;return u&&typeof t=="undefined"?n:u||null==n?Et(n,t,e):"object"==r?Ge(n):nr(n)}function Ye(n){return n}function Ge(n){var t=tu(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||De(u)?function(r){var u=e;if(u&&!r)return false;for(;u--;){var o=t[u];if(!xr.call(r,o)||!qt(n[o],r[o],null,true))return false}return true}:function(n){return n&&xr.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function He(n,t,e){var r=true,u=t&&zt(t,tu);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=zt(t,tu)),false===e?r=false:De(e)&&"chain"in e&&(r=e.chain),e=-1; +for(var o=Be(n),a=u?u.length:0;++e--n?t.apply(this,arguments):void 0}},q.assign=Hr,q.at=function(t){return n(t,Tt(arguments,true,false,1))},q.bind=Ue,q.bindAll=function(n){for(var t=n,e=1arguments.length?ne(t,b|d,null,n):ne(t,b|d|j,null,n,ge(arguments,2))},q.chain=function(n){return new V(n,true) +},q.compact=function(n){for(var t=-1,e=n?n.length:0,r=0,u=[];++t(s?r(s,f):a(p,f))){for(t=u;--t;){var h=o[t];if(0>(h?r(h,f):a(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},q.invert=function(n,t){for(var e=-1,r=tu(n),u=r.length,o={};++eu?0:u>>>0);for(o||(t=q.createCallback(t,e,3)),St(n,function(n,e,u){if(o)for(e=t.length,u=tr(e);e--;)u[e]=n[t[e]];else u=t(n,e,u);a[++r]={a:u,b:r,c:n}}),u=a.length,a.sort(o?f:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,e){return t.call(e,n),n},q.throttle=function(n,t,e){var r=true,u=true;if(!Be(n))throw new fr(C);return false===e?r=false:De(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),mt.leading=r,mt.maxWait=+t,mt.trailing=u,Ne(n,t,mt) +},q.times=function(n,t,e){n=0>n?0:n>>>0,t=Et(t,e,1),e=-1;for(var r=tr(n);++ee?0:+e||0,r))-t.length,0<=e&&n.indexOf(t,e)==e},q.escape=function(n){return null==n?"":ir(n).replace(U,p)},q.escapeRegExp=Ke,q.every=we,q.find=Ae,q.findIndex=fe,q.findKey=function(n,t,e){return t=q.createCallback(t,e,3),Nt(n,t,Bt,true) +},q.findLast=function(n,t,e){return t=q.createCallback(t,e,3),Nt(n,t,Ut)},q.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=q.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},q.findLastKey=function(n,t,e){return t=q.createCallback(t,e,3),Nt(n,t,Dt,true)},q.findWhere=function(n,t){return Ae(n,Ge(t))},q.has=function(n,t){return n?xr.call(n,t):false},q.identity=Ye,q.indexOf=ce,q.isArguments=$e,q.isArray=Qr,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&yr.call(n)==H||false +},q.isDate=function(n){return n&&typeof n=="object"&&yr.call(n)==Q||false},q.isElement=Le,q.isEmpty=function(n){var t=true;if(!n)return t;var e=n.length;return-1e?Dr(r+e,0):zr(e||0,r-1))+1);r--;)if(n[r]===t)return r;return-1},q.noConflict=function(){return c._=vr,this},q.noop=Qe,q.now=au,q.pad=function(n,t,e){n=null==n?"":ir(n),t=+t; -var r=n.length;return re?0:+e||0,n.length),n.lastIndexOf(t,e)==e},q.template=function(n,t,e){var r=q.templateSettings;e=Hr({},e,r,jt),n=ir(null==n?"":n);var u,o,a=Hr({},e.imports,r.imports,jt),r=tu(a),a=Pe(a),i=0,f=e.interpolate||M,l="__p+='",f=ar((e.escape||M).source+"|"+f.source+"|"+(f===U?$:M).source+"|"+(e.evaluate||M).source+"|$","g"); -return n.replace(f,function(t,e,r,a,f,c){return r||(r=a),l+=n.slice(i,c).replace(K,s),e&&(u=true,l+="'+__e("+e+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t}),l+="';",(e=e.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(I,""):l).replace(R,"$1").replace(S,"$1;"),l="function("+(e||"obj")+"){"+(e?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",e=Xt(l,r,a,void 0),t?e(t):e +var r=n.length;return re?0:+e||0,n.length),n.lastIndexOf(t,e)==e},q.template=function(n,t,e){var r=q.templateSettings;e=Hr({},e,r,jt),n=ir(null==n?"":n);var u,o,a=Hr({},e.imports,r.imports,jt),r=tu(a),a=Pe(a),i=0,f=e.interpolate||M,l="__p+='",f=ar((e.escape||M).source+"|"+f.source+"|"+(f===W?$:M).source+"|"+(e.evaluate||M).source+"|$","g"); +return n.replace(f,function(t,e,r,a,f,c){return r||(r=a),l+=n.slice(i,c).replace(K,s),e&&(u=true,l+="'+__e("+e+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t}),l+="';",(e=e.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(E,""):l).replace(R,"$1").replace(F,"$1;"),l="function("+(e||"obj")+"){"+(e?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",e=Xt(l,r,a,void 0),t?e(t):e },q.trim=Je,q.trimLeft=function(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n)):(t=ir(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(0,g(n)+1):(t=ir(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var e=30,r="...";if(t&&De(t))var u="separator"in t?t.separator:u,e="length"in t?+t.length||0:e,r="omission"in t?ir(t.omission):r;else null!=t&&(e=+t||0);if(n=null==n?"":ir(n),e>=n.length)return n;var o=e-r.length;if(1>o)return r;if(e=n.slice(0,o),null==u)return e+r; -if(qe(u)){if(n.slice(o).search(u)){var a,i,f=n.slice(0,o);for(u.global||(u=ar(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(f);)i=a.index;e=e.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=e.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(F,v))},q.uniqueId=function(n){var t=++O;return ir(null==n?"":n)+t},q.all=we,q.any=Fe,q.detect=ke,q.foldl=Ie,q.foldr=Re,q.include=_e,q.inject=Ie,He(q,function(){var n={};return Bt(q,function(t,e){q.prototype[e]||(n[e]=t) -}),n}(),false),q.first=le,q.last=se,q.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Pe(n)),null==t||e?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=le,q.takeRight=se,q.takeRightWhile=se,q.takeWhile=le,q.head=le,Bt(q,function(n,t){var e="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new V(o,u):o})}),q.VERSION=x,q.prototype.chain=function(){return this.__chain__=true,this -},q.prototype.toJSON=be,q.prototype.toString=function(){return ir(this.__wrapped__)},q.prototype.value=be,q.prototype.valueOf=be,bt(["join","pop","shift"],function(n){var t=lr[n];q.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new V(e,n):e}}),bt(["push","reverse","sort","unshift"],function(n){var t=lr[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),bt(["concat","splice"],function(n){var t=lr[n];q.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__) -}}),q}var m,d=1,b=2,_=4,w=8,j=16,k=32,x="2.5.0-pre",A="__lodash@"+x+"__",C="Expected a function",O=0,E=/^[A-Z]+$/,I=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,S=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,T=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,U=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float64Array Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",et="[object Object]",rt="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; -vt[Y]=vt[G]=vt[at]=vt[it]=vt[ft]=vt[lt]=vt[ct]=vt[pt]=vt[st]=vt[ht]=vt[gt]=true,vt[ot]=vt[H]=vt[Q]=vt[nt]=vt["[object Function]"]=vt["[object Map]"]=vt[tt]=vt[et]=vt[rt]=vt["[object Set]"]=vt[ut]=vt["[object WeakMap]"]=false;var yt={};yt[Y]=yt[G]=yt[ot]=yt[H]=yt[Q]=yt[nt]=yt[at]=yt[it]=yt[ft]=yt[lt]=yt[ct]=yt[tt]=yt[et]=yt[rt]=yt[ut]=yt[pt]=yt[st]=yt[ht]=yt[gt]=true,yt["[object Function]"]=yt["[object Map]"]=yt["[object Set]"]=yt["[object WeakMap]"]=false;var mt={leading:false,maxWait:0,trailing:false},dt={configurable:false,enumerable:false,value:null,writable:false},bt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},_t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},wt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},jt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},xt=jt[typeof window]&&window||this,At=jt[typeof exports]&&exports&&!exports.nodeType&&exports,jt=jt[typeof module]&&module&&!module.nodeType&&module,Ct=At&&jt&&typeof global=="object"&&global; -!Ct||Ct.global!==Ct&&Ct.window!==Ct&&Ct.self!==Ct||(xt=Ct);var Ct=jt&&jt.exports===At&&At,Ot=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(xt._=Ot, define(function(){return Ot})):At&&jt?Ct?(jt.exports=Ot)._=Ot:At._=Ot:xt._=Ot}).call(this); \ No newline at end of file +if(qe(u)){if(n.slice(o).search(u)){var a,i,f=n.slice(0,o);for(u.global||(u=ar(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(f);)i=a.index;e=e.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=e.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(S,v))},q.uniqueId=function(n){var t=++O;return ir(null==n?"":n)+t},q.all=we,q.any=Se,q.detect=Ae,q.foldl=Ee,q.foldr=Re,q.include=_e,q.inject=Ee,He(q,function(){var n={};return Bt(q,function(t,e){q.prototype[e]||(n[e]=t) +}),n}(),false),q.first=le,q.last=se,q.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Pe(n)),null==t||e?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=le,q.takeRight=se,q.takeRightWhile=se,q.takeWhile=le,q.head=le,Bt(q,function(n,t){var e="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new V(o,u):o})}),q.VERSION=k,q.prototype.chain=function(){return this.__chain__=true,this +},q.prototype.toJSON=de,q.prototype.toString=function(){return ir(this.__wrapped__)},q.prototype.value=de,q.prototype.valueOf=de,dt(["join","pop","shift"],function(n){var t=lr[n];q.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new V(e,n):e}}),dt(["push","reverse","sort","unshift"],function(n){var t=lr[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),dt(["concat","splice"],function(n){var t=lr[n];q.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__) +}}),q}var m,b=1,d=2,_=4,w=8,j=16,A=32,k="2.5.0-pre",x="__lodash@"+k+"__",C="Expected a function",O=0,I=/^[A-Z]+$/,E=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39|#96);/g,U=/[&<>"'`]/g,N=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",et="[object Object]",rt="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; +vt[Y]=vt[G]=vt[at]=vt[it]=vt[ft]=vt[lt]=vt[ct]=vt[pt]=vt[st]=vt[ht]=vt[gt]=true,vt[ot]=vt[H]=vt[Q]=vt[nt]=vt["[object Function]"]=vt["[object Map]"]=vt[tt]=vt[et]=vt[rt]=vt["[object Set]"]=vt[ut]=vt["[object WeakMap]"]=false;var yt={};yt[Y]=yt[G]=yt[ot]=yt[H]=yt[Q]=yt[nt]=yt[at]=yt[it]=yt[ft]=yt[lt]=yt[ct]=yt[tt]=yt[et]=yt[rt]=yt[ut]=yt[pt]=yt[st]=yt[ht]=yt[gt]=true,yt["[object Function]"]=yt["[object Map]"]=yt["[object Set]"]=yt["[object WeakMap]"]=false;var mt={leading:false,maxWait:0,trailing:false},bt={configurable:false,enumerable:false,value:null,writable:false},dt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},_t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},wt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},jt={"function":true,object:true},At={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},kt=jt[typeof window]&&window||this,xt=jt[typeof exports]&&exports&&!exports.nodeType&&exports,jt=jt[typeof module]&&module&&!module.nodeType&&module,Ct=xt&&jt&&typeof global=="object"&&global; +!Ct||Ct.global!==Ct&&Ct.window!==Ct&&Ct.self!==Ct||(kt=Ct);var Ct=jt&&jt.exports===xt&&xt,Ot=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(kt._=Ot, define(function(){return Ot})):xt&&jt?Ct?(jt.exports=Ot)._=Ot:xt._=Ot:kt._=Ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index b52fd841e8..52f5c980d6 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -570,8 +570,7 @@ if (typeof func != 'function') { return identity; } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { + if (typeof thisArg == 'undefined') { return func; } switch (argCount) { @@ -973,19 +972,16 @@ return stackB[length] == other; } } - var result = true, - size = 0; - stackA.push(value); stackB.push(other); if (isArr) { - size = other.length; - result = size == value.length; + length = value.length; + var result = length == other.length; if (result) { - while (size--) { - result = baseIsEqual(value[size], other[size], stackA, stackB); + while (length--) { + result = baseIsEqual(value[length], other[length], stackA, stackB); if (!result) { break; } @@ -993,25 +989,23 @@ } } else { - baseForIn(other, function(othValue, key, other) { - if (hasOwnProperty.call(other, key)) { - size++; - result = hasOwnProperty.call(value, key) && baseIsEqual(value[key], othValue, stackA, stackB); - return result || breakIndicator; - } - }); + var props = keys(value); + length = props.length; + result = length == keys(other).length; if (result) { - baseForIn(value, function(valValue, key, value) { - if (hasOwnProperty.call(value, key)) { - result = --size > -1; - return result || breakIndicator; + while (length--) { + var key = props[length]; + result = hasOwnProperty.call(other, key) && baseIsEqual(value[key], other[key], stackA, stackB); + if (!result) { + break; } - }); + } } } stackA.pop(); stackB.pop(); + return result; } @@ -3195,8 +3189,8 @@ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function - * called per iteration. If a property name or object is provided it is - * used to create a "_.pluck" or "_.where" style callback respectively. + * called per iteration. If property name(s) or an object is provided it + * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns the new sorted array. * @example @@ -5000,7 +4994,7 @@ var type = typeof func, isFunc = type == 'function'; - if (isFunc && (typeof thisArg == 'undefined' || !('prototype' in func))) { + if (isFunc && typeof thisArg == 'undefined') { return func; } if (isFunc || func == null) { @@ -5568,9 +5562,9 @@ // some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose Lo-Dash to the global object even when an AMD loader is present in - // case Lo-Dash is loaded with a RequireJS shim config. - // See http://requirejs.org/docs/api.html#config-shim + // Expose Lo-Dash to the global object when an AMD loader is present to avoid + // errors in cases where Lo-Dash is loaded by a script tag and not intended + // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch root._ = lodash; // define as an anonymous module so, through path mapping, it can be diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index a1d307caef..e6aaa1f88d 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -4,27 +4,26 @@ * Build: `lodash underscore -o ./dist/lodash.underscore.js` */ ;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(t>>0:0,u=Array(e);++t>>0:0,u=Array(e);++tu(r,i)&&o.push(i)}return o}function g(n,r){var t=-1,e=n?n.length:0;if(typeof e=="number"&&-1o?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):sr}),i}function j(n,r){var t={};if(typeof r=="function")return b(n,function(n,e,u){r(n,e,u)&&(t[e]=n)}),t;for(var e=-1,u=r.length;++eo(f,c)&&(t&&f.push(c),i.push(a))}return i}function x(n,r){var t,e=["_"];try{var u=Function(e,"return "+n+(t?"\n/*\n//# sourceURL="+t+"\n*/":"")).apply(sr,r);u.source=n}catch(o){throw o.source=n,o}return u}function T(n,r){return function(t,e,u){var o=r?r():{};e=fr(e,u,3),u=-1;var i=t?t.length:0;if(typeof i=="number"&&-1r?0:r)}function I(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?it(u+e,0):e||0;else if(e)return e=q(r,t),u&&r[e]===t?e:-1;return n(r,t,e)}function M(n,r,t){return N(n,null==r||t?1:0>r?0:r)}function N(n,r,t){var e=-1,u=n?n.length:0;for(r=null==r?0:+r||0,0>r?r=it(u+r,0):r>u&&(r=u),t=typeof t=="undefined"?u:+t||0,0>t?t=it(u+t,0):t>u&&(t=u),u=r>t?0:t-r,t=Array(u);++e>>1,t(n[e])u&&(u=t);else r=fr(r,t,3),g(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function L(n,r){return z(n,pr(r))}function P(n,r,t,e){var u=3>arguments.length; -r=fr(r,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return r=fr(r,e,4),h(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function G(n){var r=-1,t=n&&n.length,e=Array(0>t?0:t>>>0);return g(n,function(n){var t=w(++r);e[r]=e[t],e[t]=n}),e}function H(n,r,t){var e;(typeof r!="function"||typeof t!="undefined")&&(r=fr(r,t,3)),t=-1;var u=n?n.length:0; -if(typeof u=="number"&&-1arguments.length?E(n,gr,r):E(n,gr|vr,r,N(arguments,2))}function K(n,r,t){function e(){var t=r-(dt()-c);0>=t||t>r?(f&&clearTimeout(f),t=s,f=p=s=sr,t&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),f=p=s=sr,(v||h!==r)&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=dt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p; -else{f||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(f&&(f=clearTimeout(f)),g=c,a=n.apply(l,i)):f||(f=setTimeout(u,o))}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,a=n.apply(l,i)),!m||p||f||(i=l=null),a}var i,f,a,c,l,p,s,g=0,h=false,v=true;if(!rr(n))throw new TypeError(mr);if(r=0>r?0:r,true===t)var y=true,v=false;else tr(t)&&(y=t.leading,h="maxWait"in t&&it(r,+t.maxWait||0),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=sr},o}function Q(n){if(!rr(n))throw new TypeError(mr); -return function(){return!n.apply(this,arguments)}}function X(n){if(!n)return n;var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++t"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={};Mr[Tr]=Mr["[object Array]"]=Mr["[object Float32Array]"]=Mr["[object Float64Array]"]=Mr["[object Int8Array]"]=Mr["[object Int16Array]"]=Mr["[object Int32Array]"]=Mr["[object Uint8Array]"]=Mr["[object Uint8ClampedArray]"]=Mr["[object Uint16Array]"]=Mr["[object Uint32Array]"]=true,Mr["[object ArrayBuffer]"]=Mr[Er]=Mr[kr]=Mr["[object Error]"]=Mr["[object Function]"]=Mr["[object Map]"]=Mr[Or]=Mr[Sr]=Mr[Fr]=Mr["[object Set]"]=Mr[Ir]=Mr["[object WeakMap]"]=false; -var Nr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Br={"function":true,object:true},Rr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$r=Br[typeof window]&&window||this,Ur=Br[typeof exports]&&exports&&!exports.nodeType&&exports,Wr=Br[typeof module]&&module&&!module.nodeType&&module,Dr=Ur&&Wr&&typeof global=="object"&&global;!Dr||Dr.global!==Dr&&Dr.window!==Dr&&Dr.self!==Dr||($r=Dr); -var zr=Wr&&Wr.exports===Ur&&Ur,Cr=Array.prototype,Lr=Object.prototype,Pr=Function.prototype.toString,Vr=Math.pow(2,53)-1,Gr=$r._,Hr=Lr.toString,Jr=RegExp("^"+(null==Hr?"":(Hr+"").replace(Ar,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Kr=Math.ceil,Qr=Math.floor,Xr=Lr.hasOwnProperty,Yr=Cr.push,Zr=Lr.propertyIsEnumerable,nt=Cr.splice,rt=O(rt=Object.create)&&rt,tt=O(tt=Array.isArray)&&tt,et=$r.isFinite,ut=$r.isNaN,ot=O(ot=Object.keys)&&ot,it=Math.max,ft=Math.min,at=O(at=Date.now)&&at,ct=Math.random; +if(i||f)return d(i?n.__wrapped__:n,f?r.__wrapped__:r,t,e);if(i=Xr.call(n,"constructor"),f=Xr.call(r,"constructor"),i!=f||!i&&(i=n.constructor,f=r.constructor,i!=f&&!(rr(i)&&i instanceof i&&rr(f)&&f instanceof f)&&"constructor"in n&&"constructor"in r))return false}for(t||(t=[]),e||(e=[]),i=t.length;i--;)if(t[i]==n)return e[i]==r;if(t.push(n),e.push(r),u){if(i=n.length,f=i==r.length)for(;i--&&(f=d(n[i],r[i],t,e)););}else if(u=bt(n),i=u.length,f=i==bt(r).length)for(;i--&&(f=u[i],f=Xr.call(r,f)&&d(n[f],r[f],t,e)););return t.pop(),e.pop(),f +}function _(n,r,t){var e=-1,u=typeof r=="function",o=n&&n.length,i=Array(0>o?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):sr}),i}function j(n,r){var t={};if(typeof r=="function")return b(n,function(n,e,u){r(n,e,u)&&(t[e]=n)}),t;for(var e=-1,u=r.length;++eo(f,c)&&(t&&f.push(c),i.push(a)) +}return i}function x(n,r){var t,e=["_"];try{var u=Function(e,"return "+n+(t?"\n/*\n//# sourceURL="+t+"\n*/":"")).apply(sr,r);u.source=n}catch(o){throw o.source=n,o}return u}function T(n,r){return function(t,e,u){var o=r?r():{};e=fr(e,u,3),u=-1;var i=t?t.length:0;if(typeof i=="number"&&-1r?0:r)}function I(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?it(u+e,0):e||0; +else if(e)return e=q(r,t),u&&r[e]===t?e:-1;return n(r,t,e)}function M(n,r,t){return N(n,null==r||t?1:0>r?0:r)}function N(n,r,t){var e=-1,u=n?n.length:0;for(r=null==r?0:+r||0,0>r?r=it(u+r,0):r>u&&(r=u),t=typeof t=="undefined"?u:+t||0,0>t?t=it(u+t,0):t>u&&(t=u),u=r>t?0:t-r,t=Array(u);++e>>1,t(n[e])u&&(u=t);else r=fr(r,t,3),g(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function L(n,r){return z(n,pr(r))}function P(n,r,t,e){var u=3>arguments.length;r=fr(r,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return r=fr(r,e,4),h(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function G(n){var r=-1,t=n&&n.length,e=Array(0>t?0:t>>>0);return g(n,function(n){var t=w(++r);e[r]=e[t],e[t]=n}),e}function H(n,r,t){var e;(typeof r!="function"||typeof t!="undefined")&&(r=fr(r,t,3)),t=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length?E(n,gr,r):E(n,gr|vr,r,N(arguments,2)) +}function K(n,r,t){function e(){var t=r-(dt()-c);0>=t||t>r?(f&&clearTimeout(f),t=s,f=p=s=sr,t&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),f=p=s=sr,(v||h!==r)&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=dt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p;else{f||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(f&&(f=clearTimeout(f)),g=c,a=n.apply(l,i)):f||(f=setTimeout(u,o))}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,a=n.apply(l,i)),!m||p||f||(i=l=null),a +}var i,f,a,c,l,p,s,g=0,h=false,v=true;if(!rr(n))throw new TypeError(mr);if(r=0>r?0:r,true===t)var y=true,v=false;else tr(t)&&(y=t.leading,h="maxWait"in t&&it(r,+t.maxWait||0),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=sr},o}function Q(n){if(!rr(n))throw new TypeError(mr);return function(){return!n.apply(this,arguments)}}function X(n){if(!n)return n;var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++t"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={}; +Mr[Tr]=Mr["[object Array]"]=Mr["[object Float32Array]"]=Mr["[object Float64Array]"]=Mr["[object Int8Array]"]=Mr["[object Int16Array]"]=Mr["[object Int32Array]"]=Mr["[object Uint8Array]"]=Mr["[object Uint8ClampedArray]"]=Mr["[object Uint16Array]"]=Mr["[object Uint32Array]"]=true,Mr["[object ArrayBuffer]"]=Mr[Er]=Mr[kr]=Mr["[object Error]"]=Mr["[object Function]"]=Mr["[object Map]"]=Mr[Or]=Mr[Sr]=Mr[Fr]=Mr["[object Set]"]=Mr[Ir]=Mr["[object WeakMap]"]=false;var Nr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Br={"function":true,object:true},Rr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$r=Br[typeof window]&&window||this,Ur=Br[typeof exports]&&exports&&!exports.nodeType&&exports,Wr=Br[typeof module]&&module&&!module.nodeType&&module,Dr=Ur&&Wr&&typeof global=="object"&&global; +!Dr||Dr.global!==Dr&&Dr.window!==Dr&&Dr.self!==Dr||($r=Dr);var zr=Wr&&Wr.exports===Ur&&Ur,Cr=Array.prototype,Lr=Object.prototype,Pr=Function.prototype.toString,Vr=Math.pow(2,53)-1,Gr=$r._,Hr=Lr.toString,Jr=RegExp("^"+(null==Hr?"":(Hr+"").replace(Ar,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Kr=Math.ceil,Qr=Math.floor,Xr=Lr.hasOwnProperty,Yr=Cr.push,Zr=Lr.propertyIsEnumerable,nt=Cr.splice,rt=O(rt=Object.create)&&rt,tt=O(tt=Array.isArray)&&tt,et=$r.isFinite,ut=$r.isNaN,ot=O(ot=Object.keys)&&ot,it=Math.max,ft=Math.min,at=O(at=Date.now)&&at,ct=Math.random; i.prototype=o.prototype;var lt={};!function(){var n={0:1,length:1};lt.spliceObjects=(nt.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},rt||(c=function(){function n(){}return function(r){if(tr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||$r.Object()}}());var pt=M,st=F,gt=T(function(n,r,t){Xr.call(n,t)?n[t]++:n[t]=1}),ht=T(function(n,r,t){Xr.call(n,t)?n[t].push(r):n[t]=[r]}),vt=T(function(n,r,t){n[t]=r }),yt=T(function(n,r,t){n[t?0:1].push(r)},function(){return[[],[]]});nr(arguments)||(nr=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Xr.call(n,"callee")&&!Zr.call(n,"callee")||false});var mt=tt||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&"[object Array]"==Hr.call(n)||false};rr(/x/)&&(rr=function(n){return typeof n=="function"&&"[object Function]"==Hr.call(n)});var bt=ot?function(n){return tr(n)?ot(n):[]}:S,dt=at||function(){return(new Date).getTime()};o.after=function(n,r){if(!rr(r))throw new TypeError(mr); return n=et(n=+n)?n:0,function(){return 1>--n?r.apply(this,arguments):void 0}},o.bind=J,o.bindAll=function(n){for(var r=n,t=1 Date: Wed, 11 Jun 2014 16:58:26 -0700 Subject: [PATCH 0762/1608] Initial implementation of _.chunk - close #465 --- lodash.js | 30 ++++++++++++++++++++++++++++++ test/test.js | 25 ++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index d5039ce7b2..01c7811e2e 100644 --- a/lodash.js +++ b/lodash.js @@ -3998,6 +3998,35 @@ return baseAt(collection, baseFlatten(arguments, true, false, 1)); } + /** + * Creates an array of elements split into groups the length of `chunkSize`. + * If `collection` cannot be split evenly, the final chunk will be the remaining elements. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|string} collection The collection to iterate over. + * @param {numer} chunkSize The size of each chunk. + * @returns {Array} Returns the new array containing chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(collection, chunkSize) { + var index = 0, + length = collection ? collection.length : 0, + result = []; + + while (index < length) { + result.push(slice(collection, index, (index += chunkSize))); + } + return result; + } + /** * Checks if `value` is present in `collection` using strict equality for * comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the @@ -8611,6 +8640,7 @@ lodash.bindAll = bindAll; lodash.bindKey = bindKey; lodash.chain = chain; + lodash.chunk = chunk; lodash.compact = compact; lodash.compose = compose; lodash.constant = constant; diff --git a/test/test.js b/test/test.js index 059ecfd1d3..e1803d2a9f 100644 --- a/test/test.js +++ b/test/test.js @@ -1211,6 +1211,29 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.chunk'); + + (function() { + var array = [0, 1, 2, 3, 4, 5]; + + test('should return chunked arrays', 1, function() { + var actual = _.chunk(array, 3); + deepEqual(actual, [[0, 1, 2], [3, 4, 5]]); + }); + + test('should return the last chunk as remaining elements', 1, function() { + var actual = _.chunk(array, 4); + deepEqual(actual, [[0, 1, 2, 3], [4, 5]]); + }); + + test('should ignore falsey values', 1, function() { + var actual = _.chunk(false, 3); + deepEqual(actual, []); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('cloning'); (function() { @@ -10918,7 +10941,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 187, function() { + test('should accept falsey arguments', 188, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From d06a477371aea6482f53e145a7db2e380c2adc66 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 11 Jun 2014 22:59:30 -0700 Subject: [PATCH 0763/1608] Add "enumerable" to `_.isEmpty` doc. [ci skip] --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 01c7811e2e..ba62cd54ed 100644 --- a/lodash.js +++ b/lodash.js @@ -6567,7 +6567,7 @@ /** * Checks if a collection is empty. A value is considered empty unless it is * an array, array-like object, or string with a length greater than `0` or - * an object with own properties. + * an object with own enumerable properties. * * @static * @memberOf _ From b6bc844b4dd6c2c801eba4800ded93c5f122cb1e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 08:38:35 -0700 Subject: [PATCH 0764/1608] Remove support for cloning arrays and make `_.isEqual` more robust when comparing errors. --- lodash.js | 38 +++++++++++++++++++------------------- test/test.js | 50 +++++++++++++++++++++++--------------------------- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/lodash.js b/lodash.js index ba62cd54ed..90e86e2d75 100644 --- a/lodash.js +++ b/lodash.js @@ -162,16 +162,16 @@ /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; - cloneableClasses[argsClass] = - cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] = - cloneableClasses[boolClass] = cloneableClasses[dateClass] = - cloneableClasses[errorClass] = cloneableClasses[float32Class] = + cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] = + cloneableClasses[dateClass] = cloneableClasses[float32Class] = cloneableClasses[float64Class] = cloneableClasses[int8Class] = cloneableClasses[int16Class] = cloneableClasses[int32Class] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] = cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true; + cloneableClasses[errorClass] = cloneableClasses[funcClass] = cloneableClasses[mapClass] = cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false; @@ -1237,9 +1237,6 @@ case dateClass: return new Ctor(+value); - case errorClass: - return new Ctor(value.message); - case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: @@ -1791,10 +1788,6 @@ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +value == +other; - case errorClass: - // check properties instead of coercing to strings to support IE < 8 - return value.name === other.name && value.message === other.message; - case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) @@ -1804,18 +1797,20 @@ case regexpClass: case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and object instances as equal + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and + // treat strings primitives and string objects as equal return value == String(other); } + var isArr = arrayLikeClasses[valClass], + isErr = valClass == errorClass; + if (!support.argsClass) { valIsArg = isArguments(value); othIsArg = isArguments(other); } - var isArr = arrayLikeClasses[valClass]; if (!isArr) { - // exit for functions and DOM nodes - if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) { + // exit for things like functions and DOM nodes + if (!(isErr || valClass == objectClass) || (!support.nodeClass && (isNode(value) || isNode(other)))) { return false; } // unwrap any `lodash` wrapped values @@ -1836,6 +1831,10 @@ var valCtor = valIsArg ? Object : value.constructor, othCtor = othIsArg ? Object : other.constructor; + // error objects of different types are not equal + if (isErr && valCtor.prototype.name != othCtor.prototype.name) { + return false; + } // non `Object` object instances with different constructors are not equal if (valCtor != othCtor && !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && @@ -1895,8 +1894,8 @@ } } else { - var valProps = keys(value), - othProps = keys(other); + var valProps = isErr ? ['message', 'name'] : keys(value), + othProps = isErr ? ['message', 'name'] : keys(other); if (valIsArg) { valProps.push('length'); @@ -1910,7 +1909,8 @@ if (result || isWhere) { while (++index < length) { var key = valProps[index]; - result = hasOwnProperty.call(other, key); + result = isErr || hasOwnProperty.call(other, key); + if (result) { valValue = value[key]; othValue = other[key]; diff --git a/test/test.js b/test/test.js index e1803d2a9f..6567fdcf96 100644 --- a/test/test.js +++ b/test/test.js @@ -1241,30 +1241,30 @@ Klass.prototype = { 'b': 1 }; var nonCloneable = { - 'a DOM element': body, - 'a function': Klass + 'DOM elements': body, + 'functions': Klass }; var objects = { - 'an `arguments` object': arguments, - 'an array': ['a', ''], - 'an array-like-object': { '0': 'a', '1': '', 'length': 3 }, - 'boolean': false, - 'boolean object': Object(false), - 'a Klass instance': new Klass, - 'an object': { 'a': 0, 'b': 1, 'c': 3 }, - 'an object with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } }, - 'an object from another document': _._object || {}, - 'null': null, - 'a number': 3, - 'a number object': Object(3), - 'a regexp': /a/gim, - 'a string': 'a', - 'a string object': Object('a'), - 'undefined': undefined + '`arguments` objects': arguments, + 'arrays': ['a', ''], + 'array-like-objects': { '0': 'a', '1': '', 'length': 3 }, + 'booleans': false, + 'boolean objects': Object(false), + 'Klass instances': new Klass, + 'objects': { 'a': 0, 'b': 1, 'c': 3 }, + 'objects with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } }, + 'objects from another document': _._object || {}, + 'null values': null, + 'numbers': 3, + 'number objects': Object(3), + 'regexes': /a/gim, + 'strings': 'a', + 'string objects': Object('a'), + 'undefined values': undefined }; - objects['an array'].length = 3; + objects['arrays'].length = 3; test('`_.clone` should shallow clone by default', 2, function() { var expected = [{ 'a': 0 }, { 'b': 1 }], @@ -1313,13 +1313,9 @@ }); _.each(errorTypes, function(type) { - test('`_.' + methodName + '` should clone ' + type + ' objects', 2, function() { - var Ctor = root[type], - error = new Ctor('text'), - actual = func(error); - - ok(_.isEqual(actual, error)); - notStrictEqual(actual, error); + test('`_.' + methodName + '` should not clone ' + type + ' objects', 1, function() { + var error = new root[type]; + strictEqual(func(error), error); }); }); @@ -1426,7 +1422,7 @@ test('`_.' + methodName + '` should return a unwrapped value when chaining', 2, function() { if (!isNpm) { - var object = objects['an object'], + var object = objects['objects'], actual = _(object)[methodName](); deepEqual(actual, object); From d4f857b739c13edea42f6a1391cf5be6cfe17336 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 08:39:30 -0700 Subject: [PATCH 0765/1608] Move `_.chunk` to the Arrays category and make it use a default `chunkSize` of `1`. --- lodash.js | 60 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/lodash.js b/lodash.js index 90e86e2d75..1e48b602c2 100644 --- a/lodash.js +++ b/lodash.js @@ -2648,6 +2648,37 @@ /*--------------------------------------------------------------------------*/ + /** + * Creates an array of elements split into groups the length of `chunkSize`. + * If `collection` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {numer} [chunkSize=1] The size of each chunk. + * @returns {Array} Returns the new array containing chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, chunkSize) { + var index = 0, + length = array ? array.length : 0, + result = []; + + chunkSize = nativeMax(+chunkSize || 1, 1); + while (index < length) { + result.push(slice(array, index, (index += chunkSize))); + } + return result; + } + /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are all falsey. @@ -3998,35 +4029,6 @@ return baseAt(collection, baseFlatten(arguments, true, false, 1)); } - /** - * Creates an array of elements split into groups the length of `chunkSize`. - * If `collection` cannot be split evenly, the final chunk will be the remaining elements. - * - * @static - * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {numer} chunkSize The size of each chunk. - * @returns {Array} Returns the new array containing chunks. - * @example - * - * _.chunk(['a', 'b', 'c', 'd'], 2); - * // => [['a', 'b'], ['c', 'd']] - * - * _.chunk(['a', 'b', 'c', 'd'], 3); - * // => [['a', 'b', 'c'], ['d']] - */ - function chunk(collection, chunkSize) { - var index = 0, - length = collection ? collection.length : 0, - result = []; - - while (index < length) { - result.push(slice(collection, index, (index += chunkSize))); - } - return result; - } - /** * Checks if `value` is present in `collection` using strict equality for * comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the From 7d35c43defae30362d0f9ab14c057f786793d647 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 08:39:57 -0700 Subject: [PATCH 0766/1608] Minor doc / source cleanup. --- lodash.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lodash.js b/lodash.js index 1e48b602c2..73911312fb 100644 --- a/lodash.js +++ b/lodash.js @@ -1461,7 +1461,7 @@ * of values to exclude. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {Array} [values] The array of values to exclude. * @returns {Array} Returns the new array of filtered values. */ @@ -1895,7 +1895,7 @@ } else { var valProps = isErr ? ['message', 'name'] : keys(value), - othProps = isErr ? ['message', 'name'] : keys(other); + othProps = isErr ? valProps : keys(other); if (valIsArg) { valProps.push('length'); @@ -2094,7 +2094,7 @@ * and `this` binding. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. @@ -2715,7 +2715,7 @@ * @static * @memberOf _ * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example @@ -3710,7 +3710,7 @@ * @memberOf _ * @alias unique * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" @@ -5545,7 +5545,7 @@ trailing = false; } else if (isObject(options)) { leading = options.leading; - maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); + maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? options.trailing : trailing; } @@ -7830,7 +7830,7 @@ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); - // escape characters that cannot be included in string literals + // escape characters that can't be included in string literals source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // replace delimiters with snippets From 3ae328898d12639d338649bc38f60a8ac57c461d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 09:11:47 -0700 Subject: [PATCH 0767/1608] Reduce `_.omit`. --- lodash.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lodash.js b/lodash.js index 73911312fb..b095f1a283 100644 --- a/lodash.js +++ b/lodash.js @@ -7203,13 +7203,8 @@ if (typeof predicate == 'function') { return basePick(object, negate(lodash.createCallback(predicate, thisArg, 3))); } - var omitProps = baseFlatten(arguments, true, false, 1), - length = omitProps.length; - - while (length--) { - omitProps[length] = String(omitProps[length]); - } - return basePick(object, baseDifference(keysIn(object), omitProps)); + var omitProps = baseFlatten(arguments, true, false, 1); + return basePick(object, baseDifference(keysIn(object), arrayMap(omitProps, String))); } /** From 05ff79f3476f1b9f44f90085c4d5171f07d6fdd6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 09:17:59 -0700 Subject: [PATCH 0768/1608] Avoid using `passing` in test descriptions. --- test/test.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/test.js b/test/test.js index 6567fdcf96..78c1b6f75d 100644 --- a/test/test.js +++ b/test/test.js @@ -2933,7 +2933,7 @@ deepEqual(_.first(objects, 'b'), objects.slice(0, 2)); }); - test('should chain when passing `n`, `callback`, or `thisArg`', 3, function() { + test('should chain when `n`, `callback`, or `thisArg` are provided', 3, function() { if (!isNpm) { var actual = _(array).first(2); @@ -5911,7 +5911,7 @@ deepEqual(_.last(objects, 'b'), objects.slice(-2)); }); - test('should chain when passing `n`, `callback`, or `thisArg`', 3, function() { + test('should chain when `n`, `callback`, or `thisArg` are provided', 3, function() { if (!isNpm) { var actual = _(array).last(2); @@ -7619,7 +7619,7 @@ deepEqual(_.uniq(actual).sort(), [0, 1]); }); - test('supports not passing a `max` argument', 1, function() { + test('supports not providing a `max` argument', 1, function() { ok(_.some(array, function() { return _.random(5) !== 5; })); @@ -7651,7 +7651,7 @@ ok(actual >= min && actual <= max); }); - test('supports passing a `floating` argument', 3, function() { + test('supports providing a `floating` argument', 3, function() { var actual = _.random(true); ok(actual % 1 && actual >= 0 && actual <= 1); @@ -7668,15 +7668,15 @@ QUnit.module('lodash.range'); (function() { - test('should work when passing a single `end` argument', 1, function() { + test('should work with a single `end` argument', 1, function() { deepEqual(_.range(4), [0, 1, 2, 3]); }); - test('should work when passing `start` and `end` arguments', 1, function() { + test('should work with `start` and `end` arguments', 1, function() { deepEqual(_.range(1, 5), [1, 2, 3, 4]); }); - test('should work when passing `start`, `end`, and `step` arguments', 1, function() { + test('should work with `start`, `end`, and `step` arguments', 1, function() { deepEqual(_.range(0, 20, 5), [0, 5, 10, 15]); }); @@ -7684,11 +7684,11 @@ deepEqual(_.range(1, 4, 0), [1, 1, 1]); }); - test('should work when passing `step` larger than `end`', 1, function() { + test('should work with a `step` larger than `end`', 1, function() { deepEqual(_.range(1, 5, 20), [1]); }); - test('should work when passing a negative `step` argument', 2, function() { + test('should work with a negative `step` argument', 2, function() { deepEqual(_.range(0, -4, -1), [0, -1, -2, -3]); deepEqual(_.range(21, 10, -3), [21, 18, 15, 12]); }); @@ -8320,7 +8320,7 @@ ok(_.contains(a, actual[0]) && _.contains(b, actual[1]) && _.contains(c, actual[2])); }); - test('should chain when passing `n`', 1, function() { + test('should chain when `n` is provided', 1, function() { if (!isNpm) { var actual = _(array).sample(2); ok(actual instanceof _); @@ -10119,7 +10119,7 @@ strictEqual(_.uniq(actual).length, actual.length); }); - test('should return a string value when not passing a prefix argument', 1, function() { + test('should return a string value when not providing a prefix argument', 1, function() { strictEqual(typeof _.uniqueId(), 'string'); }); From 4c1a8f358af5f1ecd34625fe9684281f8756b48a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 09:29:05 -0700 Subject: [PATCH 0769/1608] Add more `_.chunk` tests. --- test/test.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index 78c1b6f75d..919f7d57bb 100644 --- a/test/test.js +++ b/test/test.js @@ -1226,9 +1226,15 @@ deepEqual(actual, [[0, 1, 2, 3], [4, 5]]); }); - test('should ignore falsey values', 1, function() { - var actual = _.chunk(false, 3); - deepEqual(actual, []); + test('should ensure the minimum `chunkSize` is `1`', 1, function() { + var values = falsey.concat(-1), + expected = _.map(values, _.constant([[0], [1], [2], [3], [4], [5]])); + + var actual = _.map(values, function(value, index) { + return index ? _.chunk(array, value) : _.chunk(array); + }); + + deepEqual(actual, expected); }); }()); @@ -10883,6 +10889,7 @@ var returnArrays = [ 'at', + 'chunk', 'compact', 'difference', 'filter', @@ -10937,7 +10944,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 188, function() { + test('should accept falsey arguments', 189, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; @@ -10980,7 +10987,7 @@ }); }); - test('should return an array', 66, function() { + test('should return an array', 68, function() { var array = [1, 2, 3]; _.each(returnArrays, function(methodName) { From 50c6b276f9de4193d2b08012221aa42e47431603 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 19:40:17 -0700 Subject: [PATCH 0770/1608] Remove `_.pluck` use from `_.zip`. --- lodash.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index b095f1a283..d99d904b4f 100644 --- a/lodash.js +++ b/lodash.js @@ -3836,8 +3836,8 @@ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], index = -1, - length = array ? max(pluck(array, 'length')) : 0, - result = Array(length < 0 ? 0 : length); + length = (array && array.length) ? max(array, 'length').length : 0, + result = Array(length); while (++index < length) { result[index] = pluck(array, index); From ed309182bfbaa81058c4b9faa8a5075c2430214b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 12 Jun 2014 23:39:30 -0700 Subject: [PATCH 0771/1608] Add `_.chunk` to the features section of the readme. [ci skip] --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 198f664bf5..092e1f5873 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ var _ = require('lodash-underscore'); ``` **Note:** -Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL +Don’t assign values to the [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL ## Features *not* in Underscore @@ -66,11 +66,12 @@ Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl * [_(…)](http://lodash.com/docs#_) supports intuitive chaining * [_.at](http://lodash.com/docs#at) for cherry-picking collection values * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”*](http://michaux.ca/articles/lazy-function-definition-pattern) defined methods + * [_.callback](http://lodash.com/docs#createCallback) for extending callbacks in methods & mixins + * [_.chunk](http://lodash.com/docs#chunk) for splitting an array into chunks of a given size * [_.clone](http://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` * [_.create](http://lodash.com/docs#create) for easier object inheritance - * [_.callback](http://lodash.com/docs#createCallback) for extending callbacks in methods & mixins * [_.curry](http://lodash.com/docs#curry) for creating [curried](http://hughfdjackson.com/javascript/why-curry-helps/) functions * [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) accept additional `options` for more control * [_.findIndex](http://lodash.com/docs#findIndex) & [_.findKey](http://lodash.com/docs#findKey) for finding indexes & keys @@ -88,7 +89,7 @@ Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl * [_.parseInt](http://lodash.com/docs#parseInt) for consistent behavior * [_.pull](http://lodash.com/docs#pull), [_.pullAt](http://lodash.com/docs#pullAt), & [_.remove](http://lodash.com/docs#remove) for mutating arrays * [_.random](http://lodash.com/docs#random) supports returning floating-point numbers - * [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking + * [_.runInContext](http://lodash.com/docs#runInContext) for collisionless mixins & easier mocking * [_.slice](http://lodash.com/docs#slice) for creating subsets of array-like values * [_.sortBy](http://lodash.com/docs#sortBy) supports sorting by multiple properties * [_.support](http://lodash.com/docs#support) for flagging environment features From f68efe6674ea92dbfe368aa8b04d9e101671192b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 13 Jun 2014 09:33:33 -0700 Subject: [PATCH 0772/1608] Make `_.partial` and `_.partialRight` docs complement each other. [ci skip] [closes #586] --- lodash.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index d99d904b4f..f82ce21c31 100644 --- a/lodash.js +++ b/lodash.js @@ -5820,9 +5820,9 @@ * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; - * var hi = _.partial(greet, 'hi'); - * hi('fred'); - * // => 'hi fred' + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' */ function partial(func) { if (func) { @@ -5849,6 +5849,12 @@ * @returns {Function} Returns the new partially applied function. * @example * + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hello'); + * // => 'hello fred' + * + * // create a deep `_.defaults` * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { * return _.merge(value, other, deep); * }); From b195fdbf60a6b549515b3e8ca6be05b65bde9cb5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 13 Jun 2014 23:52:57 -0700 Subject: [PATCH 0773/1608] Optimize `_.matches`. --- lodash.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index f82ce21c31..704962016b 100644 --- a/lodash.js +++ b/lodash.js @@ -8207,12 +8207,12 @@ // property containing a primitive value if (propsLength == 1 && value === value && !isObject(value)) { return function(object) { - if (!(object && hasOwnProperty.call(object, key))) { + if (object == null) { return false; } // treat `-0` vs. `+0` as not equal var other = object[key]; - return value === other && (value !== 0 || (1 / value == 1 / other)); + return value === other && (value !== 0 || (1 / value == 1 / other)) && hasOwnProperty.call(object, key); }; } return function(object) { From 74c08de53000faef971a833ab4b5428829c5dc83 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 14 Jun 2014 10:19:16 -0700 Subject: [PATCH 0774/1608] Cleanup `nonEnumProps` assignment. --- lodash.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lodash.js b/lodash.js index 704962016b..741814cf8b 100644 --- a/lodash.js +++ b/lodash.js @@ -712,17 +712,14 @@ nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true }; nonEnumProps[objectClass] = { 'constructor': true }; - (function() { - var length = shadowedProps.length; - while (length--) { - var key = shadowedProps[length]; - for (var className in nonEnumProps) { - if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) { - nonEnumProps[className][key] = false; - } + arrayEach(shadowedProps, function(key) { + for (var className in nonEnumProps) { + if (hasOwnProperty.call(nonEnumProps, className)) { + var props = nonEnumProps[className]; + props[key] = hasOwnProperty.call(props, key); } } - }()); + }); /*--------------------------------------------------------------------------*/ From 1065ebb0aad5d108b49d252f76c5bd2a42de84ac Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 14 Jun 2014 10:23:26 -0700 Subject: [PATCH 0775/1608] Simplify `baseFlatten`. --- lodash.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index 741814cf8b..2e2a1973af 100644 --- a/lodash.js +++ b/lodash.js @@ -1595,6 +1595,7 @@ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, + resIndex = 0, result = []; while (++index < length) { @@ -1607,15 +1608,14 @@ value = baseFlatten(value, isShallow, isStrict); } var valIndex = -1, - valLength = value.length, - resIndex = result.length; + valLength = value.length; result.length += valLength; while (++valIndex < valLength) { result[resIndex++] = value[valIndex]; } } else if (!isStrict) { - result.push(value); + result[resIndex++] = value; } } return result; From 4ccb3810c2fcaf7dadbecef67dc48ffbb893dd70 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 14 Jun 2014 23:21:36 -0700 Subject: [PATCH 0776/1608] Make nullish check consistent in variations of `_.matches` returned function. --- dist/lodash.underscore.js | 2 +- lodash.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 52f5c980d6..8b702b8441 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -5053,7 +5053,7 @@ return function(object) { var length = propsLength; - if (length && !object) { + if (length && object == null) { return false; } while (length--) { diff --git a/lodash.js b/lodash.js index 2e2a1973af..3bad128697 100644 --- a/lodash.js +++ b/lodash.js @@ -8214,7 +8214,7 @@ } return function(object) { var length = propsLength; - if (length && !object) { + if (length && object == null) { return false; } while (length--) { From 39bdd37615a69e2e1af32f1f9f1a41d0c410080b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 09:41:27 -0700 Subject: [PATCH 0777/1608] Correct the resolution of `length` in `_.zip`. --- dist/lodash.underscore.js | 4 ++-- lodash.js | 2 +- test/test.js | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 8b702b8441..04b370aa45 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -2026,8 +2026,8 @@ */ function zip() { var index = -1, - length = max(pluck(arguments, 'length')), - result = Array(length < 0 ? 0 : length); + length = isArray(length = max(arguments, 'length')) && length.length || 0, + result = Array(length); while (++index < length) { result[index] = pluck(arguments, index); diff --git a/lodash.js b/lodash.js index 3bad128697..97c4bba9e1 100644 --- a/lodash.js +++ b/lodash.js @@ -3833,7 +3833,7 @@ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], index = -1, - length = (array && array.length) ? max(array, 'length').length : 0, + length = isArray(length = max(array, 'length')) && length.length || 0, result = Array(length); while (++index < length) { diff --git a/test/test.js b/test/test.js index 919f7d57bb..a1a04bf0f4 100644 --- a/test/test.js +++ b/test/test.js @@ -10434,6 +10434,21 @@ deepEqual(actual, [['barney', 36, undefined], ['fred', 40, false]]); }); + test('should treat falsey values as empty arrays', 1, function() { + var expected = _.map(falsey, _.constant([])); + + var actual = _.map(falsey, function(value) { + return _.zip(value, value, value); + }); + + deepEqual(actual, expected); + }); + + test('should support consuming its return value', 1, function() { + var expected = [['barney', 'fred'], [36, 40]]; + deepEqual(_.zip(_.zip(_.zip(_.zip(expected)))), expected); + }); + test('should support consuming its return value', 1, function() { var expected = [['barney', 'fred'], [36, 40]]; deepEqual(_.zip(_.zip(_.zip(_.zip(expected)))), expected); From 04b93aeaf25ec3e791c2b423f561996d69bad448 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 10:21:44 -0700 Subject: [PATCH 0778/1608] Make object check style consistent. --- dist/lodash.underscore.js | 4 ++-- lodash.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 04b370aa45..e15ba1127f 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -3931,7 +3931,7 @@ * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function assign(object) { - if (!object) { + if (object == null) { return object; } var args = arguments, @@ -4024,7 +4024,7 @@ * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { - if (!object) { + if (object == null) { return object; } var args = arguments, diff --git a/lodash.js b/lodash.js index 97c4bba9e1..f778f0dd03 100644 --- a/lodash.js +++ b/lodash.js @@ -2304,7 +2304,7 @@ var args = arguments, length = args.length; - if (!object || length < 2) { + if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` @@ -6150,7 +6150,7 @@ * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { - if (!object) { + if (object == null) { return object; } var args = slice(arguments); From 5b7b16416bbddbe0dab51aeb948d2318d47fb22a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 13:45:46 -0700 Subject: [PATCH 0779/1608] Fix `_.zip` use with `arguments` objects. --- dist/lodash.underscore.js | 2 +- lodash.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index e15ba1127f..8ca6cb0806 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -2026,7 +2026,7 @@ */ function zip() { var index = -1, - length = isArray(length = max(arguments, 'length')) && length.length || 0, + length = isObject(length = max(arguments, 'length')) && length.length || 0, result = Array(length); while (++index < length) { diff --git a/lodash.js b/lodash.js index f778f0dd03..355cea392a 100644 --- a/lodash.js +++ b/lodash.js @@ -3833,7 +3833,7 @@ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], index = -1, - length = isArray(length = max(array, 'length')) && length.length || 0, + length = isObject(length = max(array, 'length')) && length.length || 0, result = Array(length); while (++index < length) { From e884916275ac167f1190488127e68ba29369f9b7 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 13:46:51 -0700 Subject: [PATCH 0780/1608] Rebuild dist. --- dist/lodash.compat.js | 140 +++++++++++++++++++++------------- dist/lodash.compat.min.js | 85 +++++++++++---------- dist/lodash.js | 125 +++++++++++++++++++----------- dist/lodash.min.js | 125 +++++++++++++++--------------- dist/lodash.underscore.js | 35 ++++----- dist/lodash.underscore.min.js | 18 ++--- 6 files changed, 294 insertions(+), 234 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 6794893c64..5827ddf8e0 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -163,16 +163,16 @@ /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; - cloneableClasses[argsClass] = - cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] = - cloneableClasses[boolClass] = cloneableClasses[dateClass] = - cloneableClasses[errorClass] = cloneableClasses[float32Class] = + cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] = + cloneableClasses[dateClass] = cloneableClasses[float32Class] = cloneableClasses[float64Class] = cloneableClasses[int8Class] = cloneableClasses[int16Class] = cloneableClasses[int32Class] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] = cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true; + cloneableClasses[errorClass] = cloneableClasses[funcClass] = cloneableClasses[mapClass] = cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false; @@ -713,17 +713,14 @@ nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true }; nonEnumProps[objectClass] = { 'constructor': true }; - (function() { - var length = shadowedProps.length; - while (length--) { - var key = shadowedProps[length]; - for (var className in nonEnumProps) { - if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) { - nonEnumProps[className][key] = false; - } + arrayEach(shadowedProps, function(key) { + for (var className in nonEnumProps) { + if (hasOwnProperty.call(nonEnumProps, className)) { + var props = nonEnumProps[className]; + props[key] = hasOwnProperty.call(props, key); } } - }()); + }); /*--------------------------------------------------------------------------*/ @@ -1238,9 +1235,6 @@ case dateClass: return new Ctor(+value); - case errorClass: - return new Ctor(value.message); - case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: @@ -1465,7 +1459,7 @@ * of values to exclude. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {Array} [values] The array of values to exclude. * @returns {Array} Returns the new array of filtered values. */ @@ -1602,6 +1596,7 @@ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, + resIndex = 0, result = []; while (++index < length) { @@ -1614,15 +1609,14 @@ value = baseFlatten(value, isShallow, isStrict); } var valIndex = -1, - valLength = value.length, - resIndex = result.length; + valLength = value.length; result.length += valLength; while (++valIndex < valLength) { result[resIndex++] = value[valIndex]; } } else if (!isStrict) { - result.push(value); + result[resIndex++] = value; } } return result; @@ -1792,10 +1786,6 @@ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +value == +other; - case errorClass: - // check properties instead of coercing to strings to support IE < 8 - return value.name === other.name && value.message === other.message; - case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) @@ -1805,18 +1795,20 @@ case regexpClass: case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and object instances as equal + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and + // treat strings primitives and string objects as equal return value == String(other); } + var isArr = arrayLikeClasses[valClass], + isErr = valClass == errorClass; + if (!support.argsClass) { valIsArg = isArguments(value); othIsArg = isArguments(other); } - var isArr = arrayLikeClasses[valClass]; if (!isArr) { - // exit for functions and DOM nodes - if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) { + // exit for things like functions and DOM nodes + if (!(isErr || valClass == objectClass) || (!support.nodeClass && (isNode(value) || isNode(other)))) { return false; } // unwrap any `lodash` wrapped values @@ -1837,6 +1829,10 @@ var valCtor = valIsArg ? Object : value.constructor, othCtor = othIsArg ? Object : other.constructor; + // error objects of different types are not equal + if (isErr && valCtor.prototype.name != othCtor.prototype.name) { + return false; + } // non `Object` object instances with different constructors are not equal if (valCtor != othCtor && !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && @@ -1896,8 +1892,8 @@ } } else { - var valProps = keys(value), - othProps = keys(other); + var valProps = isErr ? ['message', 'name'] : keys(value), + othProps = isErr ? valProps : keys(other); if (valIsArg) { valProps.push('length'); @@ -1911,7 +1907,8 @@ if (result || isWhere) { while (++index < length) { var key = valProps[index]; - result = hasOwnProperty.call(other, key); + result = isErr || hasOwnProperty.call(other, key); + if (result) { valValue = value[key]; othValue = other[key]; @@ -2095,7 +2092,7 @@ * and `this` binding. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. @@ -2308,7 +2305,7 @@ var args = arguments, length = args.length; - if (!object || length < 2) { + if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` @@ -2649,6 +2646,37 @@ /*--------------------------------------------------------------------------*/ + /** + * Creates an array of elements split into groups the length of `chunkSize`. + * If `collection` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {numer} [chunkSize=1] The size of each chunk. + * @returns {Array} Returns the new array containing chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, chunkSize) { + var index = 0, + length = array ? array.length : 0, + result = []; + + chunkSize = nativeMax(+chunkSize || 1, 1); + while (index < length) { + result.push(slice(array, index, (index += chunkSize))); + } + return result; + } + /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are all falsey. @@ -2685,7 +2713,7 @@ * @static * @memberOf _ * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example @@ -3680,7 +3708,7 @@ * @memberOf _ * @alias unique * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" @@ -3806,8 +3834,8 @@ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], index = -1, - length = array ? max(pluck(array, 'length')) : 0, - result = Array(length < 0 ? 0 : length); + length = isObject(length = max(array, 'length')) && length.length || 0, + result = Array(length); while (++index < length) { result[index] = pluck(array, index); @@ -5515,7 +5543,7 @@ trailing = false; } else if (isObject(options)) { leading = options.leading; - maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); + maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? options.trailing : trailing; } @@ -5790,9 +5818,9 @@ * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; - * var hi = _.partial(greet, 'hi'); - * hi('fred'); - * // => 'hi fred' + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' */ function partial(func) { if (func) { @@ -5819,6 +5847,12 @@ * @returns {Function} Returns the new partially applied function. * @example * + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hello'); + * // => 'hello fred' + * + * // create a deep `_.defaults` * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { * return _.merge(value, other, deep); * }); @@ -6117,7 +6151,7 @@ * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { - if (!object) { + if (object == null) { return object; } var args = slice(arguments); @@ -6539,7 +6573,7 @@ /** * Checks if a collection is empty. A value is considered empty unless it is * an array, array-like object, or string with a length greater than `0` or - * an object with own properties. + * an object with own enumerable properties. * * @static * @memberOf _ @@ -7173,13 +7207,8 @@ if (typeof predicate == 'function') { return basePick(object, negate(lodash.createCallback(predicate, thisArg, 3))); } - var omitProps = baseFlatten(arguments, true, false, 1), - length = omitProps.length; - - while (length--) { - omitProps[length] = String(omitProps[length]); - } - return basePick(object, baseDifference(keysIn(object), omitProps)); + var omitProps = baseFlatten(arguments, true, false, 1); + return basePick(object, baseDifference(keysIn(object), arrayMap(omitProps, String))); } /** @@ -7800,7 +7829,7 @@ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); - // escape characters that cannot be included in string literals + // escape characters that can't be included in string literals source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // replace delimiters with snippets @@ -8176,17 +8205,17 @@ // property containing a primitive value if (propsLength == 1 && value === value && !isObject(value)) { return function(object) { - if (!(object && hasOwnProperty.call(object, key))) { + if (object == null) { return false; } // treat `-0` vs. `+0` as not equal var other = object[key]; - return value === other && (value !== 0 || (1 / value == 1 / other)); + return value === other && (value !== 0 || (1 / value == 1 / other)) && hasOwnProperty.call(object, key); }; } return function(object) { var length = propsLength; - if (length && !object) { + if (length && object == null) { return false; } while (length--) { @@ -8612,6 +8641,7 @@ lodash.bindAll = bindAll; lodash.bindKey = bindKey; lodash.chain = chain; + lodash.chunk = chunk; lodash.compact = compact; lodash.compose = compose; lodash.constant = constant; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 6a10a47621..d3f251cd4c 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -4,68 +4,69 @@ * Build: `lodash -o ./dist/lodash.compat.js` */ ;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=ue(e);++ra(t,l)&&f.push(l);return f}function Lt(n,t){var r=-1,e=n,u=n?n.length:0;if(typeof u=="number"&&-1l)for(;++fl)for(;++so?0:o>>>0);return Lt(n,function(n){var o=u?t:null!=n&&n[t];a[++e]=o?o.apply(n,r):m}),a}function Vt(n,t,r,e,u){var o=ar(t);return(o?jt:zt)(t,function(t,a,i){var l=t&&ar(t),f=t&&iu(t),c=n[a];if(l||f){for(e||(e=[]),u||(u=[]),f=e.length;f--;)if(e[f]==t)return void(n[a]=u[f]);i=r?r(c,t,a,n,i):m,(f=typeof i!="undefined")||(i=l?au(c)?c:[]:iu(c)?c:{}),e.push(t),u.push(i),f||Vt(i,t,r,e,u),n[a]=i}else i=r?r(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i) -}),n}function Jt(n,t){var r={};if(typeof t=="function")return Dt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r;for(var e=-1,u=t.length;++ei(s,g)&&((u||f)&&s.push(g),c.push(p)) +}),n}function Jt(n,t){var r={};if(typeof t=="function")return Dt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r;for(var e=-1,u=t.length;++ei(s,h)&&((u||f)&&s.push(h),c.push(p)) }return c}function Gt(n,t){for(var r=-1,e=t(n),u=e.length,o=ue(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3e)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3o?0:o)}function gr(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?Ze(u+e,0):e||0;else if(e)return e=mr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function hr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),dr(n,0,0>o?0:o)}function vr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; +for(t=q.createCallback(t,r,3);++eo?0:o)}function hr(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?Ze(u+e,0):e||0;else if(e)return e=mr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function gr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),dr(n,0,0>o?0:o)}function vr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0; for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:m;return o=e-(o||0),dr(n,0>o?0:o)}function yr(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,r,3);++et?0:t;return dr(n,o)}function dr(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t?t=Ze(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=Ze(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=ue(u);++e>>1,r(n[e])r?0:r);++t>>1,r(n[e])r?Ze(e+r,0):r||0:0,typeof n=="string"||!au(n)&&Kr(n)?ro&&(o=i)}else t=null==t&&Kr(n)?u:q.createCallback(t,r,3),Lt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Rr(n,t){return Ir(n,ee(t))}function Ur(n,t,r,e){var u=3>arguments.length; if(t=q.createCallback(t,e,4),au(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++oarguments.length;return t=q.createCallback(t,e,4),Tt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Nr(n){var t=-1,r=n&&n.length,e=ue(0>r?0:r>>>0);return Lt(n,function(n){var r=Xt(0,++t);e[t]=e[r],e[r]=n}),e}function Lr(n,t,r){var e;if((typeof t!="function"||typeof r!="undefined")&&(t=q.createCallback(t,r,3)),au(n)){r=-1; -for(var u=n.length;++rarguments.length)return er(n,b,null,t);if(n)var r=n[k]?n[k][2]:n.length,e=dr(arguments,2),r=r-e.length;return er(n,b|A,r,t,e)}function Wr(n,t,r){function e(){var r=t-(gu()-f);0>=r||r>t?(i&&ke(i),r=p,i=s=p=m,r&&(g=gu(),l=n.apply(c,a),s||i||(a=c=null))):s=Ne(e,r)}function u(){s&&ke(s),i=s=p=m,(v||h!==t)&&(g=gu(),l=n.apply(c,a),s||i||(a=c=null))}function o(){if(a=arguments,f=gu(),c=this,p=v&&(s||!y),false===h)var r=y&&!s; -else{i||y||(g=f);var o=h-(f-g),d=0>=o||o>h;d?(i&&(i=ke(i)),g=f,l=n.apply(c,a)):i||(i=Ne(u,o))}return d&&s?s=ke(s):s||t===h||(s=Ne(e,t)),r&&(d=true,l=n.apply(c,a)),!d||s||i||(a=c=null),l}var a,i,l,f,c,s,p,g=0,h=false,v=true;if(!zr(n))throw new pe(O);if(t=0>t?0:t,true===r)var y=true,v=false;else qr(r)&&(y=r.leading,h="maxWait"in r&&Ze(t,+r.maxWait||0),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&ke(s),i&&ke(i),i=s=p=m},o}function $r(n){if(!zr(n))throw new pe(O);return function(){return!n.apply(this,arguments) -}}function Pr(n){return Mt(n,Vr)}function Br(n){return n&&typeof n=="object"&&typeof n.length=="number"&&we.call(n)==H||false}function Dr(n){return n&&typeof n=="object"&&1===n.nodeType&&(He.nodeClass?-1>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,a=r-1,e=ue(r),i=0t||null==n||!ze(t))return r;n=se(n);do t%2&&(r+=n),t=Ee(t/2),n+=n;while(t);return r}function Gr(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n),v(n)+1):(t=se(t),n.slice(o(n,t),a(n,t)+1)):n}function Hr(n,t,r){var e=typeof n,u="function"==e;return u&&typeof t=="undefined"?n:u||null==n?Ut(n,t,r):"object"==e?ne(n):ee(n) -}function Qr(n){return n}function ne(n){var t=lu(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||qr(u)?function(e){var u=r;if(u&&!e)return false;for(;u--;){var o=t[u];if(!Se.call(e,o)||!Zt(n[o],e[o],null,true))return false}return true}:function(n){return n&&Se.call(n,e)?(n=n[e],u===n&&(0!==u||1/u==1/n)):false}}function te(n,t,r){var e=true,u=t&&Mt(t,lu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Mt(t,lu)),false===r?e=false:qr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=zr(n),a=u?u.length:0;++rarguments.length)return er(n,b,null,t);if(n)var r=n[k]?n[k][2]:n.length,e=dr(arguments,2),r=r-e.length;return er(n,b|A,r,t,e)}function Wr(n,t,r){function e(){var r=t-(hu()-f);0>=r||r>t?(i&&ke(i),r=p,i=s=p=m,r&&(h=hu(),l=n.apply(c,a),s||i||(a=c=null))):s=Ne(e,r)}function u(){s&&ke(s),i=s=p=m,(v||g!==t)&&(h=hu(),l=n.apply(c,a),s||i||(a=c=null))}function o(){if(a=arguments,f=hu(),c=this,p=v&&(s||!y),false===g)var r=y&&!s; +else{i||y||(h=f);var o=g-(f-h),d=0>=o||o>g;d?(i&&(i=ke(i)),h=f,l=n.apply(c,a)):i||(i=Ne(u,o))}return d&&s?s=ke(s):s||t===g||(s=Ne(e,t)),r&&(d=true,l=n.apply(c,a)),!d||s||i||(a=c=null),l}var a,i,l,f,c,s,p,h=0,g=false,v=true;if(!zr(n))throw new pe(O);if(t=0>t?0:t,true===r)var y=true,v=false;else qr(r)&&(y=r.leading,g="maxWait"in r&&Ze(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&ke(s),i&&ke(i),i=s=p=m},o}function $r(n){if(!zr(n))throw new pe(O);return function(){return!n.apply(this,arguments) +}}function Pr(n){return Mt(n,Vr)}function Br(n){return n&&typeof n=="object"&&typeof n.length=="number"&&we.call(n)==H||false}function Dr(n){return n&&typeof n=="object"&&1===n.nodeType&&(He.nodeClass?-1>>0,e=n.constructor,u=-1,o=e&&n===e.prototype,a=r-1,e=ue(r),i=0t||null==n||!ze(t))return r;n=se(n);do t%2&&(r+=n),t=Ee(t/2),n+=n;while(t);return r}function Gr(n,t){return(n=null==n?"":se(n))?null==t?n.slice(g(n),v(n)+1):(t=se(t),n.slice(o(n,t),a(n,t)+1)):n}function Hr(n,t,r){var e=typeof n,u="function"==e;return u&&typeof t=="undefined"?n:u||null==n?Ut(n,t,r):"object"==e?ne(n):ee(n) +}function Qr(n){return n}function ne(n){var t=lu(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||qr(u)?function(e){var u=r;if(u&&null==e)return false;for(;u--;){var o=t[u];if(!Se.call(e,o)||!Zt(n[o],e[o],null,true))return false}return true}:function(n){if(null==n)return false;var t=n[e];return u===t&&(0!==u||1/u==1/t)&&Se.call(n,e)}}function te(n,t,r){var e=true,u=t&&Mt(t,lu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Mt(t,lu)),false===r?e=false:qr(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=zr(n),a=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},q.assign=ou,q.at=function(t){return He.unindexedChars&&Kr(t)&&(t=t.split("")),n(t,$t(arguments,true,false,1))},q.bind=Tr,q.bindAll=function(n){for(var t=n,r=1arguments.length?er(t,b|_,null,n):er(t,b|_|A,null,n,dr(arguments,2)) -},q.chain=function(n){return new J(n,true)},q.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t(p?e(p,l):a(s,l))){for(t=u;--t;){var g=o[t];if(0>(g?e(g,l):a(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},q.invert=function(n,t){for(var r=-1,e=lu(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=q.createCallback(t,r,3)),Lt(n,function(n,r,u){if(o)for(r=t.length,u=ue(r);r--;)u[r]=n[t[r]];else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?l:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,r){return t.call(r,n),n},q.throttle=function(n,t,r){var e=true,u=true;if(!zr(n))throw new pe(O);return false===r?e=false:qr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),_t.leading=e,_t.maxWait=+t,_t.trailing=u,Wr(n,t,_t) -},q.times=function(n,t,r){n=0>n?0:n>>>0,t=Ut(t,r,1),r=-1;for(var e=ue(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},q.escape=function(n){return null==n?"":se(n).replace(N,s)},q.escapeRegExp=Xr,q.every=Cr,q.find=kr,q.findIndex=sr,q.findKey=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,zt,true) -},q.findLast=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,Tt)},q.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=q.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},q.findLastKey=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,qt,true)},q.findWhere=function(n,t){return kr(n,ne(t))},q.has=function(n,t){return n?Se.call(n,t):false},q.identity=Qr,q.indexOf=gr,q.isArguments=Br,q.isArray=au,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&we.call(n)==nt||false -},q.isDate=function(n){return n&&typeof n=="object"&&we.call(n)==tt||false},q.isElement=Dr,q.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Ze(e+r,0):Ke(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},q.noConflict=function(){return c._=_e,this},q.noop=re,q.now=gu,q.pad=function(n,t,r){n=null==n?"":se(n),t=+t; -var e=n.length;return e(p?e(p,l):a(s,l))){for(t=u;--t;){var h=o[t]; +if(0>(h?e(h,l):a(n[t],l)))continue n}p&&p.push(l),s.push(l)}return s},q.invert=function(n,t){for(var r=-1,e=lu(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=q.createCallback(t,r,3)),Lt(n,function(n,r,u){if(o)for(r=t.length,u=ue(r);r--;)u[r]=n[t[r]]; +else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?l:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,r){return t.call(r,n),n},q.throttle=function(n,t,r){var e=true,u=true;if(!zr(n))throw new pe(O);return false===r?e=false:qr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),_t.leading=e,_t.maxWait=+t,_t.trailing=u,Wr(n,t,_t)},q.times=function(n,t,r){n=0>n?0:n>>>0,t=Ut(t,r,1),r=-1;for(var e=ue(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},q.escape=function(n){return null==n?"":se(n).replace(N,s)},q.escapeRegExp=Xr,q.every=Cr,q.find=kr,q.findIndex=sr,q.findKey=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,zt,true)},q.findLast=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,Tt) +},q.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=q.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},q.findLastKey=function(n,t,r){return t=q.createCallback(t,r,3),Wt(n,t,qt,true)},q.findWhere=function(n,t){return kr(n,ne(t))},q.has=function(n,t){return n?Se.call(n,t):false},q.identity=Qr,q.indexOf=hr,q.isArguments=Br,q.isArray=au,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&we.call(n)==nt||false},q.isDate=function(n){return n&&typeof n=="object"&&we.call(n)==tt||false +},q.isElement=Dr,q.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?Ze(e+r,0):Ke(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},q.noConflict=function(){return c._=_e,this},q.noop=re,q.now=hu,q.pad=function(n,t,r){n=null==n?"":se(n),t=+t;var e=n.length; +return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},q.template=function(n,t,r){var e=q.templateSettings;r=ou({},r,e,xt),n=se(null==n?"":n);var u,o,a=ou({},r.imports,e.imports,xt),e=lu(a),a=Jr(a),i=0,l=r.interpolate||M,f="__p+='",l=ce((r.escape||M).source+"|"+l.source+"|"+(l===W?$:M).source+"|"+(r.evaluate||M).source+"|$","g"); return n.replace(l,function(t,r,e,a,l,c){return e||(e=a),f+=n.slice(i,c).replace(V,p),r&&(u=true,f+="'+__e("+r+")+'"),l&&(o=true,f+="';"+l+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",(r=r.variable)||(f="with(obj){"+f+"}"),f=(o?f.replace(S,""):f).replace(R,"$1").replace(U,"$1;"),f="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}",r=Ht(f,e,a),t?r(t):r -},q.trim=Gr,q.trimLeft=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(h(n)):(t=se(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(0,v(n)+1):(t=se(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var r=30,e="...";if(t&&qr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?se(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":se(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e; +},q.trim=Gr,q.trimLeft=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(g(n)):(t=se(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":se(n))?null==t?n.slice(0,v(n)+1):(t=se(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var r=30,e="...";if(t&&qr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?se(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":se(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e; if(Zr(u)){if(n.slice(o).search(u)){var a,i,l=n.slice(0,o);for(u.global||(u=ce(u.source,(P.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(l);)i=a.index;r=r.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(F,y))},q.uniqueId=function(n){var t=++E;return se(null==n?"":n)+t},q.all=Cr,q.any=Lr,q.detect=kr,q.foldl=Ur,q.foldr=Fr,q.include=Ar,q.inject=Ur,te(q,function(){var n={};return zt(q,function(t,r){q.prototype[r]||(n[r]=t) }),n}(),false),q.first=pr,q.last=vr,q.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Jr(n):He.unindexedChars&&Kr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=pr,q.takeRight=vr,q.takeRightWhile=vr,q.takeWhile=pr,q.head=pr,zt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o}) -}),q.VERSION=x,q.prototype.chain=function(){return this.__chain__=true,this},q.prototype.toJSON=jr,q.prototype.toString=function(){return se(this.__wrapped__)},q.prototype.value=jr,q.prototype.valueOf=jr,jt(["join","pop","shift"],function(n){var t=ge[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),jt(["push","reverse","sort","unshift"],function(n){var t=ge[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),jt(["concat","splice"],function(n){var t=ge[n]; -q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),He.spliceObjects||jt(["pop","shift","splice"],function(n){var t=ge[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,A=16,C=32,x="2.5.0-pre",k="__lodash@"+x+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,S=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,L=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",gt="[object Int32Array]",ht="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; -mt[H]=mt[Q]=mt[ft]=mt[ct]=mt[st]=mt[pt]=mt[gt]=mt[ht]=mt[vt]=mt[yt]=mt[dt]=true,mt[lt]=mt[nt]=mt[tt]=mt[rt]=mt[et]=mt["[object Map]"]=mt[ut]=mt[ot]=mt[at]=mt["[object Set]"]=mt[it]=mt["[object WeakMap]"]=false;var bt={};bt[H]=bt[Q]=bt[lt]=bt[nt]=bt[tt]=bt[rt]=bt[ft]=bt[ct]=bt[st]=bt[pt]=bt[gt]=bt[ut]=bt[ot]=bt[at]=bt[it]=bt[ht]=bt[vt]=bt[yt]=bt[dt]=true,bt[et]=bt["[object Map]"]=bt["[object Set]"]=bt["[object WeakMap]"]=false;var _t={leading:false,maxWait:0,trailing:false},wt={configurable:false,enumerable:false,value:null,writable:false},jt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},At={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},xt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ot=xt[typeof window]&&window||this,Et=xt[typeof exports]&&exports&&!exports.nodeType&&exports,xt=xt[typeof module]&&module&&!module.nodeType&&module,It=Et&&xt&&typeof global=="object"&&global; +}),q.VERSION=x,q.prototype.chain=function(){return this.__chain__=true,this},q.prototype.toJSON=jr,q.prototype.toString=function(){return se(this.__wrapped__)},q.prototype.value=jr,q.prototype.valueOf=jr,jt(["join","pop","shift"],function(n){var t=he[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),jt(["push","reverse","sort","unshift"],function(n){var t=he[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),jt(["concat","splice"],function(n){var t=he[n]; +q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),He.spliceObjects||jt(["pop","shift","splice"],function(n){var t=he[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,A=16,C=32,x="2.5.0-pre",k="__lodash@"+x+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,S=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,L=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",ht="[object Int32Array]",gt="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; +mt[H]=mt[Q]=mt[ft]=mt[ct]=mt[st]=mt[pt]=mt[ht]=mt[gt]=mt[vt]=mt[yt]=mt[dt]=true,mt[lt]=mt[nt]=mt[tt]=mt[rt]=mt[et]=mt["[object Map]"]=mt[ut]=mt[ot]=mt[at]=mt["[object Set]"]=mt[it]=mt["[object WeakMap]"]=false;var bt={};bt[H]=bt[Q]=bt[lt]=bt[nt]=bt[tt]=bt[ft]=bt[ct]=bt[st]=bt[pt]=bt[ht]=bt[ut]=bt[ot]=bt[at]=bt[it]=bt[gt]=bt[vt]=bt[yt]=bt[dt]=true,bt[rt]=bt[et]=bt["[object Map]"]=bt["[object Set]"]=bt["[object WeakMap]"]=false;var _t={leading:false,maxWait:0,trailing:false},wt={configurable:false,enumerable:false,value:null,writable:false},jt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},At={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},xt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ot=xt[typeof window]&&window||this,Et=xt[typeof exports]&&exports&&!exports.nodeType&&exports,xt=xt[typeof module]&&module&&!module.nodeType&&module,It=Et&&xt&&typeof global=="object"&&global; !It||It.global!==It&&It.window!==It&&It.self!==It||(Ot=It);var It=xt&&xt.exports===Et&&Et,St=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ot._=St, define(function(){return St})):Et&&xt?It?(xt.exports=St)._=St:Et._=St:Ot._=St}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index ab8f859f1d..f73ae96e2d 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -157,16 +157,16 @@ /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; - cloneableClasses[argsClass] = - cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] = - cloneableClasses[boolClass] = cloneableClasses[dateClass] = - cloneableClasses[errorClass] = cloneableClasses[float32Class] = + cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] = + cloneableClasses[dateClass] = cloneableClasses[float32Class] = cloneableClasses[float64Class] = cloneableClasses[int8Class] = cloneableClasses[int16Class] = cloneableClasses[int32Class] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] = cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true; + cloneableClasses[errorClass] = cloneableClasses[funcClass] = cloneableClasses[mapClass] = cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false; @@ -1077,9 +1077,6 @@ case dateClass: return new Ctor(+value); - case errorClass: - return new Ctor(value.message); - case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: @@ -1300,7 +1297,7 @@ * of values to exclude. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {Array} [values] The array of values to exclude. * @returns {Array} Returns the new array of filtered values. */ @@ -1431,6 +1428,7 @@ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, + resIndex = 0, result = []; while (++index < length) { @@ -1443,15 +1441,14 @@ value = baseFlatten(value, isShallow, isStrict); } var valIndex = -1, - valLength = value.length, - resIndex = result.length; + valLength = value.length; result.length += valLength; while (++valIndex < valLength) { result[resIndex++] = value[valIndex]; } } else if (!isStrict) { - result.push(value); + result[resIndex++] = value; } } return result; @@ -1621,10 +1618,6 @@ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +value == +other; - case errorClass: - // check properties instead of coercing to strings to support IE < 8 - return value.name === other.name && value.message === other.message; - case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) @@ -1634,14 +1627,16 @@ case regexpClass: case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and object instances as equal + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and + // treat strings primitives and string objects as equal return value == String(other); } - var isArr = arrayLikeClasses[valClass]; + var isArr = arrayLikeClasses[valClass], + isErr = valClass == errorClass; + if (!isArr) { - // exit for functions and DOM nodes - if (valClass != objectClass) { + // exit for things like functions and DOM nodes + if (!(isErr || valClass == objectClass)) { return false; } // unwrap any `lodash` wrapped values @@ -1662,6 +1657,10 @@ var valCtor = valIsArg ? Object : value.constructor, othCtor = othIsArg ? Object : other.constructor; + // error objects of different types are not equal + if (isErr && valCtor.prototype.name != othCtor.prototype.name) { + return false; + } // non `Object` object instances with different constructors are not equal if (valCtor != othCtor && !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && @@ -1721,8 +1720,8 @@ } } else { - var valProps = keys(value), - othProps = keys(other); + var valProps = isErr ? ['message', 'name'] : keys(value), + othProps = isErr ? valProps : keys(other); if (valIsArg) { valProps.push('length'); @@ -1736,7 +1735,8 @@ if (result || isWhere) { while (++index < length) { var key = valProps[index]; - result = hasOwnProperty.call(other, key); + result = isErr || hasOwnProperty.call(other, key); + if (result) { valValue = value[key]; othValue = other[key]; @@ -1920,7 +1920,7 @@ * and `this` binding. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. @@ -2133,7 +2133,7 @@ var args = arguments, length = args.length; - if (!object || length < 2) { + if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` @@ -2461,6 +2461,37 @@ /*--------------------------------------------------------------------------*/ + /** + * Creates an array of elements split into groups the length of `chunkSize`. + * If `collection` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {numer} [chunkSize=1] The size of each chunk. + * @returns {Array} Returns the new array containing chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, chunkSize) { + var index = 0, + length = array ? array.length : 0, + result = []; + + chunkSize = nativeMax(+chunkSize || 1, 1); + while (index < length) { + result.push(slice(array, index, (index += chunkSize))); + } + return result; + } + /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are all falsey. @@ -2497,7 +2528,7 @@ * @static * @memberOf _ * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example @@ -3492,7 +3523,7 @@ * @memberOf _ * @alias unique * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" @@ -3618,8 +3649,8 @@ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], index = -1, - length = array ? max(pluck(array, 'length')) : 0, - result = Array(length < 0 ? 0 : length); + length = isObject(length = max(array, 'length')) && length.length || 0, + result = Array(length); while (++index < length) { result[index] = pluck(array, index); @@ -5333,7 +5364,7 @@ trailing = false; } else if (isObject(options)) { leading = options.leading; - maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); + maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? options.trailing : trailing; } @@ -5608,9 +5639,9 @@ * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; - * var hi = _.partial(greet, 'hi'); - * hi('fred'); - * // => 'hi fred' + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' */ function partial(func) { if (func) { @@ -5637,6 +5668,12 @@ * @returns {Function} Returns the new partially applied function. * @example * + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hello'); + * // => 'hello fred' + * + * // create a deep `_.defaults` * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { * return _.merge(value, other, deep); * }); @@ -5935,7 +5972,7 @@ * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { - if (!object) { + if (object == null) { return object; } var args = slice(arguments); @@ -6350,7 +6387,7 @@ /** * Checks if a collection is empty. A value is considered empty unless it is * an array, array-like object, or string with a length greater than `0` or - * an object with own properties. + * an object with own enumerable properties. * * @static * @memberOf _ @@ -6953,13 +6990,8 @@ if (typeof predicate == 'function') { return basePick(object, negate(lodash.createCallback(predicate, thisArg, 3))); } - var omitProps = baseFlatten(arguments, true, false, 1), - length = omitProps.length; - - while (length--) { - omitProps[length] = String(omitProps[length]); - } - return basePick(object, baseDifference(keysIn(object), omitProps)); + var omitProps = baseFlatten(arguments, true, false, 1); + return basePick(object, baseDifference(keysIn(object), arrayMap(omitProps, String))); } /** @@ -7580,7 +7612,7 @@ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); - // escape characters that cannot be included in string literals + // escape characters that can't be included in string literals source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // replace delimiters with snippets @@ -7956,17 +7988,17 @@ // property containing a primitive value if (propsLength == 1 && value === value && !isObject(value)) { return function(object) { - if (!(object && hasOwnProperty.call(object, key))) { + if (object == null) { return false; } // treat `-0` vs. `+0` as not equal var other = object[key]; - return value === other && (value !== 0 || (1 / value == 1 / other)); + return value === other && (value !== 0 || (1 / value == 1 / other)) && hasOwnProperty.call(object, key); }; } return function(object) { var length = propsLength; - if (length && !object) { + if (length && object == null) { return false; } while (length--) { @@ -8392,6 +8424,7 @@ lodash.bindAll = bindAll; lodash.bindKey = bindKey; lodash.chain = chain; + lodash.chunk = chunk; lodash.compact = compact; lodash.compose = compose; lodash.constant = constant; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 973b119b32..0e34b905d5 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,66 +3,67 @@ * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){for(var e=-1,r=t.length,u=Array(r);++et||typeof n=="undefined")return 1;if(nr||13r||8202e||13e||8202>>0:0,u=tr(r);++ea(t,f)&&l.push(f);return l}function St(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number"&&-1f)for(;++lo?0:o>>>0);return St(n,function(n){var o=u?t:null!=n&&n[t];a[++r]=o?o.apply(n,e):m}),a}function Zt(n,t,e,r,u){var o=re(t);return(o?dt:Bt)(t,function(t,a,i){var f=t&&re(t),l=t&&nu(t),c=n[a]; -if(f||l){for(r||(r=[]),u||(u=[]),l=r.length;l--;)if(r[l]==t)return void(n[a]=u[l]);i=e?e(c,t,a,n,i):m,(l=typeof i!="undefined")||(i=f?Qr(c)?c:[]:nu(c)?c:{}),r.push(t),u.push(i),l||Zt(i,t,e,r,u),n[a]=i}else i=e?e(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i)}),n}function Pt(n,t){var e={};if(typeof t=="function")return Lt(n,function(n,r,u){t(n,r,u)&&(e[r]=n)}),e;for(var r=-1,u=t.length;++ri(p,h)&&((u||l)&&p.push(h),c.push(s))}return c}function Jt(n,t){for(var e=-1,r=t(n),u=r.length,o=tr(u);++er)return t;var u=typeof e[2];if("number"!=u&&"string"!=u||!e[3]||e[3][e[2]]!==e[1]||(r=2),3o?0:o)}function ce(n,t,r){var u=n?n.length:0;if(typeof r=="number")r=0>r?Dr(u+r,0):r||0;else if(r)return r=ve(n,t),u&&n[r]===t?r:-1;return e(n,t,r)}function pe(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0; -for(t=q.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else o=null==t||e?1:t;return o=r-(o||0),ge(n,0,0>o?0:o)}function se(n,t,e){var r=n?n.length:0;if(typeof t!="number"&&null!=t){var u=r,o=0;for(t=q.createCallback(t,e,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||e)return n?n[r-1]:m;return o=r-(o||0),ge(n,0>o?0:o)}function he(n,t,e){if(typeof t!="number"&&null!=t){var r=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,e,3);++rt?0:t;return ge(n,o)}function ge(n,t,e){var r=-1,u=n?n.length:0; -for(t=null==t?0:+t||0,0>t?t=Dr(u+t,0):t>u&&(t=u),e=typeof e=="undefined"?u:+e||0,0>e?e=Dr(u+e,0):e>u&&(e=u),u=t>e?0:e-t,e=tr(u);++r>>1,e(n[r])e?0:e);++te?Dr(r+e,0):e||0:0,typeof n=="string"||!Qr(n)&&Me(n)?eo&&(o=i)}else t=null==t&&Me(n)?u:q.createCallback(t,e,3),St(n,function(n,e,u){e=t(n,e,u),(e>r||-1/0===e&&e===o)&&(r=e,o=n)});return o}function Ie(n,t){return Ce(n,nr(t))}function Ee(n,t,e,r){var u=3>arguments.length;t=q.createCallback(t,r,4);var o=-1,a=n?n.length:0;if(typeof a=="number"&&-1arguments.length;return t=q.createCallback(t,r,4),Ut(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Fe(n){var t=-1,e=n&&n.length,r=tr(0>e?0:e>>>0);return St(n,function(n){var e=Kt(0,++t);r[t]=r[e],r[e]=n}),r}function Se(n,t,e){var r;(typeof t!="function"||typeof e!="undefined")&&(t=q.createCallback(t,e,3)),e=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return ne(n,b,null,t);if(n)var e=n[x]?n[x][2]:n.length,r=ge(arguments,2),e=e-r.length;return ne(n,b|j,e,t,r)}function Ne(n,t,e){function r(){var e=t-(au()-l);0>=e||e>t?(i&&wr(i),e=s,i=p=s=m,e&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))):p=Er(r,e)}function u(){p&&wr(p),i=p=s=m,(v||g!==t)&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))}function o(){if(a=arguments,l=au(),c=this,s=v&&(p||!y),false===g)var e=y&&!p; -else{i||y||(h=l);var o=g-(l-h),m=0>=o||o>g;m?(i&&(i=wr(i)),h=l,f=n.apply(c,a)):i||(i=Er(u,o))}return m&&p?p=wr(p):p||t===g||(p=Er(r,t)),e&&(m=true,f=n.apply(c,a)),!m||p||i||(a=c=null),f}var a,i,f,l,c,p,s,h=0,g=false,v=true;if(!Be(n))throw new fr(C);if(t=0>t?0:t,true===e)var y=true,v=false;else De(e)&&(y=e.leading,g="maxWait"in e&&Dr(t,+e.maxWait||0),v="trailing"in e?e.trailing:v);return o.cancel=function(){p&&wr(p),i&&wr(i),i=p=s=m},o}function Te(n){if(!Be(n))throw new fr(C);return function(){return!n.apply(this,arguments) -}}function We(n){return zt(n,Ze)}function $e(n){return n&&typeof n=="object"&&typeof n.length=="number"&&yr.call(n)==Y||false}function Le(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,r=n.constructor,u=-1,r=r&&n===r.prototype,o=e-1,a=tr(e),i=0t||null==n||!$r(t))return e;n=ir(n);do t%2&&(e+=n),t=Ar(t/2),n+=n;while(t);return e}function Je(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n),g(n)+1):(t=ir(t),n.slice(o(n,t),a(n,t)+1)):n -}function Xe(n,t,e){var r=typeof n,u="function"==r;return u&&typeof t=="undefined"?n:u||null==n?Et(n,t,e):"object"==r?Ge(n):nr(n)}function Ye(n){return n}function Ge(n){var t=tu(n),e=t.length,r=t[0],u=e&&n[r];return 1!=e||u!==u||De(u)?function(r){var u=e;if(u&&!r)return false;for(;u--;){var o=t[u];if(!xr.call(r,o)||!qt(n[o],r[o],null,true))return false}return true}:function(n){return n&&xr.call(n,r)?(n=n[r],u===n&&(0!==u||1/u==1/n)):false}}function He(n,t,e){var r=true,u=t&&zt(t,tu);t&&(e||u.length)||(null==e&&(e=t),t=n,n=this,u=zt(t,tu)),false===e?r=false:De(e)&&"chain"in e&&(r=e.chain),e=-1; -for(var o=Be(n),a=u?u.length:0;++e--n?t.apply(this,arguments):void 0}},q.assign=Hr,q.at=function(t){return n(t,Tt(arguments,true,false,1))},q.bind=Ue,q.bindAll=function(n){for(var t=n,e=1arguments.length?ne(t,b|d,null,n):ne(t,b|d|j,null,n,ge(arguments,2))},q.chain=function(n){return new V(n,true) -},q.compact=function(n){for(var t=-1,e=n?n.length:0,r=0,u=[];++t(s?r(s,f):a(p,f))){for(t=u;--t;){var h=o[t];if(0>(h?r(h,f):a(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},q.invert=function(n,t){for(var e=-1,r=tu(n),u=r.length,o={};++eu?0:u>>>0);for(o||(t=q.createCallback(t,e,3)),St(n,function(n,e,u){if(o)for(e=t.length,u=tr(e);e--;)u[e]=n[t[e]];else u=t(n,e,u);a[++r]={a:u,b:r,c:n}}),u=a.length,a.sort(o?f:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,e){return t.call(e,n),n},q.throttle=function(n,t,e){var r=true,u=true;if(!Be(n))throw new fr(C);return false===e?r=false:De(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),mt.leading=r,mt.maxWait=+t,mt.trailing=u,Ne(n,t,mt) -},q.times=function(n,t,e){n=0>n?0:n>>>0,t=Et(t,e,1),e=-1;for(var r=tr(n);++ee?0:+e||0,r))-t.length,0<=e&&n.indexOf(t,e)==e},q.escape=function(n){return null==n?"":ir(n).replace(U,p)},q.escapeRegExp=Ke,q.every=we,q.find=Ae,q.findIndex=fe,q.findKey=function(n,t,e){return t=q.createCallback(t,e,3),Nt(n,t,Bt,true) -},q.findLast=function(n,t,e){return t=q.createCallback(t,e,3),Nt(n,t,Ut)},q.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=q.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},q.findLastKey=function(n,t,e){return t=q.createCallback(t,e,3),Nt(n,t,Dt,true)},q.findWhere=function(n,t){return Ae(n,Ge(t))},q.has=function(n,t){return n?xr.call(n,t):false},q.identity=Ye,q.indexOf=ce,q.isArguments=$e,q.isArray=Qr,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&yr.call(n)==H||false -},q.isDate=function(n){return n&&typeof n=="object"&&yr.call(n)==Q||false},q.isElement=Le,q.isEmpty=function(n){var t=true;if(!n)return t;var e=n.length;return-1e?Dr(r+e,0):zr(e||0,r-1))+1);r--;)if(n[r]===t)return r;return-1},q.noConflict=function(){return c._=vr,this},q.noop=Qe,q.now=au,q.pad=function(n,t,e){n=null==n?"":ir(n),t=+t; -var r=n.length;return re?0:+e||0,n.length),n.lastIndexOf(t,e)==e},q.template=function(n,t,e){var r=q.templateSettings;e=Hr({},e,r,jt),n=ir(null==n?"":n);var u,o,a=Hr({},e.imports,r.imports,jt),r=tu(a),a=Pe(a),i=0,f=e.interpolate||M,l="__p+='",f=ar((e.escape||M).source+"|"+f.source+"|"+(f===W?$:M).source+"|"+(e.evaluate||M).source+"|$","g"); -return n.replace(f,function(t,e,r,a,f,c){return r||(r=a),l+=n.slice(i,c).replace(K,s),e&&(u=true,l+="'+__e("+e+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t}),l+="';",(e=e.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(E,""):l).replace(R,"$1").replace(F,"$1;"),l="function("+(e||"obj")+"){"+(e?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",e=Xt(l,r,a,void 0),t?e(t):e -},q.trim=Je,q.trimLeft=function(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(h(n)):(t=ir(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":ir(n))?null==t?n.slice(0,g(n)+1):(t=ir(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var e=30,r="...";if(t&&De(t))var u="separator"in t?t.separator:u,e="length"in t?+t.length||0:e,r="omission"in t?ir(t.omission):r;else null!=t&&(e=+t||0);if(n=null==n?"":ir(n),e>=n.length)return n;var o=e-r.length;if(1>o)return r;if(e=n.slice(0,o),null==u)return e+r; -if(qe(u)){if(n.slice(o).search(u)){var a,i,f=n.slice(0,o);for(u.global||(u=ar(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(f);)i=a.index;e=e.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=e.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(S,v))},q.uniqueId=function(n){var t=++O;return ir(null==n?"":n)+t},q.all=we,q.any=Se,q.detect=Ae,q.foldl=Ee,q.foldr=Re,q.include=_e,q.inject=Ee,He(q,function(){var n={};return Bt(q,function(t,e){q.prototype[e]||(n[e]=t) -}),n}(),false),q.first=le,q.last=se,q.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Pe(n)),null==t||e?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=le,q.takeRight=se,q.takeRightWhile=se,q.takeWhile=le,q.head=le,Bt(q,function(n,t){var e="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new V(o,u):o})}),q.VERSION=k,q.prototype.chain=function(){return this.__chain__=true,this -},q.prototype.toJSON=de,q.prototype.toString=function(){return ir(this.__wrapped__)},q.prototype.value=de,q.prototype.valueOf=de,dt(["join","pop","shift"],function(n){var t=lr[n];q.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new V(e,n):e}}),dt(["push","reverse","sort","unshift"],function(n){var t=lr[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),dt(["concat","splice"],function(n){var t=lr[n];q.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__) -}}),q}var m,b=1,d=2,_=4,w=8,j=16,A=32,k="2.5.0-pre",x="__lodash@"+k+"__",C="Expected a function",O=0,I=/^[A-Z]+$/,E=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39|#96);/g,U=/[&<>"'`]/g,N=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",et="[object Object]",rt="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; -vt[Y]=vt[G]=vt[at]=vt[it]=vt[ft]=vt[lt]=vt[ct]=vt[pt]=vt[st]=vt[ht]=vt[gt]=true,vt[ot]=vt[H]=vt[Q]=vt[nt]=vt["[object Function]"]=vt["[object Map]"]=vt[tt]=vt[et]=vt[rt]=vt["[object Set]"]=vt[ut]=vt["[object WeakMap]"]=false;var yt={};yt[Y]=yt[G]=yt[ot]=yt[H]=yt[Q]=yt[nt]=yt[at]=yt[it]=yt[ft]=yt[lt]=yt[ct]=yt[tt]=yt[et]=yt[rt]=yt[ut]=yt[pt]=yt[st]=yt[ht]=yt[gt]=true,yt["[object Function]"]=yt["[object Map]"]=yt["[object Set]"]=yt["[object WeakMap]"]=false;var mt={leading:false,maxWait:0,trailing:false},bt={configurable:false,enumerable:false,value:null,writable:false},dt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},_t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},wt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},jt={"function":true,object:true},At={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},kt=jt[typeof window]&&window||this,xt=jt[typeof exports]&&exports&&!exports.nodeType&&exports,jt=jt[typeof module]&&module&&!module.nodeType&&module,Ct=xt&&jt&&typeof global=="object"&&global; +;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202>>0:0,u=te(e);++ra(t,f)&&l.push(f);return l}function St(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number"&&-1f)for(;++po?0:o>>>0);return St(n,function(n){var o=u?t:null!=n&&n[t];a[++e]=o?o.apply(n,r):m}),a}function Zt(n,t,r,e,u){var o=er(t);return(o?dt:Bt)(t,function(t,a,i){var f=t&&er(t),l=t&&nu(t),c=n[a]; +if(f||l){for(e||(e=[]),u||(u=[]),l=e.length;l--;)if(e[l]==t)return void(n[a]=u[l]);i=r?r(c,t,a,n,i):m,(l=typeof i!="undefined")||(i=f?Qe(c)?c:[]:nu(c)?c:{}),e.push(t),u.push(i),l||Zt(i,t,r,e,u),n[a]=i}else i=r?r(c,t,a,n,i):m,typeof i=="undefined"&&(i=t),(o||typeof i!="undefined")&&(n[a]=i)}),n}function Pt(n,t){var r={};if(typeof t=="function")return Lt(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r;for(var e=-1,u=t.length;++ei(p,h)&&((u||l)&&p.push(h),c.push(s))}return c}function Jt(n,t){for(var r=-1,e=t(n),u=e.length,o=te(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3o?0:o)}function cr(n,t,e){var u=n?n.length:0;if(typeof e=="number")e=0>e?De(u+e,0):e||0;else if(e)return e=vr(n,t),u&&n[e]===t?e:-1;return r(n,t,e) +}function pr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else o=null==t||r?1:t;return o=e-(o||0),gr(n,0,0>o?0:o)}function sr(n,t,r){var e=n?n.length:0;if(typeof t!="number"&&null!=t){var u=e,o=0;for(t=q.createCallback(t,r,3);u--&&t(n[u],u,n);)o++}else if(o=t,null==o||r)return n?n[e-1]:m;return o=e-(o||0),gr(n,0>o?0:o)}function hr(n,t,r){if(typeof t!="number"&&null!=t){var e=-1,u=n?n.length:0,o=0;for(t=q.createCallback(t,r,3);++et?0:t;return gr(n,o)}function gr(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t?t=De(u+t,0):t>u&&(t=u),r=typeof r=="undefined"?u:+r||0,0>r?r=De(u+r,0):r>u&&(r=u),u=t>r?0:r-t,r=te(u);++e>>1,r(n[e])r?De(e+r,0):r||0:0,typeof n=="string"||!Qe(n)&&Mr(n)?ro&&(o=i)}else t=null==t&&Mr(n)?u:q.createCallback(t,r,3),St(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Ir(n,t){return Cr(n,ne(t))}function Er(n,t,r,e){var u=3>arguments.length;t=q.createCallback(t,e,4);var o=-1,a=n?n.length:0;if(typeof a=="number"&&-1arguments.length;return t=q.createCallback(t,e,4),Ut(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Fr(n){var t=-1,r=n&&n.length,e=te(0>r?0:r>>>0);return St(n,function(n){var r=Kt(0,++t);e[t]=e[r],e[r]=n}),e}function Sr(n,t,r){var e;(typeof t!="function"||typeof r!="undefined")&&(t=q.createCallback(t,r,3)),r=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length)return nr(n,b,null,t);if(n)var r=n[x]?n[x][2]:n.length,e=gr(arguments,2),r=r-e.length;return nr(n,b|j,r,t,e)}function Nr(n,t,r){function e(){var r=t-(au()-l);0>=r||r>t?(i&&we(i),r=s,i=p=s=m,r&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))):p=Ee(e,r)}function u(){p&&we(p),i=p=s=m,(v||g!==t)&&(h=au(),f=n.apply(c,a),p||i||(a=c=null))}function o(){if(a=arguments,l=au(),c=this,s=v&&(p||!y),false===g)var r=y&&!p; +else{i||y||(h=l);var o=g-(l-h),m=0>=o||o>g;m?(i&&(i=we(i)),h=l,f=n.apply(c,a)):i||(i=Ee(u,o))}return m&&p?p=we(p):p||t===g||(p=Ee(e,t)),r&&(m=true,f=n.apply(c,a)),!m||p||i||(a=c=null),f}var a,i,f,l,c,p,s,h=0,g=false,v=true;if(!Br(n))throw new fe(C);if(t=0>t?0:t,true===r)var y=true,v=false;else Dr(r)&&(y=r.leading,g="maxWait"in r&&De(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){p&&we(p),i&&we(i),i=p=s=m},o}function Tr(n){if(!Br(n))throw new fe(C);return function(){return!n.apply(this,arguments) +}}function Wr(n){return zt(n,Zr)}function $r(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ye.call(n)==Y||false}function Lr(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,a=te(r),i=0t||null==n||!$e(t))return r;n=ie(n);do t%2&&(r+=n),t=Ae(t/2),n+=n;while(t);return r}function Jr(n,t){return(n=null==n?"":ie(n))?null==t?n.slice(h(n),g(n)+1):(t=ie(t),n.slice(o(n,t),a(n,t)+1)):n +}function Xr(n,t,r){var e=typeof n,u="function"==e;return u&&typeof t=="undefined"?n:u||null==n?Et(n,t,r):"object"==e?Gr(n):ne(n)}function Yr(n){return n}function Gr(n){var t=tu(n),r=t.length,e=t[0],u=r&&n[e];return 1!=r||u!==u||Dr(u)?function(e){var u=r;if(u&&null==e)return false;for(;u--;){var o=t[u];if(!xe.call(e,o)||!qt(n[o],e[o],null,true))return false}return true}:function(n){if(null==n)return false;var t=n[e];return u===t&&(0!==u||1/u==1/t)&&xe.call(n,e)}}function Hr(n,t,r){var e=true,u=t&&zt(t,tu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=zt(t,tu)),false===r?e=false:Dr(r)&&"chain"in r&&(e=r.chain),r=-1; +for(var o=Br(n),a=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},q.assign=He,q.at=function(t){return n(t,Tt(arguments,true,false,1))},q.bind=Ur,q.bindAll=function(n){for(var t=n,r=1arguments.length?nr(t,b|d,null,n):nr(t,b|d|j,null,n,gr(arguments,2))},q.chain=function(n){return new V(n,true) +},q.chunk=function(n,t){var r=0,e=n?n.length:0,u=[];for(t=De(+t||1,1);r(s?e(s,f):a(p,f))){for(t=u;--t;){var h=o[t]; +if(0>(h?e(h,f):a(n[t],f)))continue n}s&&s.push(f),p.push(f)}return p},q.invert=function(n,t){for(var r=-1,e=tu(n),u=e.length,o={};++ru?0:u>>>0);for(o||(t=q.createCallback(t,r,3)),St(n,function(n,r,u){if(o)for(r=t.length,u=te(r);r--;)u[r]=n[t[r]]; +else u=t(n,r,u);a[++e]={a:u,b:e,c:n}}),u=a.length,a.sort(o?f:i);u--;)a[u]=a[u].c;return a},q.tap=function(n,t,r){return t.call(r,n),n},q.throttle=function(n,t,r){var e=true,u=true;if(!Br(n))throw new fe(C);return false===r?e=false:Dr(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),mt.leading=e,mt.maxWait=+t,mt.trailing=u,Nr(n,t,mt)},q.times=function(n,t,r){n=0>n?0:n>>>0,t=Et(t,r,1),r=-1;for(var e=te(n);++rr?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},q.escape=function(n){return null==n?"":ie(n).replace(U,p)},q.escapeRegExp=Kr,q.every=wr,q.find=Ar,q.findIndex=fr,q.findKey=function(n,t,r){return t=q.createCallback(t,r,3),Nt(n,t,Bt,true)},q.findLast=function(n,t,r){return t=q.createCallback(t,r,3),Nt(n,t,Ut) +},q.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=q.createCallback(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},q.findLastKey=function(n,t,r){return t=q.createCallback(t,r,3),Nt(n,t,Dt,true)},q.findWhere=function(n,t){return Ar(n,Gr(t))},q.has=function(n,t){return n?xe.call(n,t):false},q.identity=Yr,q.indexOf=cr,q.isArguments=$r,q.isArray=Qe,q.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ye.call(n)==H||false},q.isDate=function(n){return n&&typeof n=="object"&&ye.call(n)==Q||false +},q.isElement=Lr,q.isEmpty=function(n){var t=true;if(!n)return t;var r=n.length;return-1r?De(e+r,0):ze(r||0,e-1))+1);e--;)if(n[e]===t)return e;return-1},q.noConflict=function(){return c._=ve,this},q.noop=Qr,q.now=au,q.pad=function(n,t,r){n=null==n?"":ie(n),t=+t;var e=n.length; +return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},q.template=function(n,t,r){var e=q.templateSettings;r=He({},r,e,jt),n=ie(null==n?"":n);var u,o,a=He({},r.imports,e.imports,jt),e=tu(a),a=Pr(a),i=0,f=r.interpolate||M,l="__p+='",f=ae((r.escape||M).source+"|"+f.source+"|"+(f===W?$:M).source+"|"+(r.evaluate||M).source+"|$","g"); +return n.replace(f,function(t,r,e,a,f,c){return e||(e=a),l+=n.slice(i,c).replace(K,s),r&&(u=true,l+="'+__e("+r+")+'"),f&&(o=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),l+="';",(r=r.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(E,""):l).replace(R,"$1").replace(F,"$1;"),l="function("+(r||"obj")+"){"+(r?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",r=Xt(l,e,a,void 0),t?r(t):r +},q.trim=Jr,q.trimLeft=function(n,t){return(n=null==n?"":ie(n))?null==t?n.slice(h(n)):(t=ie(t),n.slice(o(n,t))):n},q.trimRight=function(n,t){return(n=null==n?"":ie(n))?null==t?n.slice(0,g(n)+1):(t=ie(t),n.slice(0,a(n,t)+1)):n},q.trunc=function(n,t){var r=30,e="...";if(t&&Dr(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?ie(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":ie(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e;if(r=n.slice(0,o),null==u)return r+e; +if(qr(u)){if(n.slice(o).search(u)){var a,i,f=n.slice(0,o);for(u.global||(u=ae(u.source,(L.exec(u)||"")+"g")),u.lastIndex=0;a=u.exec(f);)i=a.index;r=r.slice(0,null==i?o:i)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1n.indexOf(";")?n:n.replace(S,v))},q.uniqueId=function(n){var t=++O;return ie(null==n?"":n)+t},q.all=wr,q.any=Sr,q.detect=Ar,q.foldl=Er,q.foldr=Rr,q.include=_r,q.inject=Er,Hr(q,function(){var n={};return Bt(q,function(t,r){q.prototype[r]||(n[r]=t) +}),n}(),false),q.first=lr,q.last=sr,q.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Pr(n)),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=lr,q.takeRight=sr,q.takeRightWhile=sr,q.takeWhile=lr,q.head=lr,Bt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o})}),q.VERSION=k,q.prototype.chain=function(){return this.__chain__=true,this +},q.prototype.toJSON=dr,q.prototype.toString=function(){return ie(this.__wrapped__)},q.prototype.value=dr,q.prototype.valueOf=dr,dt(["join","pop","shift"],function(n){var t=le[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),dt(["push","reverse","sort","unshift"],function(n){var t=le[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),dt(["concat","splice"],function(n){var t=le[n];q.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__) +}}),q}var m,b=1,d=2,_=4,w=8,j=16,A=32,k="2.5.0-pre",x="__lodash@"+k+"__",C="Expected a function",O=0,I=/^[A-Z]+$/,E=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39|#96);/g,U=/[&<>"'`]/g,N=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",rt="[object Object]",et="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; +vt[Y]=vt[G]=vt[at]=vt[it]=vt[ft]=vt[lt]=vt[ct]=vt[pt]=vt[st]=vt[ht]=vt[gt]=true,vt[ot]=vt[H]=vt[Q]=vt[nt]=vt["[object Function]"]=vt["[object Map]"]=vt[tt]=vt[rt]=vt[et]=vt["[object Set]"]=vt[ut]=vt["[object WeakMap]"]=false;var yt={};yt[Y]=yt[G]=yt[ot]=yt[H]=yt[Q]=yt[at]=yt[it]=yt[ft]=yt[lt]=yt[ct]=yt[tt]=yt[rt]=yt[et]=yt[ut]=yt[pt]=yt[st]=yt[ht]=yt[gt]=true,yt[nt]=yt["[object Function]"]=yt["[object Map]"]=yt["[object Set]"]=yt["[object WeakMap]"]=false;var mt={leading:false,maxWait:0,trailing:false},bt={configurable:false,enumerable:false,value:null,writable:false},dt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},_t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},wt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},jt={"function":true,object:true},At={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},kt=jt[typeof window]&&window||this,xt=jt[typeof exports]&&exports&&!exports.nodeType&&exports,jt=jt[typeof module]&&module&&!module.nodeType&&module,Ct=xt&&jt&&typeof global=="object"&&global; !Ct||Ct.global!==Ct&&Ct.window!==Ct&&Ct.self!==Ct||(kt=Ct);var Ct=jt&&jt.exports===xt&&xt,Ot=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(kt._=Ot, define(function(){return Ot})):xt&&jt?Ct?(jt.exports=Ot)._=Ot:xt._=Ot:kt._=Ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 8ca6cb0806..452965c156 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -640,7 +640,7 @@ * of values to exclude. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {Array} [values] The array of values to exclude. * @returns {Array} Returns the new array of filtered values. */ @@ -752,6 +752,7 @@ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, + resIndex = 0, result = []; while (++index < length) { @@ -764,15 +765,14 @@ value = baseFlatten(value, isShallow, isStrict); } var valIndex = -1, - valLength = value.length, - resIndex = result.length; + valLength = value.length; result.length += valLength; while (++valIndex < valLength) { result[resIndex++] = value[valIndex]; } } else if (!isStrict) { - result.push(value); + result[resIndex++] = value; } } return result; @@ -1085,7 +1085,7 @@ * and `this` binding. * * @private - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. @@ -1388,7 +1388,7 @@ * @static * @memberOf _ * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example @@ -1934,7 +1934,7 @@ * @memberOf _ * @alias unique * @category Arrays - * @param {Array} array The array to process. + * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" @@ -3541,7 +3541,7 @@ trailing = false; } else if (isObject(options)) { leading = options.leading; - maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0); + maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? options.trailing : trailing; } @@ -3814,9 +3814,9 @@ * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; - * var hi = _.partial(greet, 'hi'); - * hi('fred'); - * // => 'hi fred' + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' */ function partial(func) { return createWrapper(func, PARTIAL_FLAG, null, null, slice(arguments, 1)); @@ -4235,7 +4235,7 @@ /** * Checks if a collection is empty. A value is considered empty unless it is * an array, array-like object, or string with a length greater than `0` or - * an object with own properties. + * an object with own enumerable properties. * * @static * @memberOf _ @@ -4636,13 +4636,8 @@ if (!isObject(object)) { return {}; } - var omitProps = baseFlatten(arguments, true, false, 1), - length = omitProps.length; - - while (length--) { - omitProps[length] = String(omitProps[length]); - } - return basePick(object, baseDifference(keysIn(object), omitProps)); + var omitProps = baseFlatten(arguments, true, false, 1); + return basePick(object, baseDifference(keysIn(object), arrayMap(omitProps, String))); } /** @@ -5058,7 +5053,7 @@ } while (length--) { var key = props[length]; - if (!(hasOwnProperty.call(object, key) && object[key] === source[key])) { + if (!(object[key] === source[key] && hasOwnProperty.call(object, key))) { return false } } diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index e6aaa1f88d..32299960fc 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -6,8 +6,8 @@ ;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(t>>0:0,u=Array(e);++tu(r,i)&&o.push(i)}return o}function g(n,r){var t=-1,e=n?n.length:0;if(typeof e=="number"&&-1o?0:o>>>0);return g(n,function(n){var o=u?r:null!=n&&n[r];i[++e]=o?o.apply(n,t):sr}),i}function j(n,r){var t={};if(typeof r=="function")return b(n,function(n,e,u){r(n,e,u)&&(t[e]=n)}),t;for(var e=-1,u=r.length;++eo(f,c)&&(t&&f.push(c),i.push(a)) }return i}function x(n,r){var t,e=["_"];try{var u=Function(e,"return "+n+(t?"\n/*\n//# sourceURL="+t+"\n*/":"")).apply(sr,r);u.source=n}catch(o){throw o.source=n,o}return u}function T(n,r){return function(t,e,u){var o=r?r():{};e=fr(e,u,3),u=-1;var i=t?t.length:0;if(typeof i=="number"&&-1u&&(u=t);else r=fr(r,t,3),g(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function L(n,r){return z(n,pr(r))}function P(n,r,t,e){var u=3>arguments.length;r=fr(r,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number"&&-1arguments.length;return r=fr(r,e,4),h(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function G(n){var r=-1,t=n&&n.length,e=Array(0>t?0:t>>>0);return g(n,function(n){var t=w(++r);e[r]=e[t],e[t]=n}),e}function H(n,r,t){var e;(typeof r!="function"||typeof t!="undefined")&&(r=fr(r,t,3)),t=-1;var u=n?n.length:0;if(typeof u=="number"&&-1arguments.length?E(n,gr,r):E(n,gr|vr,r,N(arguments,2)) }function K(n,r,t){function e(){var t=r-(dt()-c);0>=t||t>r?(f&&clearTimeout(f),t=s,f=p=s=sr,t&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),f=p=s=sr,(v||h!==r)&&(g=dt(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=dt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p;else{f||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(f&&(f=clearTimeout(f)),g=c,a=n.apply(l,i)):f||(f=setTimeout(u,o))}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,a=n.apply(l,i)),!m||p||f||(i=l=null),a -}var i,f,a,c,l,p,s,g=0,h=false,v=true;if(!rr(n))throw new TypeError(mr);if(r=0>r?0:r,true===t)var y=true,v=false;else tr(t)&&(y=t.leading,h="maxWait"in t&&it(r,+t.maxWait||0),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=sr},o}function Q(n){if(!rr(n))throw new TypeError(mr);return function(){return!n.apply(this,arguments)}}function X(n){if(!n)return n;var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++tr?0:r,true===t)var y=true,v=false;else tr(t)&&(y=t.leading,h="maxWait"in t&&it(+t.maxWait||0,r),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=sr},o}function Q(n){if(!rr(n))throw new TypeError(mr);return function(){return!n.apply(this,arguments)}}function X(n){if(null==n)return n;var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++t"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={}; +}function cr(n){var r=bt(n),t=r.length;return function(e){var u=t;if(u&&null==e)return false;for(;u--;){var o=r[u];if(e[o]!==n[o]||!Xr.call(e,o))return false}return true}}function lr(n){for(var r=-1,t=Z(n),e=t.length;++r"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={}; Mr[Tr]=Mr["[object Array]"]=Mr["[object Float32Array]"]=Mr["[object Float64Array]"]=Mr["[object Int8Array]"]=Mr["[object Int16Array]"]=Mr["[object Int32Array]"]=Mr["[object Uint8Array]"]=Mr["[object Uint8ClampedArray]"]=Mr["[object Uint16Array]"]=Mr["[object Uint32Array]"]=true,Mr["[object ArrayBuffer]"]=Mr[Er]=Mr[kr]=Mr["[object Error]"]=Mr["[object Function]"]=Mr["[object Map]"]=Mr[Or]=Mr[Sr]=Mr[Fr]=Mr["[object Set]"]=Mr[Ir]=Mr["[object WeakMap]"]=false;var Nr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Br={"function":true,object:true},Rr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$r=Br[typeof window]&&window||this,Ur=Br[typeof exports]&&exports&&!exports.nodeType&&exports,Wr=Br[typeof module]&&module&&!module.nodeType&&module,Dr=Ur&&Wr&&typeof global=="object"&&global; !Dr||Dr.global!==Dr&&Dr.window!==Dr&&Dr.self!==Dr||($r=Dr);var zr=Wr&&Wr.exports===Ur&&Ur,Cr=Array.prototype,Lr=Object.prototype,Pr=Function.prototype.toString,Vr=Math.pow(2,53)-1,Gr=$r._,Hr=Lr.toString,Jr=RegExp("^"+(null==Hr?"":(Hr+"").replace(Ar,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Kr=Math.ceil,Qr=Math.floor,Xr=Lr.hasOwnProperty,Yr=Cr.push,Zr=Lr.propertyIsEnumerable,nt=Cr.splice,rt=O(rt=Object.create)&&rt,tt=O(tt=Array.isArray)&&tt,et=$r.isFinite,ut=$r.isNaN,ot=O(ot=Object.keys)&&ot,it=Math.max,ft=Math.min,at=O(at=Date.now)&&at,ct=Math.random; i.prototype=o.prototype;var lt={};!function(){var n={0:1,length:1};lt.spliceObjects=(nt.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},rt||(c=function(){function n(){}return function(r){if(tr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||$r.Object()}}());var pt=M,st=F,gt=T(function(n,r,t){Xr.call(n,t)?n[t]++:n[t]=1}),ht=T(function(n,r,t){Xr.call(n,t)?n[t].push(r):n[t]=[r]}),vt=T(function(n,r,t){n[t]=r @@ -30,10 +30,10 @@ return n=et(n=+n)?n:0,function(){return 1>--n?r.apply(this,arguments):void 0}},o return e}},o.constant=function(n){return function(){return n}},o.countBy=gt,o.debounce=K,o.defaults=Y,o.defer=function(n){if(!rr(n))throw new TypeError(mr);var r=N(arguments,1);return setTimeout(function(){n.apply(sr,r)},1)},o.delay=function(n,r){if(!rr(n))throw new TypeError(mr);var t=N(arguments,2);return setTimeout(function(){n.apply(sr,t)},r)},o.difference=function(){for(var n=-1,r=arguments.length;++nr?0:r)},o.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},o.invert=function(n){for(var r=-1,t=bt(n),e=t.length,u={};++ro?0:o>>>0);for(t=fr(t,e,3),g(n,function(n,r,e){i[++u]={a:t(n,r,e),b:u,c:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].c;return i -},o.tap=function(n,r){return r(n),n},o.throttle=function(n,r,t){var e=true,u=true;if(!rr(n))throw new TypeError(mr);return false===t?e=false:tr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),K(n,r,{leading:e,maxWait:r,trailing:u})},o.times=function(n,r,t){n=0>n?0:n>>>0,r=l(r,t,1),t=-1;for(var e=Array(n);++tr?0:r);++no?0:o>>>0);for(t=fr(t,e,3),g(n,function(n,r,e){i[++u]={a:t(n,r,e),b:u,c:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].c;return i},o.tap=function(n,r){return r(n),n},o.throttle=function(n,r,t){var e=true,u=true; +if(!rr(n))throw new TypeError(mr);return false===t?e=false:tr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),K(n,r,{leading:e,maxWait:r,trailing:u})},o.times=function(n,r,t){n=0>n?0:n>>>0,r=l(r,t,1),t=-1;for(var e=Array(n);++tt?it(e+t,0):ft(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},o.noConflict=function(){return $r._=Gr,this },o.now=dt,o.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Qr(ct()*(r-n+1))},o.reduce=P,o.reduceRight=V,o.result=function(n,r){if(null!=n){var t=n[r];return rr(t)?n[r]():t}},o.size=function(n){var r=n?n.length:0;return typeof r=="number"&&-1 Date: Sun, 15 Jun 2014 14:24:37 -0700 Subject: [PATCH 0781/1608] make `ui.isModularize` set to `true` if coming from lodash-es6. --- test/asset/test-ui.js | 2 +- test/test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asset/test-ui.js b/test/asset/test-ui.js index 5456fd2eea..51ad8e73ad 100644 --- a/test/asset/test-ui.js +++ b/test/asset/test-ui.js @@ -132,7 +132,7 @@ ui.isForeign = RegExp('^(\\w+:)?//').test(build); // used to indicate testing a modularized build - ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|node)|modularize|npm)\b/.test([location.pathname, location.search]); + ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|es6|node)|modularize|npm)\b/.test([location.pathname, location.search]); // used to indicate testing in Sauce Labs' automated test cloud ui.isSauceLabs = location.port == '9001'; diff --git a/test/test.js b/test/test.js index a1a04bf0f4..6e11c676ee 100644 --- a/test/test.js +++ b/test/test.js @@ -67,7 +67,7 @@ var ui = root.ui || (root.ui = { 'buildPath': filePath, 'loaderPath': '', - 'isModularize': /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|node)|modularize|npm)\b/.test(filePath), + 'isModularize': /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|es6|node)|modularize|npm)\b/.test(filePath), 'urlParams': {} }); From e152f549039ebdfd66b319d14c71df46c5e2cd6e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 16:18:07 -0700 Subject: [PATCH 0782/1608] Make tests work with es6 transpiled code. --- test/asset/test-ui.js | 5 ++++- test/backbone.html | 3 +++ test/index.html | 17 +++++++++++------ test/test.js | 26 +++++++++++++++----------- test/underscore.html | 3 +++ 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/test/asset/test-ui.js b/test/asset/test-ui.js index 51ad8e73ad..958364ea94 100644 --- a/test/asset/test-ui.js +++ b/test/asset/test-ui.js @@ -128,11 +128,14 @@ init(); }); + // used to indicate that Lo-Dash is in strict mode + ui.isStrict = /\b(?:lodash-es6|transpiled)\b/.test([location.pathname, location.search]); + // used to indicate testing a foreign file ui.isForeign = RegExp('^(\\w+:)?//').test(build); // used to indicate testing a modularized build - ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|es6|node)|modularize|npm)\b/.test([location.pathname, location.search]); + ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|es6|node)|modularize|npm|transpiled)\b/.test([location.pathname, location.search]); // used to indicate testing in Sauce Labs' automated test cloud ui.isSauceLabs = location.port == '9001'; diff --git a/test/backbone.html b/test/backbone.html index 26c613972b..d8446139e7 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -126,6 +126,9 @@

    Test

    QUnit.config.autostart = false; require(getConfig(), ['underscore', 'backbone'], function(lodash) { + ui.isStrict || (ui.isStrict = 'default' in lodash); + lodash = (lodash['default'] || lodash); + mixinPrereqs(lodash); if (ui.isModularize) { diff --git a/test/index.html b/test/index.html index 210a648c59..5ad3bab353 100644 --- a/test/index.html +++ b/test/index.html @@ -258,6 +258,15 @@ function loadModulesAndTests() { require(getConfig(), ['lodash', 'shimmed', 'underscore'], function(lodash, shimmed, underscore) { + ui.isStrict || (ui.isStrict = 'default' in lodash); + lodash = lodash['default'] || lodash; + + lodashModule = lodash; + lodashModule.moduleName = 'lodash'; + + shimmed = shimmed && (shimmed['default'] || shimmmed); + underscore = underscore && (underscore['default'] || underscore); + if (shimmed && shimmed.noConflict) { shimmedModule = shimmed.noConflict(); shimmedModule.moduleName = 'shimmed'; @@ -266,16 +275,12 @@ underscoreModule = underscore.noConflict(); underscoreModule.moduleName = 'underscore'; } - if (lodash) { - lodashModule = lodash; - lodashModule.moduleName = 'lodash'; - } if (ui.isModularize) { window._ = lodash; } if (ui.isModularize) { require(getConfig(), ['lodash/internals/baseEach'], function(baseEach) { - lodash._baseEach = baseEach; + lodash._baseEach = baseEach['default'] || baseEach; loadTests(); }); } else { @@ -289,7 +294,7 @@ if (window.requirejs) { addBizarroMethods(); require(getConfig(), ['lodash'], function(lodash) { - lodashBizarro = lodash.noConflict(); + lodashBizarro = (lodash['default'] || lodash).noConflict(); delete requirejs.s.contexts._; removeBizarroMethods(); diff --git a/test/test.js b/test/test.js index 6e11c676ee..be38863662 100644 --- a/test/test.js +++ b/test/test.js @@ -67,7 +67,8 @@ var ui = root.ui || (root.ui = { 'buildPath': filePath, 'loaderPath': '', - 'isModularize': /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|es6|node)|modularize|npm)\b/.test(filePath), + 'isModularize': /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|es6|node)|modularize|npm|transpiled)\b/.test(filePath), + 'isStrict': /\b(?:lodash-es6|transpiled)\b/.test(filePath), 'urlParams': {} }); @@ -83,12 +84,15 @@ /** Detect if testing `npm` modules */ var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]); - /** Detects if running in PhantomJS */ + /** Detect if running in PhantomJS */ var isPhantom = phantom || typeof callPhantom == 'function'; /** Detect if running in Rhino */ var isRhino = isJava && typeof global == 'function' && global().Array === root.Array; + /** Detect if Lo-Dash is in strict mode */ + var isStrict = ui.isStrict; + /** Used to test Web Workers */ var Worker = !(ui.isForeign || isModularize) && document && root.Worker; @@ -170,7 +174,7 @@ /** The `lodash` function to test */ var _ = root._ || (root._ = ( _ = load(filePath) || root._, - _ = _._ || _, + _ = _._ || (isStrict = ui.isStrict = isStrict || 'default' in _, _['default']) || _, (_.runInContext ? _.runInContext(root) : _) )); @@ -322,7 +326,7 @@ var path = require('path'), baseEach = require(path.join(path.dirname(filePath), 'internals', 'baseEach.js')); - _._baseEach = baseEach.baseEach || baseEach; + _._baseEach = baseEach.baseEach || baseEach['default'] || baseEach; } // allow bypassing native checks var _fnToString = Function.prototype.toString; @@ -380,7 +384,7 @@ emptyObject(require.cache); // load Lo-Dash and expose it to the bad extensions/shims - lodashBizarro = (lodashBizarro = require(filePath))._ || lodashBizarro; + lodashBizarro = (lodashBizarro = require(filePath))._ || lodashBizarro['default'] || lodashBizarro; // restore native methods setProperty(Array, 'isArray', _isArray); @@ -2645,9 +2649,9 @@ _.each(['assign', 'bindAll', 'defaults'], function(methodName) { var func = _[methodName]; - test('`_.' + methodName + '` should not throw strict mode errors', 1, function() { + test('`_.' + methodName + '` should ' + (isStrict ? '' : 'not ') + 'throw strict mode errors', 1, function() { var object = { 'a': null, 'b': function(){} }, - pass = true; + pass = !isStrict; if (freeze) { freeze(object); @@ -2658,7 +2662,7 @@ func(object, { 'a': 1 }); } } catch(e) { - pass = false; + pass = !pass; } ok(pass); } @@ -5726,7 +5730,7 @@ }); test('`_.' + methodName + '` should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantom) { + if (!(isPhantom || isStrict)) { var actual = func(args); deepEqual(actual.sort(), ['0', '1', '2']); } else { @@ -5735,7 +5739,7 @@ }); test('`_.' + methodName + '` should custom properties on `arguments` objects', 1, function() { - if (!isPhantom) { + if (!(isPhantom || isStrict)) { args.a = 1; var actual = func(args); @@ -5747,7 +5751,7 @@ }); test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of `arguments` objects', 1, function() { - if (!isPhantom) { + if (!(isPhantom || isStrict)) { Object.prototype.a = 1; var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a'], actual = func(args); diff --git a/test/underscore.html b/test/underscore.html index 2f4905fc62..6fd4805c38 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -234,6 +234,9 @@ QUnit.config.autostart = false; require(getConfig(), [moduleId], function(lodash) { + ui.isStrict || (ui.isStrict = 'default' in lodash); + lodash = (lodash['default'] || lodash); + if (ui.isModularize) { window._ = lodash; } From 1c770a3c66ef317eb6162fa121f6a46c3226d67f Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 17:07:51 -0700 Subject: [PATCH 0783/1608] Drop testing Node 0.6. and bump in name only to v3.0.0-pre. --- .travis.yml | 1 - LICENSE.txt | 4 ++-- README.md | 4 ++-- bower.json | 2 +- component.json | 2 +- dist/lodash.compat.js | 4 ++-- dist/lodash.compat.min.js | 4 ++-- dist/lodash.js | 4 ++-- dist/lodash.min.js | 4 ++-- dist/lodash.underscore.js | 4 ++-- dist/lodash.underscore.min.js | 6 +++--- doc/README.md | 2 +- lodash.js | 4 ++-- package.json | 2 +- 14 files changed, 23 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e25e67b6e..f2c00c550f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: - - "0.6" - "0.8" - "0.10" env: diff --git a/LICENSE.txt b/LICENSE.txt index e23f4fbb37..a11898326f 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,5 @@ Copyright 2012-2014 The Dojo Foundation -Based on Underscore.js 1.5.2, copyright 2009-2014 Jeremy Ashkenas, +Based on Underscore.js 1.6.0, copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Permission is hereby granted, free of charge, to any person obtaining @@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 092e1f5873..faeeac3067 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Lo-Dash v2.5.0-pre +# Lo-Dash v3.0.0-pre A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). ## Documentation @@ -115,7 +115,7 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# ## Support -Tested in Chrome (19, 34-35), Firefox (3, 20, 29-30), IE 6-11, Opera 21-22, Safari 5-7, Node.js 0.6.21~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 34-35), Firefox (3, 20, 29-30), IE 6-11, Opera 21-22, Safari 5-7, Node.js 0.8.26~0.10.28, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. diff --git a/bower.json b/bower.json index acfca13cfc..046a7ae037 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "2.5.0-pre", + "version": "3.0.0-pre", "main": "dist/lodash.compat.js", "ignore": [ ".*", diff --git a/component.json b/component.json index 291094d09f..7fbe9dc91b 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "lodash", "repo": "lodash/lodash", - "version": "2.5.0-pre", + "version": "3.0.0-pre", "description": "A utility library delivering consistency, customization, performance, & extras.", "license": "MIT", "main": "dist/lodash.compat.js", diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 5827ddf8e0..30d2abe717 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre (Custom Build) + * Lo-Dash 3.0.0-pre (Custom Build) * Build: `lodash -o ./dist/lodash.compat.js` * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 @@ -21,7 +21,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.5.0-pre'; + var version = '3.0.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index d3f251cd4c..516d22966e 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE + * Lo-Dash 3.0.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ ;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(nn.indexOf(";")?n:n.replace(F,y))},q.uniqueId=function(n){var t=++E;return se(null==n?"":n)+t},q.all=Cr,q.any=Lr,q.detect=kr,q.foldl=Ur,q.foldr=Fr,q.include=Ar,q.inject=Ur,te(q,function(){var n={};return zt(q,function(t,r){q.prototype[r]||(n[r]=t) }),n}(),false),q.first=pr,q.last=vr,q.sample=function(n,t,r){return n&&typeof n.length!="number"?n=Jr(n):He.unindexedChars&&Kr(n)&&(n=n.split("")),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=pr,q.takeRight=vr,q.takeRightWhile=vr,q.takeWhile=pr,q.head=pr,zt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o}) }),q.VERSION=x,q.prototype.chain=function(){return this.__chain__=true,this},q.prototype.toJSON=jr,q.prototype.toString=function(){return se(this.__wrapped__)},q.prototype.value=jr,q.prototype.valueOf=jr,jt(["join","pop","shift"],function(n){var t=he[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),jt(["push","reverse","sort","unshift"],function(n){var t=he[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),jt(["concat","splice"],function(n){var t=he[n]; -q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),He.spliceObjects||jt(["pop","shift","splice"],function(n){var t=he[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,A=16,C=32,x="2.5.0-pre",k="__lodash@"+x+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,S=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,L=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",ht="[object Int32Array]",gt="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; +q.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),He.spliceObjects||jt(["pop","shift","splice"],function(n){var t=he[n],r="splice"==n;q.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new J(u,n):u}}),q}var m,b=1,_=2,w=4,j=8,A=16,C=32,x="3.0.0-pre",k="__lodash@"+x+"__",O="Expected a function",E=0,I=/^[A-Z]+$/,S=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,F=/&(?:amp|lt|gt|quot|#39|#96);/g,N=/[&<>"'`]/g,L=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,K=/\bthis\b/,V=/['\n\r\u2028\u2029\\]/g,J=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",Y="Array ArrayBuffer Boolean Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),G="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),H="[object Arguments]",Q="[object Array]",nt="[object Boolean]",tt="[object Date]",rt="[object Error]",et="[object Function]",ut="[object Number]",ot="[object Object]",at="[object RegExp]",it="[object String]",lt="[object ArrayBuffer]",ft="[object Float32Array]",ct="[object Float64Array]",st="[object Int8Array]",pt="[object Int16Array]",ht="[object Int32Array]",gt="[object Uint8Array]",vt="[object Uint8ClampedArray]",yt="[object Uint16Array]",dt="[object Uint32Array]",mt={}; mt[H]=mt[Q]=mt[ft]=mt[ct]=mt[st]=mt[pt]=mt[ht]=mt[gt]=mt[vt]=mt[yt]=mt[dt]=true,mt[lt]=mt[nt]=mt[tt]=mt[rt]=mt[et]=mt["[object Map]"]=mt[ut]=mt[ot]=mt[at]=mt["[object Set]"]=mt[it]=mt["[object WeakMap]"]=false;var bt={};bt[H]=bt[Q]=bt[lt]=bt[nt]=bt[tt]=bt[ft]=bt[ct]=bt[st]=bt[pt]=bt[ht]=bt[ut]=bt[ot]=bt[at]=bt[it]=bt[gt]=bt[vt]=bt[yt]=bt[dt]=true,bt[rt]=bt[et]=bt["[object Map]"]=bt["[object Set]"]=bt["[object WeakMap]"]=false;var _t={leading:false,maxWait:0,trailing:false},wt={configurable:false,enumerable:false,value:null,writable:false},jt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},At={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ct={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},xt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ot=xt[typeof window]&&window||this,Et=xt[typeof exports]&&exports&&!exports.nodeType&&exports,xt=xt[typeof module]&&module&&!module.nodeType&&module,It=Et&&xt&&typeof global=="object"&&global; !It||It.global!==It&&It.window!==It&&It.self!==It||(Ot=It);var It=xt&&xt.exports===Et&&Et,St=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ot._=St, define(function(){return St})):Et&&xt?It?(xt.exports=St)._=St:Et._=St:Ot._=St}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index f73ae96e2d..fb86bf6bbe 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre (Custom Build) + * Lo-Dash 3.0.0-pre (Custom Build) * Build: `lodash modern -o ./dist/lodash.js` * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 @@ -21,7 +21,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.5.0-pre'; + var version = '3.0.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 0e34b905d5..61bc136218 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE + * Lo-Dash 3.0.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ ;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(nn.indexOf(";")?n:n.replace(S,v))},q.uniqueId=function(n){var t=++O;return ie(null==n?"":n)+t},q.all=wr,q.any=Sr,q.detect=Ar,q.foldl=Er,q.foldr=Rr,q.include=_r,q.inject=Er,Hr(q,function(){var n={};return Bt(q,function(t,r){q.prototype[r]||(n[r]=t) }),n}(),false),q.first=lr,q.last=sr,q.sample=function(n,t,r){return n&&typeof n.length!="number"&&(n=Pr(n)),null==t||r?(t=n?n.length:0,0t?0:+t||0,n.length),n)},q.take=lr,q.takeRight=sr,q.takeRightWhile=sr,q.takeWhile=lr,q.head=lr,Bt(q,function(n,t){var r="sample"!=t;q.prototype[t]||(q.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o})}),q.VERSION=k,q.prototype.chain=function(){return this.__chain__=true,this },q.prototype.toJSON=dr,q.prototype.toString=function(){return ie(this.__wrapped__)},q.prototype.value=dr,q.prototype.valueOf=dr,dt(["join","pop","shift"],function(n){var t=le[n];q.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),dt(["push","reverse","sort","unshift"],function(n){var t=le[n];q.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),dt(["concat","splice"],function(n){var t=le[n];q.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__) -}}),q}var m,b=1,d=2,_=4,w=8,j=16,A=32,k="2.5.0-pre",x="__lodash@"+k+"__",C="Expected a function",O=0,I=/^[A-Z]+$/,E=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39|#96);/g,U=/[&<>"'`]/g,N=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",rt="[object Object]",et="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; +}}),q}var m,b=1,d=2,_=4,w=8,j=16,A=32,k="3.0.0-pre",x="__lodash@"+k+"__",C="Expected a function",O=0,I=/^[A-Z]+$/,E=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,F=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39|#96);/g,U=/[&<>"'`]/g,N=/<%-([\s\S]+?)%>/g,T=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,$=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,D=/^0[xX]/,z=/^\[object .+?Constructor\]$/,q=/[\xC0-\xFF]/g,M=/($^)/,Z=/[.*+?^${}()|[\]\/\\]/g,P=/\bthis\b/,K=/['\n\r\u2028\u2029\\]/g,V=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,J=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",X="Array ArrayBuffer Boolean Date Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),Y="[object Arguments]",G="[object Array]",H="[object Boolean]",Q="[object Date]",nt="[object Error]",tt="[object Number]",rt="[object Object]",et="[object RegExp]",ut="[object String]",ot="[object ArrayBuffer]",at="[object Float32Array]",it="[object Float64Array]",ft="[object Int8Array]",lt="[object Int16Array]",ct="[object Int32Array]",pt="[object Uint8Array]",st="[object Uint8ClampedArray]",ht="[object Uint16Array]",gt="[object Uint32Array]",vt={}; vt[Y]=vt[G]=vt[at]=vt[it]=vt[ft]=vt[lt]=vt[ct]=vt[pt]=vt[st]=vt[ht]=vt[gt]=true,vt[ot]=vt[H]=vt[Q]=vt[nt]=vt["[object Function]"]=vt["[object Map]"]=vt[tt]=vt[rt]=vt[et]=vt["[object Set]"]=vt[ut]=vt["[object WeakMap]"]=false;var yt={};yt[Y]=yt[G]=yt[ot]=yt[H]=yt[Q]=yt[at]=yt[it]=yt[ft]=yt[lt]=yt[ct]=yt[tt]=yt[rt]=yt[et]=yt[ut]=yt[pt]=yt[st]=yt[ht]=yt[gt]=true,yt[nt]=yt["[object Function]"]=yt["[object Map]"]=yt["[object Set]"]=yt["[object WeakMap]"]=false;var mt={leading:false,maxWait:0,trailing:false},bt={configurable:false,enumerable:false,value:null,writable:false},dt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},_t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},wt={\u00c0:"A",\u00c1:"A",\u00c2:"A",\u00c3:"A",\u00c4:"A",\u00c5:"A",\u00e0:"a",\u00e1:"a",\u00e2:"a",\u00e3:"a",\u00e4:"a",\u00e5:"a",\u00c7:"C",\u00e7:"c",\u00d0:"D",\u00f0:"d",\u00c8:"E",\u00c9:"E",\u00ca:"E",\u00cb:"E",\u00e8:"e",\u00e9:"e",\u00ea:"e",\u00eb:"e",\u00cc:"I",\u00cd:"I",\u00ce:"I",\u00cf:"I",\u00ec:"i",\u00ed:"i",\u00ee:"i",\u00ef:"i",\u00d1:"N",\u00f1:"n",\u00d2:"O",\u00d3:"O",\u00d4:"O",\u00d5:"O",\u00d6:"O",\u00d8:"O",\u00f2:"o",\u00f3:"o",\u00f4:"o",\u00f5:"o",\u00f6:"o",\u00f8:"o",\u00d9:"U",\u00da:"U",\u00db:"U",\u00dc:"U",\u00f9:"u",\u00fa:"u",\u00fb:"u",\u00fc:"u",\u00dd:"Y",\u00fd:"y",\u00ff:"y",\u00c6:"AE",\u00e6:"ae",\u00de:"Th",\u00fe:"th",\u00df:"ss","\xd7":" ","\xf7":" "},jt={"function":true,object:true},At={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},kt=jt[typeof window]&&window||this,xt=jt[typeof exports]&&exports&&!exports.nodeType&&exports,jt=jt[typeof module]&&module&&!module.nodeType&&module,Ct=xt&&jt&&typeof global=="object"&&global; !Ct||Ct.global!==Ct&&Ct.window!==Ct&&Ct.self!==Ct||(kt=Ct);var Ct=jt&&jt.exports===xt&&xt,Ot=y();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(kt._=Ot, define(function(){return Ot})):xt&&jt?Ct?(jt.exports=Ot)._=Ot:xt._=Ot:kt._=Ot}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 452965c156..a2155139f3 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre (Custom Build) + * Lo-Dash 3.0.0-pre (Custom Build) * Build: `lodash underscore -o ./dist/lodash.underscore.js` * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 @@ -21,7 +21,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.5.0-pre'; + var version = '3.0.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index 32299960fc..21630fa37f 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE + * Lo-Dash 3.0.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash underscore -o ./dist/lodash.underscore.js` */ ;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(tr?0:r,true===t)var y=true,v=false;else tr(t)&&(y=t.leading,h="maxWait"in t&&it(+t.maxWait||0,r),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=sr},o}function Q(n){if(!rr(n))throw new TypeError(mr);return function(){return!n.apply(this,arguments)}}function X(n){if(null==n)return n;var r=arguments,t=0,e=r.length,u=typeof r[2];for("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2);++t"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={}; +}function cr(n){var r=bt(n),t=r.length;return function(e){var u=t;if(u&&null==e)return false;for(;u--;){var o=r[u];if(e[o]!==n[o]||!Xr.call(e,o))return false}return true}}function lr(n){for(var r=-1,t=Z(n),e=t.length;++r"'`]/g,jr=/^\[object .+?Constructor\]$/,wr=/($^)/,Ar=/[.*+?^${}()|[\]\/\\]/g,xr=/['\n\r\u2028\u2029\\]/g,Tr="[object Arguments]",Er="[object Boolean]",kr="[object Date]",Or="[object Number]",Sr="[object Object]",Fr="[object RegExp]",Ir="[object String]",Mr={}; Mr[Tr]=Mr["[object Array]"]=Mr["[object Float32Array]"]=Mr["[object Float64Array]"]=Mr["[object Int8Array]"]=Mr["[object Int16Array]"]=Mr["[object Int32Array]"]=Mr["[object Uint8Array]"]=Mr["[object Uint8ClampedArray]"]=Mr["[object Uint16Array]"]=Mr["[object Uint32Array]"]=true,Mr["[object ArrayBuffer]"]=Mr[Er]=Mr[kr]=Mr["[object Error]"]=Mr["[object Function]"]=Mr["[object Map]"]=Mr[Or]=Mr[Sr]=Mr[Fr]=Mr["[object Set]"]=Mr[Ir]=Mr["[object WeakMap]"]=false;var Nr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},qr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Br={"function":true,object:true},Rr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$r=Br[typeof window]&&window||this,Ur=Br[typeof exports]&&exports&&!exports.nodeType&&exports,Wr=Br[typeof module]&&module&&!module.nodeType&&module,Dr=Ur&&Wr&&typeof global=="object"&&global; !Dr||Dr.global!==Dr&&Dr.window!==Dr&&Dr.self!==Dr||($r=Dr);var zr=Wr&&Wr.exports===Ur&&Ur,Cr=Array.prototype,Lr=Object.prototype,Pr=Function.prototype.toString,Vr=Math.pow(2,53)-1,Gr=$r._,Hr=Lr.toString,Jr=RegExp("^"+(null==Hr?"":(Hr+"").replace(Ar,"\\$&")).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Kr=Math.ceil,Qr=Math.floor,Xr=Lr.hasOwnProperty,Yr=Cr.push,Zr=Lr.propertyIsEnumerable,nt=Cr.splice,rt=O(rt=Object.create)&&rt,tt=O(tt=Array.isArray)&&tt,et=$r.isFinite,ut=$r.isNaN,ot=O(ot=Object.keys)&&ot,it=Math.max,ft=Math.min,at=O(at=Date.now)&&at,ct=Math.random; i.prototype=o.prototype;var lt={};!function(){var n={0:1,length:1};lt.spliceObjects=(nt.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},rt||(c=function(){function n(){}return function(r){if(tr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||$r.Object()}}());var pt=M,st=F,gt=T(function(n,r,t){Xr.call(n,t)?n[t]++:n[t]=1}),ht=T(function(n,r,t){Xr.call(n,t)?n[t].push(r):n[t]=[r]}),vt=T(function(n,r,t){n[t]=r @@ -38,5 +38,5 @@ if(!rr(n))throw new TypeError(mr);return false===t?e=false:tr(t)&&(e="leading"in return true},o.isEqual=function(n,r){return d(n,r)},o.isFinite=function(n){return et(n)&&!ut(parseFloat(n))},o.isFunction=rr,o.isNaN=function(n){return er(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=er,o.isObject=tr,o.isRegExp=function(n){return tr(n)&&Hr.call(n)==Fr||false},o.isString=ur,o.isUndefined=function(n){return typeof n=="undefined"},o.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?it(e+t,0):ft(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},o.noConflict=function(){return $r._=Gr,this },o.now=dt,o.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Qr(ct()*(r-n+1))},o.reduce=P,o.reduceRight=V,o.result=function(n,r){if(null!=n){var t=n[r];return rr(t)?n[r]():t}},o.size=function(n){var r=n?n.length:0;return typeof r=="number"&&-1n.indexOf(";")?n:n.replace(dr,u))},o.uniqueId=function(n){var r=++br+"";return n?n+r:r},o.all=$,o.any=H,o.detect=W,o.foldl=P,o.foldr=V,o.include=R,o.inject=P,o.first=F,o.last=function(n,r,t){var e=n?n.length:0;return null==r||t?n?n[e-1]:sr:(r=e-(r||0),N(n,0>r?0:r)) -},o.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=ir(n)),null==r||t?(r=n?n.length:0,0r?0:+r||0,n.length),n)},o.take=st,o.head=F,lr(function(n,r,t){for(var e=-1,u=bt(r),o=u.length;++er?0:+r||0,n.length),n)},o.take=st,o.head=F,lr(function(n,r,t){for(var e=-1,u=bt(r),o=u.length;++eLo-Dash v2.5.0-pre +# Lo-Dash v3.0.0-pre diff --git a/lodash.js b/lodash.js index 355cea392a..e4e3ac30ba 100644 --- a/lodash.js +++ b/lodash.js @@ -1,6 +1,6 @@ /** * @license - * Lo-Dash 2.5.0-pre + * Lo-Dash 3.0.0-pre * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.6.0 * Copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors @@ -20,7 +20,7 @@ PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ - var version = '2.5.0-pre'; + var version = '3.0.0-pre'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; diff --git a/package.json b/package.json index fc76501378..e6941fdb20 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "2.5.0-pre", + "version": "3.0.0-pre", "description": "A utility library delivering consistency, customization, performance, & extras.", "homepage": "http://lodash.com/", "license": "MIT", From 4fd1eae84fec005c2cc1f5c9c595a7112004657c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 18:32:16 -0700 Subject: [PATCH 0784/1608] Fix typo to fix AMD tests. --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 5ad3bab353..a75d8c84ea 100644 --- a/test/index.html +++ b/test/index.html @@ -264,7 +264,7 @@ lodashModule = lodash; lodashModule.moduleName = 'lodash'; - shimmed = shimmed && (shimmed['default'] || shimmmed); + shimmed = shimmed && (shimmed['default'] || shimmed); underscore = underscore && (underscore['default'] || underscore); if (shimmed && shimmed.noConflict) { From fcf29f357db651b7fb3f5d07a69a082e959742f8 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 23:18:13 -0700 Subject: [PATCH 0785/1608] Minor readme nit. [ci skip] --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index faeeac3067..19ba8e9ed4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # Lo-Dash v3.0.0-pre + A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). ## Documentation + * [API Documentation](http://lodash.com/docs) * [DevDocs – *a searchable interface for our documentation*](http://devdocs.io/lodash/) @@ -26,7 +28,7 @@ Check out our [unit tests](http://lodash.com/tests), [benchmarks](http://lodash. ## Installation -In browsers: +In a browser: ```html From cc7b413a2a68173f1b549bb4fc3ce6573f8bdf4d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 15 Jun 2014 23:18:28 -0700 Subject: [PATCH 0786/1608] Update request in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f2c00c550f..5400852046 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ branches: - master before_install: - "mkdir ~/.npm" - - "[ $SAUCE_LABS == false ] || npm i chalk@\"^0.4.0\" ecstatic@\"^0.5.0\" request@\"^2.34.0\" sauce-tunnel@\"^2.0.0\"" + - "[ $SAUCE_LABS == false ] || npm i chalk@\"^0.4.0\" ecstatic@\"^0.5.0\" request@\"^2.36.0\" sauce-tunnel@\"^2.0.0\"" - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.10.0\" && npm i istanbul@\"^0.2.0\")" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7R5 && sudo wget -O /opt/rhino-1.7R5/js.jar http://lodash.com/_travis/rhino-1.7R5.jar)" - "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7R5/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)" From 4f9da35b7691aad9d540e436161b34058a098f2e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 16 Jun 2014 09:07:47 -0700 Subject: [PATCH 0787/1608] Make `_.max` and `_.min` return unwrapped values when chaining. --- lodash.js | 4 ++-- test/test.js | 31 ++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lodash.js b/lodash.js index e4e3ac30ba..2767a07a0a 100644 --- a/lodash.js +++ b/lodash.js @@ -8677,10 +8677,8 @@ lodash.map = map; lodash.mapValues = mapValues; lodash.matches = matches; - lodash.max = max; lodash.memoize = memoize; lodash.merge = merge; - lodash.min = min; lodash.mixin = mixin; lodash.negate = negate; lodash.omit = omit; @@ -8775,6 +8773,8 @@ lodash.isUndefined = isUndefined; lodash.kebabCase = kebabCase; lodash.lastIndexOf = lastIndexOf; + lodash.max = max; + lodash.min = min; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; diff --git a/test/test.js b/test/test.js index be38863662..d305fc2887 100644 --- a/test/test.js +++ b/test/test.js @@ -3201,11 +3201,6 @@ 'some' ]; - var boolMethods = [ - 'every', - 'some' - ]; - var collectionMethods = [ 'countBy', 'every', @@ -3253,6 +3248,13 @@ 'forOwnRight' ]; + var unwrappedMethods = [ + 'every', + 'max', + 'min', + 'some' + ]; + _.each(methods, function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -3289,7 +3291,7 @@ }); }); - _.each(_.difference(methods, boolMethods), function(methodName) { + _.each(_.difference(methods, unwrappedMethods), function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -3304,6 +3306,21 @@ }); }); + _.each(unwrappedMethods, function(methodName) { + var array = [1, 2, 3], + func = _[methodName]; + + test('`_.' + methodName + '` should return an unwrapped value when chaining', 1, function() { + if (!isNpm) { + var actual = _(array)[methodName](_.noop); + ok(!(actual instanceof _)); + } + else { + skipTest(); + } + }); + }); + _.each(_.difference(methods, forInMethods), function(methodName) { var array = [1, 2, 3], func = _[methodName]; @@ -6620,7 +6637,7 @@ test('`_.' + methodName + '` should work when chaining on an array with only one value', 1, function() { if (!isNpm) { - var actual = _([40])[methodName]().value(); + var actual = _([40])[methodName](); strictEqual(actual, 40); } else { From 73f6fd49d015d92b6d0172f6e3173d37c6ba6e7e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 16 Jun 2014 12:27:21 -0700 Subject: [PATCH 0788/1608] Align `_.keys` with ES6 and coerce primitives to objects. --- dist/lodash.js | 17 +++++++++-------- lodash.js | 13 +++++++------ test/test.js | 11 ++++++++--- test/underscore.html | 3 ++- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/dist/lodash.js b/dist/lodash.js index fb86bf6bbe..b22b4304df 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -6799,14 +6799,16 @@ * // => ['x', 'y'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object && object.constructor, - length = object ? object.length : 0; + object = Object(object); + + var Ctor = object.constructor, + length = object.length; if ((Ctor && object === Ctor.prototype) || (typeof length == 'number' && length > 0)) { return shimKeys(object); } - return isObject(object) ? nativeKeys(object) : []; + return nativeKeys(object); }; /** @@ -6830,9 +6832,8 @@ * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) */ function keysIn(object) { - if (!isObject(object)) { - return []; - } + object = Object(object); + var length = object.length; length = (typeof length == 'number' && length > 0 && (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) >>> 0; @@ -8461,10 +8462,8 @@ lodash.map = map; lodash.mapValues = mapValues; lodash.matches = matches; - lodash.max = max; lodash.memoize = memoize; lodash.merge = merge; - lodash.min = min; lodash.mixin = mixin; lodash.negate = negate; lodash.omit = omit; @@ -8559,6 +8558,8 @@ lodash.isUndefined = isUndefined; lodash.kebabCase = kebabCase; lodash.lastIndexOf = lastIndexOf; + lodash.max = max; + lodash.min = min; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; diff --git a/lodash.js b/lodash.js index 2767a07a0a..54690fce6e 100644 --- a/lodash.js +++ b/lodash.js @@ -6990,15 +6990,17 @@ * // => ['x', 'y'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object && object.constructor, - length = object ? object.length : 0; + object = Object(object); + + var Ctor = object.constructor, + length = object.length; if ((Ctor && object === Ctor.prototype) || (typeof length == 'number' && length > 0) || (support.enumPrototypes && typeof object == 'function')) { return shimKeys(object); } - return isObject(object) ? nativeKeys(object) : []; + return nativeKeys(object); }; /** @@ -7022,9 +7024,8 @@ * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) */ function keysIn(object) { - if (!isObject(object)) { - return []; - } + object = Object(object); + var length = object.length; length = (typeof length == 'number' && length > 0 && (isArray(object) || (support.nonEnumStrings && isString(object)) || diff --git a/test/test.js b/test/test.js index d305fc2887..68a5195dd0 100644 --- a/test/test.js +++ b/test/test.js @@ -5721,6 +5721,11 @@ deepEqual(actual.sort(), ['a', 'b']); }); + test('`_.' + methodName + '` should coerce primitives to objects', 1, function() { + var actual = func('abc'); + deepEqual(actual.sort(), ['0', '1', '2']); + }); + test('`_.' + methodName + '` should treat sparse arrays as dense', 1, function() { var array = [1]; array[2] = 3; @@ -5729,7 +5734,7 @@ deepEqual(actual.sort(), ['0', '1', '2']); }); - test('`_.' + methodName + '` should custom properties on arrays', 1, function() { + test('`_.' + methodName + '` should return keys for custom properties on arrays', 1, function() { var array = [1]; array.a = 1; @@ -5755,7 +5760,7 @@ } }); - test('`_.' + methodName + '` should custom properties on `arguments` objects', 1, function() { + test('`_.' + methodName + '` should return keys for custom properties on `arguments` objects', 1, function() { if (!(isPhantom || isStrict)) { args.a = 1; var actual = func(args); @@ -5785,7 +5790,7 @@ deepEqual(actual.sort(), ['0', '1', '2']); }); - test('`_.' + methodName + '` should custom properties on string objects', 1, function() { + test('`_.' + methodName + '` should return keys for custom properties on string objects', 1, function() { var object = Object('a'); object.a = 1; diff --git a/test/underscore.html b/test/underscore.html index 6fd4805c38..73f147b25d 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -110,7 +110,8 @@ 'Died on test #63' ], 'keys': [ - 'is not fooled by sparse arrays; see issue #95' + 'is not fooled by sparse arrays; see issue #95', + '[]' ], 'omit': [ 'can accept a predicate' From 62e84e73ae76d575adc73f1a2e656300aeeabba0 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 17 Jun 2014 00:08:33 -0700 Subject: [PATCH 0789/1608] Add `_.clone` and `_.flatten` tests. --- test/test.js | 113 ++++++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 77 deletions(-) diff --git a/test/test.js b/test/test.js index 68a5195dd0..0b37bf7bcd 100644 --- a/test/test.js +++ b/test/test.js @@ -1276,7 +1276,7 @@ objects['arrays'].length = 3; - test('`_.clone` should shallow clone by default', 2, function() { + test('`_.clone` should perform a shallow clone', 2, function() { var expected = [{ 'a': 0 }, { 'b': 1 }], actual = _.clone(expected); @@ -1284,6 +1284,14 @@ ok(actual !== expected && actual[0] === expected[0]); }); + test('`_.clone` should work with `isDeep`', 2, function() { + var expected = [{ 'a': 0 }, { 'b': 1 }], + actual = _.clone(expected, true); + + deepEqual(actual, expected); + ok(actual !== expected && actual[0] !== expected[0]); + }); + test('`_.cloneDeep` should deep clone objects with circular references', 1, function() { var object = { 'foo': { 'b': { 'foo': { 'c': { } } } }, @@ -2987,72 +2995,37 @@ QUnit.module('lodash.flatten'); (function() { - var args = arguments, - array = [{ 'a': [1, [2]] }, { 'a': [3] }]; - - test('should flatten `arguments` objects', 1, function() { - var actual = _.flatten([args, args]); - deepEqual(actual, [1, 2, 3, 1, 2, 3]); - }); - - test('should work with a callback', 1, function() { - var actual = _.flatten(array, function(object) { - return object.a; - }); - - deepEqual(actual, [1, 2, 3]); - }); - - test('should work with `isShallow` and `callback`', 1, function() { - var actual = _.flatten(array, true, function(object) { - return object.a; - }); - - deepEqual(actual, [1, [2], 3]); - }); - - test('should pass the correct `callback` arguments', 1, function() { - var args; - - _.flatten(array, function() { - args || (args = slice.call(arguments)); - }); + var args = arguments; - deepEqual(args, [array[0], 0, array]); + test('should perform a shallow flatten', 1, function() { + var array = [[['a']], [['b']]]; + deepEqual(_.flatten(array), [['a'], ['b']]); }); - test('should support the `thisArg` argument', 1, function() { - var actual = _.flatten(array, function(object, index) { - return this[index].a; - }, array); - - deepEqual(actual, [1, 2, 3]); + test('should work with `isDeep`', 1, function() { + var array = [[['a']], [['b']]]; + deepEqual(_.flatten(array, true), ['a', 'b']); }); - test('should work with a string for `callback`', 1, function() { - deepEqual(_.flatten(array, 'a'), [1, 2, 3]); + test('should flatten `arguments` objects', 1, function() { + deepEqual(_.flatten([args, args]), [1, 2, 3, 1, 2, 3]); }); - test('should perform a deep flatten when used as a callback for `_.map`', 1, function() { - var array = [[[['a']]], [[['b']]]], - actual = _.map(array, _.flatten); - - deepEqual(actual, [['a'], ['b']]); + test('should perform a shallow flatten when used as a callback for `_.map`', 1, function() { + var array = [[['a']], [['b']]]; + deepEqual(_.map(array, _.flatten), [['a'], ['b']]); }); test('should treat sparse arrays as dense', 4, function() { var array = [[1, 2, 3], Array(3)], - expected = [1, 2, 3], - actual1 = _.flatten(array), - actual2 = _.flatten(array, true); + expected = [1, 2, 3]; expected.push(undefined, undefined, undefined); - deepEqual(actual1, expected); - ok('4' in actual1); - - deepEqual(actual2, expected); - ok('4' in actual2); + _.each([_.flatten(array), _.flatten(array, true)], function(actual) { + deepEqual(actual, expected); + ok('4' in actual); + }); }); test('should work with extremely large arrays', 1, function() { @@ -3071,35 +3044,22 @@ } }); - test('should work with empty arrays', 1, function() { - var actual = _.flatten([[], [[]], [[], [[[]]]]]); - deepEqual(actual, []); - }); + test('should work with empty arrays', 2, function() { + var array = [[], [[]], [[], [[[]]]]]; - test('should flatten nested arrays', 1, function() { - var array = [1, [2], [3, [[4]]]], - expected = [1, 2, 3, 4]; - - deepEqual(_.flatten(array), expected); + deepEqual(_.flatten(array), [[], [], [[[]]]]); + deepEqual(_.flatten(array, true), []); }); - test('should support shallow flattening nested arrays', 1, function() { - var array = [1, [2], [3, [4]]], - expected = [1, 2, 3, [4]]; + test('should support flattening of nested arrays', 2, function() { + var array = [1, [2], [3, [4]]]; - deepEqual(_.flatten(array, true), expected); - }); - - test('should support shallow flattening arrays of other arrays', 1, function() { - var array = [[1], [2], [3], [[4]]], - expected = [1, 2, 3, [4]]; - - deepEqual(_.flatten(array, true), expected); + deepEqual(_.flatten(array), [1, 2, 3, [4]]); + deepEqual(_.flatten(array, true), [1, 2, 3, 4]); }); test('should return an empty array for non array-like objects', 1, function() { - var actual = _.flatten({ 'a': 1 }, _.identity); - deepEqual(actual, []); + deepEqual(_.flatten({ 'a': 1 }), []); }); }(1, 2, 3)); @@ -11073,7 +11033,7 @@ }); }); - test('should handle `null` `thisArg` arguments', 44, function() { + test('should handle `null` `thisArg` arguments', 43, function() { var expected = (function() { return this; }).call(null); var funcs = [ @@ -11084,7 +11044,6 @@ 'dropWhile', 'dropRightWhile', 'every', - 'flatten', 'filter', 'find', 'findIndex', From 20202b793b5ce1422efce23645658ef17410a585 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 17 Jun 2014 00:09:04 -0700 Subject: [PATCH 0790/1608] Remove `callback` support from `_.flatten` and make it shallow by default. --- lodash.js | 68 +++++++++++++++----------------------------- test/underscore.html | 7 +++++ 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/lodash.js b/lodash.js index 54690fce6e..f25133f54f 100644 --- a/lodash.js +++ b/lodash.js @@ -1582,8 +1582,8 @@ } /** - * The base implementation of `_.flatten` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.flatten` with added support for restricting + * flattening and specifying the start index. * * @private * @param {Array} array The array to flatten. @@ -1592,7 +1592,7 @@ * @param {number} [fromIndex=0] The index to start from. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isShallow, isStrict, fromIndex) { + function baseFlatten(array, isDeep, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, resIndex = 0, @@ -1604,8 +1604,8 @@ if (value && typeof value == 'object' && typeof value.length == 'number' && (isArray(value) || isArguments(value))) { // recursively flatten arrays (susceptible to call stack limits) - if (!isShallow) { - value = baseFlatten(value, isShallow, isStrict); + if (isDeep) { + value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, valLength = value.length; @@ -2730,7 +2730,7 @@ break; } } - return baseDifference(arguments[index], baseFlatten(arguments, true, true, ++index)); + return baseDifference(arguments[index], baseFlatten(arguments, false, true, ++index)); } /** @@ -3031,51 +3031,29 @@ * @memberOf _ * @category Arrays * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback] The function called per iteration. - * If a property name or object is provided it is used to create a "_.pluck" - * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `callback`. + * @param {boolean} [isDeep=false] Specify a deep flatten. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the new flattened array. * @example * * _.flatten([1, [2], [3, [[4]]]]); - * // => [1, 2, 3, 4]; - * - * // using `isShallow` - * _.flatten([1, [2], [3, [[4]]]], true); * // => [1, 2, 3, [[4]]]; * - * var characters = [ - * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } - * ]; - * - * // using "_.pluck" callback shorthand - * _.flatten(characters, 'pets'); - * // => ['hoppy', 'baby puss', 'dino'] + * // using `isDeep` + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, 4]; */ - function flatten(array, isShallow, callback, thisArg) { + function flatten(array, isDeep, guard) { var length = array ? array.length : 0; if (!length) { return []; } - // juggle arguments - var type = typeof isShallow; - if (type != 'boolean' && isShallow != null) { - thisArg = callback; - callback = isShallow; - isShallow = false; - - // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[callback] === array) { - callback = null; - } - } - if (callback != null) { - array = map(array, callback, thisArg); + // enables use as a callback for functions like `_.map` + var type = typeof isDeep; + if ((type == 'number' || type == 'string') && guard && guard[isDeep] === array) { + isDeep = false; } - return baseFlatten(array, isShallow); + return baseFlatten(array, isDeep); } /** @@ -3341,7 +3319,7 @@ * // => [10, 20] */ function pullAt(array) { - return basePullAt(array, baseFlatten(arguments, true, false, 1)); + return basePullAt(array, baseFlatten(arguments, false, false, 1)); } /** @@ -3685,7 +3663,7 @@ * // => [1, 2, 3, 5, 4] */ function union() { - return baseUniq(baseFlatten(arguments, true, true)); + return baseUniq(baseFlatten(arguments, false, true)); } /** @@ -4023,7 +4001,7 @@ if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } - return baseAt(collection, baseFlatten(arguments, true, false, 1)); + return baseAt(collection, baseFlatten(arguments, false, false, 1)); } /** @@ -5312,7 +5290,7 @@ */ function bindAll(object) { return baseBindAll(object, arguments.length > 1 - ? baseFlatten(arguments, true, false, 1) + ? baseFlatten(arguments, false, false, 1) : functions(object)); } @@ -7207,7 +7185,7 @@ if (typeof predicate == 'function') { return basePick(object, negate(lodash.createCallback(predicate, thisArg, 3))); } - var omitProps = baseFlatten(arguments, true, false, 1); + var omitProps = baseFlatten(arguments, false, false, 1); return basePick(object, baseDifference(keysIn(object), arrayMap(omitProps, String))); } @@ -7271,7 +7249,7 @@ } return basePick(object, typeof predicate == 'function' ? lodash.createCallback(predicate, thisArg, 3) - : baseFlatten(arguments, true, false, 1)); + : baseFlatten(arguments, false, false, 1)); } /** diff --git a/test/underscore.html b/test/underscore.html index 73f147b25d..292c396f67 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -42,6 +42,12 @@ // excuse tests we intentionally fail or those with problems QUnit.config.excused = { 'Arrays': { + 'flatten': [ + 'can flatten nested arrays', + 'can shallowly flatten nested arrays', + 'works on an arguments object', + 'can shallowly flatten arrays containing only other arrays' + ], 'initial': [ 'initial works on arguments object' ], @@ -158,6 +164,7 @@ delete QUnit.config.excused.Functions.partial; } QUnit.config.excused.Arrays.intersection.shift(); + delete QUnit.config.excused.Arrays.flatten; delete QUnit.config.excused.Arrays.initial; delete QUnit.config.excused.Arrays.rest; delete QUnit.config.excused.Chaining; From 0d2db28908e8b0f2a1a9ae2e693ffe2e07bb05da Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 17 Jun 2014 01:07:04 -0700 Subject: [PATCH 0791/1608] Rename `_.createCallback` to `_.callback`. --- lodash.js | 105 +++++++++++++++++++++++++-------------------------- test/test.js | 6 +-- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/lodash.js b/lodash.js index f25133f54f..8c17454fce 100644 --- a/lodash.js +++ b/lodash.js @@ -735,13 +735,13 @@ * implicitly or explicitly included in the build. * * The chainable wrapper functions are: - * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, - * `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`, - * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, - * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, - * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, - * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, + * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `callback`, `chain`, + * `compact`, `compose`, `concat`, `constant`, `countBy`, `create`, `curry`, + * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, + * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, + * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, + * `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, `merge`, + * `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, * `partialRight`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, @@ -1331,7 +1331,7 @@ } /** - * The base implementation of `_.createCallback` without support for creating + * The base implementation of `_.callback` without support for creating * "_.pluck" and "_.where" style callbacks. * * @private @@ -1340,7 +1340,7 @@ * @param {number} [argCount] The number of arguments the callback accepts. * @returns {Function} Returns the new function. */ - function baseCreateCallback(func, thisArg, argCount) { + function baseCallback(func, thisArg, argCount) { if (typeof func != 'function') { return identity; } @@ -2272,7 +2272,7 @@ function createAggregator(setter, initializer) { return function(collection, callback, thisArg) { var result = initializer ? initializer() : {}; - callback = lodash.createCallback(callback, thisArg, 3); + callback = lodash.callback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, @@ -2314,7 +2314,7 @@ } // juggle arguments if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 5); + var callback = baseCallback(args[--length - 1], args[length--], 5); } else if (length > 2 && typeof args[length - 1] == 'function') { callback = args[--length]; } @@ -2912,7 +2912,7 @@ var index = -1, length = array ? array.length : 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (++index < length) { if (predicate(array[index], index, array)) { return index; @@ -2965,7 +2965,7 @@ function findLastIndex(array, predicate, thisArg) { var length = array ? array.length : 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (length--) { if (predicate(array[length], length, array)) { return length; @@ -3000,7 +3000,7 @@ length = array ? array.length : 0, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) { n++; } @@ -3116,7 +3116,7 @@ var index = length, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (index-- && predicate(array[index], index, array)) { n++; } @@ -3207,7 +3207,7 @@ var index = length, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (index-- && predicate(array[index], index, array)) { n++; } @@ -3361,7 +3361,7 @@ length = array ? array.length : 0, result = []; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { @@ -3396,7 +3396,7 @@ length = array ? array.length : 0, n = 0; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) { n++; } @@ -3502,7 +3502,7 @@ high = array ? array.length : low; // explicitly reference `identity` for better inlining in Firefox - callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity; + callback = callback ? lodash.callback(callback, thisArg, 1) : identity; value = callback(value); while (low < high) { @@ -3731,7 +3731,7 @@ } } if (callback != null) { - callback = lodash.createCallback(callback, thisArg, 3); + callback = lodash.callback(callback, thisArg, 3); } return baseUniq(array, isSorted, callback); } @@ -4137,7 +4137,7 @@ var result = true; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); } if (isArray(collection)) { var index = -1, @@ -4199,7 +4199,7 @@ */ function filter(collection, predicate, thisArg) { var result = []; - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); if (isArray(collection)) { var index = -1, @@ -4269,7 +4269,7 @@ var index = findIndex(collection, predicate, thisArg); return index > -1 ? collection[index] : undefined; } - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); return baseFind(collection, predicate, baseEach); } @@ -4292,7 +4292,7 @@ * // => 3 */ function findLast(collection, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); return baseFind(collection, predicate, baseEachRight); } @@ -4353,7 +4353,7 @@ function forEach(collection, callback, thisArg) { return (typeof callback == 'function' && typeof thisArg == 'undefined' && isArray(collection)) ? arrayEach(collection, callback) - : baseEach(collection, baseCreateCallback(callback, thisArg, 3)); + : baseEach(collection, baseCallback(callback, thisArg, 3)); } /** @@ -4376,7 +4376,7 @@ function forEachRight(collection, callback, thisArg) { return (typeof callback == 'function' && typeof thisArg == 'undefined' && isArray(collection)) ? arrayEachRight(collection, callback) - : baseEachRight(collection, baseCreateCallback(callback, thisArg, 3)); + : baseEachRight(collection, baseCallback(callback, thisArg, 3)); } /** @@ -4531,7 +4531,7 @@ * // => ['barney', 'fred'] */ function map(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); + callback = lodash.callback(callback, thisArg, 3); if (isArray(collection)) { return arrayMap(collection, callback, thisArg); @@ -4610,7 +4610,7 @@ } else { callback = (callback == null && isString(collection)) ? charAtCallback - : lodash.createCallback(callback, thisArg, 3); + : lodash.callback(callback, thisArg, 3); baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); @@ -4688,7 +4688,7 @@ } else { callback = (callback == null && isString(collection)) ? charAtCallback - : lodash.createCallback(callback, thisArg, 3); + : lodash.callback(callback, thisArg, 3); baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); @@ -4802,7 +4802,7 @@ */ function reduce(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); + callback = lodash.callback(callback, thisArg, 4); if (isArray(collection)) { var index = -1, @@ -4845,7 +4845,7 @@ */ function reduceRight(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); + callback = lodash.callback(callback, thisArg, 4); baseEachRight(collection, function(value, index, collection) { accumulator = noaccum @@ -4894,7 +4894,7 @@ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); return filter(collection, negate(predicate)); } @@ -5032,7 +5032,7 @@ var result; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); } if (isArray(collection)) { var index = -1, @@ -5108,7 +5108,7 @@ result = Array(length < 0 ? 0 : length >>> 0); if (!multi) { - callback = lodash.createCallback(callback, thisArg, 3); + callback = lodash.callback(callback, thisArg, 3); } baseEach(collection, function(value, key, collection) { if (multi) { @@ -6020,7 +6020,7 @@ callback = null; } } - callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1); + callback = typeof callback == 'function' && baseCallback(callback, thisArg, 1); return baseClone(value, isDeep, callback); } @@ -6067,7 +6067,7 @@ * // => false */ function cloneDeep(value, callback, thisArg) { - callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1); + callback = typeof callback == 'function' && baseCallback(callback, thisArg, 1); return baseClone(value, true, callback); } @@ -6178,7 +6178,7 @@ * // => 'fred' */ function findKey(object, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); return baseFind(object, predicate, baseForOwn, true); } @@ -6224,7 +6224,7 @@ * // => 'pebbles' */ function findLastKey(object, predicate, thisArg) { - predicate = lodash.createCallback(predicate, thisArg, 3); + predicate = lodash.callback(predicate, thisArg, 3); return baseFind(object, predicate, baseForOwnRight, true); } @@ -6257,7 +6257,7 @@ */ function forIn(object, callback, thisArg) { if (typeof callback != 'function' || typeof thisArg != 'undefined') { - callback = baseCreateCallback(callback, thisArg, 3); + callback = baseCallback(callback, thisArg, 3); } return baseFor(object, callback, keysIn); } @@ -6288,7 +6288,7 @@ * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' */ function forInRight(object, callback, thisArg) { - callback = baseCreateCallback(callback, thisArg, 3); + callback = baseCallback(callback, thisArg, 3); return baseForRight(object, callback, keysIn); } @@ -6314,7 +6314,7 @@ */ function forOwn(object, callback, thisArg) { if (typeof callback != 'function' || typeof thisArg != 'undefined') { - callback = baseCreateCallback(callback, thisArg, 3); + callback = baseCallback(callback, thisArg, 3); } return baseForOwn(object, callback); } @@ -6338,7 +6338,7 @@ * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ function forOwnRight(object, callback, thisArg) { - callback = baseCreateCallback(callback, thisArg, 3); + callback = baseCallback(callback, thisArg, 3); return baseForRight(object, callback, keys); } @@ -6632,7 +6632,7 @@ * // => true */ function isEqual(value, other, callback, thisArg) { - callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 3); + callback = typeof callback == 'function' && baseCallback(callback, thisArg, 3); if (!callback) { // exit early for identical values @@ -7090,7 +7090,7 @@ */ function mapValues(object, callback, thisArg) { var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); + callback = lodash.callback(callback, thisArg, 3); baseForOwn(object, function(value, key, object) { result[key] = callback(value, key, object); @@ -7183,7 +7183,7 @@ return {}; } if (typeof predicate == 'function') { - return basePick(object, negate(lodash.createCallback(predicate, thisArg, 3))); + return basePick(object, negate(lodash.callback(predicate, thisArg, 3))); } var omitProps = baseFlatten(arguments, false, false, 1); return basePick(object, baseDifference(keysIn(object), arrayMap(omitProps, String))); @@ -7248,7 +7248,7 @@ return {}; } return basePick(object, typeof predicate == 'function' - ? lodash.createCallback(predicate, thisArg, 3) + ? lodash.callback(predicate, thisArg, 3) : baseFlatten(arguments, false, false, 1)); } @@ -7297,7 +7297,7 @@ } } if (callback) { - callback = lodash.createCallback(callback, thisArg, 4); + callback = lodash.callback(callback, thisArg, 4); (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { return callback(accumulator, value, index, object); }); @@ -8106,7 +8106,7 @@ * ]; * * // wrap to create custom callback shorthands - * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { + * _.callback = _.wrap(_.callback, function(func, callback, thisArg) { * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); * return !match ? func(callback, thisArg) : function(object) { * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; @@ -8116,7 +8116,7 @@ * _.filter(characters, 'age__gt38'); * // => [{ 'name': 'fred', 'age': 40 }] */ - function createCallback(func, thisArg, argCount) { + function callback(func, thisArg, argCount) { var type = typeof func, isFunc = type == 'function'; @@ -8124,7 +8124,7 @@ return func; } if (isFunc || func == null) { - return baseCreateCallback(func, thisArg, argCount); + return baseCallback(func, thisArg, argCount); } // handle "_.pluck" and "_.where" style callback shorthands return type == 'object' ? matches(func) : property(func); @@ -8577,7 +8577,7 @@ */ function times(n, callback, thisArg) { n = n < 0 ? 0 : n >>> 0; - callback = baseCreateCallback(callback, thisArg, 1); + callback = baseCallback(callback, thisArg, 1); var index = -1, result = Array(n); @@ -8618,6 +8618,7 @@ lodash.bind = bind; lodash.bindAll = bindAll; lodash.bindKey = bindKey; + lodash.callback = callback; lodash.chain = chain; lodash.chunk = chunk; lodash.compact = compact; @@ -8625,7 +8626,6 @@ lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; - lodash.createCallback = createCallback; lodash.curry = curry; lodash.debounce = debounce; lodash.defaults = defaults; @@ -8695,7 +8695,6 @@ lodash.zipObject = zipObject; // add aliases - lodash.callback = createCallback; lodash.collect = map; lodash.each = forEach; lodash.eachRight = forEachRight; diff --git a/test/test.js b/test/test.js index 0b37bf7bcd..167b820bd7 100644 --- a/test/test.js +++ b/test/test.js @@ -3012,8 +3012,8 @@ }); test('should perform a shallow flatten when used as a callback for `_.map`', 1, function() { - var array = [[['a']], [['b']]]; - deepEqual(_.map(array, _.flatten), [['a'], ['b']]); + var array = [[[['a']]], [[['b']]]]; + deepEqual(_.map(array, _.flatten), [[['a']], [['b']]]); }); test('should treat sparse arrays as dense', 4, function() { @@ -10945,7 +10945,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 189, function() { + test('should accept falsey arguments', 188, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From 00e00eb7b5e4830046f2a078138c093eeb2f5ad3 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 17 Jun 2014 09:16:09 -0700 Subject: [PATCH 0792/1608] Doc tweaks for `boolean` params. [ci skip] --- lodash.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lodash.js b/lodash.js index 8c17454fce..196d6cf7b9 100644 --- a/lodash.js +++ b/lodash.js @@ -798,7 +798,7 @@ * * @private * @param {*} value The value to wrap in a `lodash` instance. - * @param {boolean} [chainAll=false] A flag to enable chaining for all methods. + * @param {boolean} [chainAll=false] Enable chaining for all methods. * @returns {Object} Returns a `lodash` instance. */ function lodashWrapper(value, chainAll) { @@ -1565,8 +1565,8 @@ * @param {Array|Object|string} collection The collection to search. * @param {Function} predicate The function called per iteration. * @param {Function} eachFunc The function to iterate over the collection. - * @param {boolean} [retKey=false] A flag to indicate returning the key of - * the found element instead of the element itself. + * @param {boolean} [retKey=false] Specify returning the key of the found + * element instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ function baseFind(collection, predicate, eachFunc, retKey) { @@ -1587,8 +1587,8 @@ * * @private * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. + * @param {boolean} [isDeep=false] Specify a deep flatten. + * @param {boolean} [isStrict=false] Restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. * @returns {Array} Returns the new flattened array. */ @@ -1741,7 +1741,7 @@ * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [callback] The function to customize comparing values. - * @param {boolean} [isWhere=false] A flag to indicate performing partial comparisons. + * @param {boolean} [isWhere=false] Specify performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. @@ -2092,7 +2092,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. + * @param {boolean} [isSorted=false] Specify the array is sorted. * @param {Function} [callback] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ @@ -3686,7 +3686,7 @@ * @alias unique * @category Arrays * @param {Array} array The array to inspect. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. + * @param {boolean} [isSorted=false] Specify the array is sorted. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. From c1eaa90c2bc6d744f79cd8911938f20ac7b519d8 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 17 Jun 2014 10:30:51 -0700 Subject: [PATCH 0793/1608] Move `callback` above `constant`. --- lodash.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lodash.js b/lodash.js index 196d6cf7b9..d69d1805dd 100644 --- a/lodash.js +++ b/lodash.js @@ -8063,27 +8063,6 @@ /*--------------------------------------------------------------------------*/ - /** - * Creates a function that returns `value`. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new function. - * @example - * - * var object = { 'name': 'fred' }; - * var getter = _.constant(object); - * getter() === object; - * // => true - */ - function constant(value) { - return function() { - return value; - }; - } - /** * Creates a function bound to an optional `thisArg`. If `func` is a property * name the created callback returns the property value for a given element. @@ -8130,6 +8109,27 @@ return type == 'object' ? matches(func) : property(func); } + /** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @category Utilities + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new function. + * @example + * + * var object = { 'name': 'fred' }; + * var getter = _.constant(object); + * getter() === object; + * // => true + */ + function constant(value) { + return function() { + return value; + }; + } + /** * This method returns the first argument provided to it. * From 6a164a235dc4e45b2fbcd46a8661909f9ac74199 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 17 Jun 2014 20:26:33 -0700 Subject: [PATCH 0794/1608] Add methods to the `lodash` wrapped/unwrapped chaining docs. [ci skip] --- lodash.js | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/lodash.js b/lodash.js index d69d1805dd..44fe6b957c 100644 --- a/lodash.js +++ b/lodash.js @@ -736,31 +736,35 @@ * * The chainable wrapper functions are: * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `callback`, `chain`, - * `compact`, `compose`, `concat`, `constant`, `countBy`, `create`, `curry`, - * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, - * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, - * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, - * `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, `merge`, - * `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, - * `partialRight`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, - * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, - * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, - * `xor`, and `zip` + * `chunk`, `compact`, `compose`, `concat`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `drop`, + * `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, `forEach`, + * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, + * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, + * `keysIn`, `map`, `mapValues`, `matches`, `memoize`, `merge`, `mixin`, + * `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `pluck`, `property`, `pull`, `pullAt`, `push`, `range`, + * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, + * `splice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, + * `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, + * `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, + * and `zipObject` * * The non-chainable wrapper functions are: - * `capitalize`, `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, - * `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, + * `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, `endsWith`, + * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, - * `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, - * `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, - * `isUndefined`, `join`, `lastIndexOf`, `noConflict`, `now`, `parseInt`, - * `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`, - * `sortedIndex`, `runInContext`, `template`, `trim`, `trimLeft`, `trimRight`, - * `unescape`, `uniqueId`, and `value` - * - * The wrapper functions `first`, `last`, and `sample` return wrapped values - * when `n` is provided, otherwise they return unwrapped values. + * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, + * `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, + * `isString`, `isUndefined`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, + * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, + * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `startsWith`, `template`, + * `trim`, `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, and `value` + * + * The wrapper function `sample` will return a wrapped value when `n` is + * provided, otherwise it will return an unwrapped value. * * Explicit chaining can be enabled by using the `_.chain` method. * From a113dc086106a8574100966da9b7e7a870c95c0b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 18 Jun 2014 00:49:35 -0700 Subject: [PATCH 0795/1608] Remove overloading from `_.first`, `_.last`, `_.initial`, & `_.rest`. --- lodash.js | 164 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 80 deletions(-) diff --git a/lodash.js b/lodash.js index 44fe6b957c..a73ccfb41f 100644 --- a/lodash.js +++ b/lodash.js @@ -2746,6 +2746,7 @@ * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -2761,7 +2762,10 @@ * _.drop([1, 2, 3], 0); * // => [1, 2, 3] */ - var drop = rest; + function drop(array, n, guard) { + n = (n == null || guard) ? 1 : n; + return slice(array, n < 0 ? 0 : n); + } /** * Creates a slice of `array` with `n` elements dropped from the end. @@ -2772,6 +2776,7 @@ * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -2787,7 +2792,12 @@ * _.dropRight([1, 2, 3], 0); * // => [1, 2, 3] */ - var dropRight = initial; + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + n = (n == null || guard) ? 1 : n; + n = length - (n || 0); + return slice(array, 0, n < 0 ? 0 : n); + } /** * Creates a slice of `array` excluding elements dropped from the end. @@ -2808,6 +2818,7 @@ * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function called * per element. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -2828,7 +2839,18 @@ * _.pluck(_.dropRightWhile(characters, { 'employer': 'na' }), 'name'); * // => ['barney', 'fred'] */ - var dropRightWhile = initial; + function dropRightWhile(array, predicate, thisArg) { + var length = array ? array.length : 0, + index = length, + n = 0; + + predicate = lodash.callback(predicate, thisArg, 3); + while (index-- && predicate(array[index], index, array)) { + n++; + } + n = length - (n || 0); + return slice(array, 0, n < 0 ? 0 : n); + } /** * Creates a slice of `array` excluding elements dropped from the beginning. @@ -2869,7 +2891,17 @@ * _.pluck(_.dropWhile(characters, { 'employer': 'slate' }), 'name'); * // => ['pebbles'] */ - var dropWhile = rest; + function dropWhile(array, predicate, thisArg) { + var index = -1, + length = array ? array.length : 0, + n = 0; + + predicate = lodash.callback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) { + n++; + } + return slice(array, n); + } /** * This method is like `_.find` except that it returns the index of the first @@ -2981,9 +3013,6 @@ /** * Gets the first element of `array`. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.take` and `_.takeWhile` respectively. - * * @static * @memberOf _ * @alias head @@ -2998,23 +3027,8 @@ * _.first([]); * // => undefined */ - function first(array, predicate, thisArg) { - if (typeof predicate != 'number' && predicate != null) { - var index = -1, - length = array ? array.length : 0, - n = 0; - - predicate = lodash.callback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { - n++; - } - } else { - n = predicate; - if (n == null || thisArg) { - return array ? array[0] : undefined; - } - } - return slice(array, 0, n < 0 ? 0 : n); + function first(array) { + return array ? array[0] : undefined; } /** @@ -3100,9 +3114,6 @@ /** * Gets all but the last element of `array`. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.dropRight` and `_.dropRightWhile` respectively. - * * @static * @memberOf _ * @category Arrays @@ -3191,9 +3202,6 @@ /** * Gets the last element of `array`. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.takeRight` and `_.takeRightWhile` respectively. - * * @static * @memberOf _ * @category Arrays @@ -3204,25 +3212,9 @@ * _.last([1, 2, 3]); * // => 3 */ - function last(array, predicate, thisArg) { + function last(array) { var length = array ? array.length : 0; - - if (typeof predicate != 'number' && predicate != null) { - var index = length, - n = 0; - - predicate = lodash.callback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { - n++; - } - } else { - n = predicate; - if (n == null || thisArg) { - return array ? array[length - 1] : undefined; - } - } - n = length - (n || 0); - return slice(array, n < 0 ? 0 : n); + return length ? array[length - 1] : undefined; } /** @@ -3380,9 +3372,6 @@ /** * Gets all but the first element of `array`. * - * Note: The `n` and `predicate` arguments are deprecated; replace with - * `_.drop` and `_.dropWhile` respectively. - * * @static * @memberOf _ * @alias tail @@ -3394,22 +3383,8 @@ * _.rest([1, 2, 3]); * // => [2, 3] */ - function rest(array, predicate, thisArg) { - if (typeof predicate != 'number' && predicate != null) { - var index = -1, - length = array ? array.length : 0, - n = 0; - - predicate = lodash.callback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { - n++; - } - } else if (predicate == null || thisArg) { - n = 1; - } else { - n = predicate < 0 ? 0 : predicate; - } - return slice(array, n); + function rest(array) { + return slice(array, 1); } /** @@ -3527,6 +3502,7 @@ * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -3542,7 +3518,10 @@ * _.take([1, 2, 3], 0); * // => [] */ - var take = first; + function take(array, n, guard) { + n = (n == null || guard) ? 1 : n; + return slice(array, 0, n < 0 ? 0 : n); + } /** * Creates a slice of `array` with `n` elements taken from the end. @@ -3553,6 +3532,7 @@ * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -3568,7 +3548,12 @@ * _.takeRight([1, 2, 3], 0); * // => [] */ - var takeRight = last; + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + n = (n == null || guard) ? 1 : n; + n = length - (n || 0); + return slice(array, n < 0 ? 0 : n); + } /** * Creates a slice of `array` with elements taken from the end. Elements are @@ -3609,7 +3594,18 @@ * _.pluck(_.takeRightWhile(characters, { 'employer': 'na' }), 'name'); * // => ['pebbles'] */ - var takeRightWhile = last; + function takeRightWhile(array, predicate, thisArg) { + var length = array ? array.length : 0, + index = length, + n = 0; + + predicate = lodash.callback(predicate, thisArg, 3); + while (index-- && predicate(array[index], index, array)) { + n++; + } + n = length - (n || 0); + return slice(array, n < 0 ? 0 : n); + } /** * Creates a slice of `array` with elements taken from the beginning. Elements @@ -3650,7 +3646,17 @@ * _.pluck(_.takeWhile(characters, { 'employer': 'slate' }), 'name'); * // => ['barney', 'fred'] */ - var takeWhile = first; + function takeWhile(array, predicate, thisArg) { + var index = -1, + length = array ? array.length : 0, + n = 0; + + predicate = lodash.callback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) { + n++; + } + return slice(array, 0, n < 0 ? 0 : n); + } /** * Creates an array of unique values, in order, of the provided arrays using @@ -8682,6 +8688,10 @@ lodash.shuffle = shuffle; lodash.slice = slice; lodash.sortBy = sortBy; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; lodash.tap = tap; lodash.throttle = throttle; lodash.times = times; @@ -8732,6 +8742,7 @@ lodash.findLastIndex = findLastIndex; lodash.findLastKey = findLastKey; lodash.findWhere = findWhere; + lodash.first = first; lodash.has = has; lodash.identity = identity; lodash.indexOf = indexOf; @@ -8754,6 +8765,7 @@ lodash.isString = isString; lodash.isUndefined = isUndefined; lodash.kebabCase = kebabCase; + lodash.last = last; lodash.lastIndexOf = lastIndexOf; lodash.max = max; lodash.min = min; @@ -8789,6 +8801,7 @@ lodash.detect = find; lodash.foldl = reduce; lodash.foldr = reduceRight; + lodash.head = first; lodash.include = contains; lodash.inject = reduce; @@ -8805,16 +8818,7 @@ /*--------------------------------------------------------------------------*/ // add functions capable of returning wrapped and unwrapped values when chaining - lodash.first = first; - lodash.last = last; lodash.sample = sample; - lodash.take = take; - lodash.takeRight = takeRight; - lodash.takeRightWhile = takeRightWhile; - lodash.takeWhile = takeWhile; - - // add alias - lodash.head = first; baseForOwn(lodash, function(func, methodName) { var callbackable = methodName != 'sample'; From 61eb5d906c98e579434df8e6d26cb3f7ef3c605e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 18 Jun 2014 08:08:07 -0700 Subject: [PATCH 0796/1608] Doc tweaks to `_.flatten` and other methods. [ci skip] --- lodash.js | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/lodash.js b/lodash.js index a73ccfb41f..cd2117d8a0 100644 --- a/lodash.js +++ b/lodash.js @@ -3032,18 +3032,8 @@ } /** - * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truthy, the array is only flattened a single level. If a callback is - * provided each element of the array is passed through the callback before - * flattening. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback returns the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * returns `true` for elements that have the properties of the given object, - * else `false`. + * Flattens a nested array. If `isDeep` is `true` the array is recursively + * flattened, otherwise it is only flattened a single level. * * @static * @memberOf _ @@ -3291,8 +3281,8 @@ /** * Removes elements from `array` corresponding to the specified indexes and - * returns an array of removed elements. Indexes may be specified as an array - * of indexes or as individual arguments. + * returns an array of the removed elements. Indexes may be specified as an + * array of indexes or as individual arguments. * * Note: Unlike `_.at`, this method mutates `array`. * @@ -3320,8 +3310,8 @@ /** * Removes all elements from `array` that the predicate returns truthy for - * and returns an array of removed elements. The predicate is bound to `thisArg` - * and invoked with three arguments; (value, index, array). + * and returns an array of the removed elements. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. @@ -5471,9 +5461,12 @@ * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout. - * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. + * @param {boolean} [options.leading=false] Specify execution on the leading + * edge of the timeout. + * @param {number} [options.maxWait] The maximum time `func` is allowed to be + * delayed before it is called. + * @param {boolean} [options.trailing=true] Specify execution on the trailing + * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * @@ -5878,8 +5871,10 @@ * @param {Function} func The function to throttle. * @param {number} wait The number of milliseconds to throttle executions to. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. + * @param {boolean} [options.leading=true] Specify execution on the leading + * edge of the timeout. + * @param {boolean} [options.trailing=true] Specify execution on the trailing + * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * @@ -8410,7 +8405,7 @@ /** * Produces a random number between `min` and `max` (inclusive). If only one * argument is provided a number between `0` and the given number is returned. - * If `floating` is truthy, or either `min` or `max` are floats, a floating-point + * If `floating` is `true`, or either `min` or `max` are floats, a floating-point * number is returned instead of an integer. * * @static From e2cd275ac563650e997097b970abf669e1f07dd5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 18 Jun 2014 08:37:27 -0700 Subject: [PATCH 0797/1608] Remove the `data` param from `_.template`. --- lodash.js | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/lodash.js b/lodash.js index cd2117d8a0..d9b2c0b96f 100644 --- a/lodash.js +++ b/lodash.js @@ -7695,12 +7695,10 @@ /** * Creates a compiled template function that can interpolate data properties - * in "interpolate" delimiters, HTML-escaped interpolated data properties in - * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. If - * a data object is provided the interpolated template string is returned. - * Data properties may be accessed as free variables in the template. If a - * settings object is provided it overrides `_.templateSettings` for the - * template. + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is provided it overrides `_.templateSettings` for the template. * * Note: In the development build, `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) @@ -7716,7 +7714,6 @@ * @memberOf _ * @category Strings * @param {string} [string=''] The template string. - * @param {Object} [data] The data object used to populate the template string. * @param {Object} [options] The options object. * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. @@ -7724,8 +7721,7 @@ * @param {RegExp} [options.interpolate] The "interpolate" delimiter. * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. * @param {string} [options.variable] The data object variable name. - * @returns {Function|string} Returns the interpolated string if a data object - * is provided, else the compiled template function. + * @returns {Function} Returns the compiled template function. * @example * * // using the "interpolate" delimiter to create a compiled template @@ -7734,39 +7730,44 @@ * // => 'hello fred' * * // using the HTML "escape" delimiter to escape data property values - * _.template('<%- value %>', { 'value': ' - \ No newline at end of file + diff --git a/perf/perf.js b/perf/perf.js index 651d3b3dfd..f5f8841b4a 100644 --- a/perf/perf.js +++ b/perf/perf.js @@ -43,11 +43,11 @@ if (!amd) { try { result = require('fs').realpathSync(result); - } catch(e) { } + } catch(e) {} try { result = require.resolve(result); - } catch(e) { } + } catch(e) {} } return result; }()); diff --git a/test/index.html b/test/index.html index 4648cf5abd..598d3a9c0e 100644 --- a/test/index.html +++ b/test/index.html @@ -54,6 +54,7 @@ var hasOwnProperty = objectProto.hasOwnProperty, fnToString = funcProto.toString, nativeString = fnToString.call(objectProto.toString), + noop = function() {}, propertyIsEnumerable = objectProto.propertyIsEnumerable, reToString = /toString/g, whitespace = ' \t\x0B\f\xA0\ufeff\n\r\u2028\u2029\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; @@ -78,26 +79,26 @@ }())); // add extensions - funcProto._method = function() {}; + funcProto._method = noop; // set bad shims setProperty(Array, '_isArray', Array.isArray); - setProperty(Array, 'isArray', function() {}); + setProperty(Array, 'isArray', noop); setProperty(Date, '_now', Date.now); - setProperty(Date, 'now', function() {}); + setProperty(Date, 'now', noop); setProperty(Object, '_create', Object.create); - setProperty(Object, 'create', function() {}); + setProperty(Object, 'create', noop); setProperty(Object, '_defineProperty', Object.defineProperty); - setProperty(Object, 'defineProperty', function() {}); + setProperty(Object, 'defineProperty', noop); setProperty(Object, '_getPrototypeOf', Object.getPrototypeOf); - setProperty(Object, 'getPrototypeOf', function() {}); + setProperty(Object, 'getPrototypeOf', noop); setProperty(Object, '_keys', Object.keys); - setProperty(Object, 'keys', function() {}); + setProperty(Object, 'keys', noop); setProperty(objectProto, 'hasOwnProperty', (function() { function wrapper(key) { @@ -114,13 +115,13 @@ }())); setProperty(Number, '_isFinite', Number.isFinite); - setProperty(Number, 'isFinite', function() {}); + setProperty(Number, 'isFinite', noop); setProperty(stringProto, '_contains', stringProto.contains); - setProperty(stringProto, 'contains', stringProto._contains ? function() {} : Boolean); + setProperty(stringProto, 'contains', stringProto._contains ? noop : Boolean); setProperty(document, '_createDocumentFragment', document.createDocumentFragment); - document.createDocumentFragment = function() {}; + document.createDocumentFragment = noop; setProperty(window, '_ArrayBuffer', window.ArrayBuffer); if (window.ArrayBuffer && window.Uint8Array) { diff --git a/test/test.js b/test/test.js index 612d7e1b8b..e77cb4c0c2 100644 --- a/test/test.js +++ b/test/test.js @@ -62,11 +62,11 @@ if (!amd) { try { result = require('fs').realpathSync(result); - } catch(e) { } + } catch(e) {} try { result = require.resolve(result); - } catch(e) { } + } catch(e) {} } return result; }()); @@ -107,7 +107,7 @@ /** Used to test host objects in IE */ try { var xml = new ActiveXObject('Microsoft.XMLDOM'); - } catch(e) { } + } catch(e) {} /** Use a single "load" function */ var load = (typeof require == 'function' && !amd) @@ -212,7 +212,7 @@ var o = {}, func = Object.defineProperty, result = func(o, o, o) && func; - } catch(e) { } + } catch(e) {} return result; }()); @@ -992,7 +992,7 @@ try { var bound = _.bind(fn, value); return bound(); - } catch(e) { } + } catch(e) {} }); ok(_.every(actual, function(value, index) { @@ -1531,8 +1531,8 @@ test('`_.cloneDeep` should deep clone objects with circular references', 1, function() { var object = { - 'foo': { 'b': { 'foo': { 'c': { } } } }, - 'bar': { } + 'foo': { 'b': { 'foo': { 'c': {} } } }, + 'bar': {} }; object.foo.b.foo.c = object; @@ -2025,7 +2025,7 @@ }); test('should accept a falsey `prototype` argument', 1, function() { - var expected = _.map(falsey, function() { return {}; }); + var expected = _.map(falsey, _.constant({})); var actual = _.map(falsey, function(value, index) { return index ? _.create(value) : _.create(); @@ -3212,7 +3212,7 @@ var actual = _.map(empties, function(value) { try { return _.every(value, _.identity); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -3360,7 +3360,7 @@ _.each(emptyValues, function(value) { try { actual.push(func(value, { 'a': 3 })); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expecting); @@ -4726,7 +4726,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? _.initial(value) : _.initial(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -5465,12 +5465,12 @@ test('should perform comparisons between objects with complex circular references', 1, function() { var object1 = { - 'foo': { 'b': { 'foo': { 'c': { } } } }, + 'foo': { 'b': { 'foo': { 'c': {} } } }, 'bar': { 'a': 2 } }; var object2 = { - 'foo': { 'b': { 'foo': { 'c': { } } } }, + 'foo': { 'b': { 'foo': { 'c': {} } } }, 'bar': { 'a': 2 } }; @@ -6690,7 +6690,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? func(value) : func(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -6779,7 +6779,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? _.map(value) : _.map(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -6851,7 +6851,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? _.mapValues(value) : _.mapValues(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -6951,7 +6951,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? matches(value) : matches(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -6965,7 +6965,7 @@ try { var result = index ? matches(value) : matches(); return result === true; - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -7067,7 +7067,7 @@ var actual = _.map(empties, function(value) { try { return _.max(value); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -7080,7 +7080,7 @@ var actual = _.map(collections, function(value) { try { return _.max(value); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -7129,7 +7129,7 @@ var actual = _.map(falsey, function(value, index) { try { return _.isFunction(index ? _.memoize(_.noop, value) : _.memoize(_.noop)); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -7224,8 +7224,8 @@ }; var source = { - 'foo': { 'b': { 'foo': { 'c': { } } } }, - 'bar': { } + 'foo': { 'b': { 'foo': { 'c': {} } } }, + 'bar': {} }; source.foo.b.foo.c = source; @@ -7305,7 +7305,7 @@ var actual = _.map(empties, function(value) { try { return _.min(value); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -7318,7 +7318,7 @@ var actual = _.map(collections, function(value) { try { return _.min(value); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -8849,7 +8849,7 @@ _.each(empties, function(value) { try { actual.push(func(value, _.noop)); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -8861,7 +8861,7 @@ var actual = _.map(empties, function(value) { try { return func(value, _.noop, 'x'); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -9068,7 +9068,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? _.rest(value) : _.rest(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -9188,7 +9188,7 @@ _.each(empties, function(value) { try { actual.push(_.shuffle(value), _.shuffle(value, 1)); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -9313,7 +9313,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? _.size(value) : _.size(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -9449,7 +9449,7 @@ var actual = _.map(empties, function(value) { try { return _.some(value, _.identity); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -9932,7 +9932,7 @@ try { var actual = compiled(); - } catch(e) { } + } catch(e) {} strictEqual(actual, 'function'); }); @@ -10003,7 +10003,7 @@ 'interpolate': /\{\{=([\s\S]+?)\}\}/g }); - var compiled = _.template('
      {{ _.each(collection, function(value, index) { }}
    • {{= index }}: {{- value }}
    • {{ }); }}
    ', index ? null : settings), + var compiled = _.template('
      {{ _.each(collection, function(value, index) {}}
    • {{= index }}: {{- value }}
    • {{}); }}
    ', index ? null : settings), expected = '
    • 0: a & A
    • 1: b & B
    '; strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected); @@ -10699,7 +10699,7 @@ try { var nodeList = document.getElementsByTagName('body'), actual = func(nodeList); - } catch(e) { } + } catch(e) {} deepEqual(actual, [body]); } @@ -11402,7 +11402,7 @@ var actual = _.map(falsey, function(value, index) { try { return index ? _.zipObject(value) : _.zipObject(); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -11663,7 +11663,7 @@ _.each(falsey, function(value, index) { try { actual.push(index ? func(value) : func()); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); @@ -11681,7 +11681,7 @@ var actual = _.map(falsey, function(value, index) { try { return func(value, 2); - } catch(e) { } + } catch(e) {} }); deepEqual(actual, expected); diff --git a/vendor/benchmark.js/benchmark.js b/vendor/benchmark.js/benchmark.js index d5727837df..e9dae44460 100644 --- a/vendor/benchmark.js/benchmark.js +++ b/vendor/benchmark.js/benchmark.js @@ -663,7 +663,7 @@ function req(id) { try { var result = freeExports && freeRequire(id); - } catch(e) { } + } catch(e) {} return result || null; } @@ -905,7 +905,7 @@ } else if (async) { // resume execution if previously asynchronous but now synchronous - while (execute()) { } + while (execute()) {} } else { // continue synchronous execution @@ -986,7 +986,7 @@ if (isAsync(bench)) { delay(bench, execute); } else { - while (execute()) { } + while (execute()) {} } } } @@ -1770,30 +1770,30 @@ divisor = 1e6; if (ns.stop) { ns.start(); - while (!(measured = ns.microseconds())) { } + while (!(measured = ns.microseconds())) {} } else { begin = ns(); - while (!(measured = ns() - begin)) { } + while (!(measured = ns() - begin)) {} } } else if (unit == 'ns') { divisor = 1e9; if (ns.nanoTime) { begin = ns.nanoTime(); - while (!(measured = ns.nanoTime() - begin)) { } + while (!(measured = ns.nanoTime() - begin)) {} } else { begin = (begin = ns())[0] + (begin[1] / divisor); - while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) { } + while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) {} divisor = 1; } } else if (ns.now) { begin = ns.now(); - while (!(measured = ns.now() - begin)) { } + while (!(measured = ns.now() - begin)) {} } else { begin = new ns().getTime(); - while (!(measured = new ns().getTime() - begin)) { } + while (!(measured = new ns().getTime() - begin)) {} } // check for broken timers (`nanoTime` may have issues) // http://alivebutsleepy.srnet.cz/unreliable-system-nanotime/ @@ -1828,7 +1828,7 @@ if (typeof timer.ns.nanoTime() == 'number') { timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' }); } - } catch(e) { } + } catch(e) {} // detect Chrome's microsecond timer: // enable benchmarking via the --enable-benchmarking command @@ -1837,7 +1837,7 @@ if ((timer.ns = new (context.chrome || context.chromium).Interval)) { timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' }); } - } catch(e) { } + } catch(e) {} // detect Node.js's nanosecond resolution timer available in Node.js >= 0.8 if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') { diff --git a/vendor/platform.js/platform.js b/vendor/platform.js/platform.js index 5e89124717..498ef8f23c 100644 --- a/vendor/platform.js/platform.js +++ b/vendor/platform.js/platform.js @@ -1,12 +1,12 @@ /*! - * Platform.js v1.1.0 + * Platform.js v1.2.0 * Copyright 2010-2014 John-David Dalton * Available under MIT license */ ;(function() { 'use strict'; - /** Used to determine if values are of the language type Object */ + /** Used to determine if values are of the language type `Object` */ var objectTypes = { 'function': true, 'object': true @@ -66,6 +66,60 @@ return string.charAt(0).toUpperCase() + string.slice(1); } + /** + * A utility function to clean up the OS name. + * + * @private + * @param {string} os The OS name to clean up. + * @param {string} [pattern] A `RegExp` pattern matching the OS name. + * @param {string} [label] A label for the OS. + */ + function cleanupOS(os, pattern, label) { + // platform tokens defined at + // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + var data = { + '6.3': '8.1', + '6.2': '8', + '6.1': 'Server 2008 R2 / 7', + '6.0': 'Server 2008 / Vista', + '5.2': 'Server 2003 / XP 64-bit', + '5.1': 'XP', + '5.01': '2000 SP1', + '5.0': '2000', + '4.0': 'NT', + '4.90': 'ME' + }; + // detect Windows version from platform tokens + if (pattern && label && /^Win/i.test(os) && + (data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(os)])) { + os = 'Windows ' + data; + } + // correct character case and cleanup + os = String(os); + + if (pattern && label) { + os = os.replace(RegExp(pattern, 'i'), label); + } + + os = format( + os.replace(/ ce$/i, ' CE') + .replace(/hpw/i, 'web') + .replace(/Macintosh/, 'Mac OS') + .replace(/_PowerPC/i, ' OS') + .replace(/(OS X) [^ \d]+/i, '$1') + .replace(/Mac (OS X)/, '$1') + .replace(/\/(\d)/, ' $1') + .replace(/_/g, '.') + .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') + .replace(/x86\.64/gi, 'x86_64') + .replace(/(Windows Phone)(?! OS)/, '$1 OS') + .split(' on ')[0] + ); + + return os; + } + /** * An iteration utility for arrays and objects. * @@ -116,11 +170,11 @@ } /** - * Gets the internal [[Class]] of a value. + * Gets the internal `[[Class]]` of a value. * * @private * @param {*} value The value. - * @returns {string} The [[Class]]. + * @returns {string} The `[[Class]]`. */ function getClassOf(value) { return value == null @@ -222,7 +276,7 @@ ? !!nav.likeChrome : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); - /** Internal [[Class]] value shortcuts */ + /** Internal `[[Class]]` value shortcuts */ var objectClass = 'Object', airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', enviroClass = isCustomContext ? objectClass : 'Environment', @@ -245,13 +299,13 @@ var doc = context.document || {}; /** - * Detect Opera browser + * Detect Opera browser (Presto-based) * http://www.howtocreate.co.uk/operaStuff/operaObject.html * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini */ var opera = context.operamini || context.opera; - /** Opera [[Class]] */ + /** Opera `[[Class]]` */ var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) ? operaClass : (opera = null); @@ -276,6 +330,9 @@ /** The browser/environment version */ var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); + /** A flag to indicate if the OS ends with "/ Version" */ + var isSpecialCasedOS; + /* Detectable layout engines (order is important) */ var layout = getLayout([ { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, @@ -293,6 +350,7 @@ 'Adobe AIR', 'Arora', 'Avant Browser', + 'Breach', 'Camino', 'Epiphany', 'Fennec', @@ -320,6 +378,7 @@ 'Swiftfox', 'WebPositive', 'Opera Mini', + { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, 'Opera', { 'label': 'Opera', 'pattern': 'OPR' }, 'Chrome', @@ -366,12 +425,12 @@ 'BlackBerry': { 'PlayBook': 1 }, 'Google': { 'Google TV': 1 }, 'HP': { 'TouchPad': 1 }, - 'HTC': { }, - 'LG': { }, + 'HTC': {}, + 'LG': {}, 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, 'Motorola': { 'Xoom': 1 }, 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, - 'Nokia': { }, + 'Nokia': {}, 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, 'Sony': { 'PlayStation 4': 1, 'PlayStation 3': 1, 'PlayStation Vita': 1 } }); @@ -426,7 +485,7 @@ * Picks the manufacturer from an array of guesses. * * @private - * @param {Object} guesses An object of guesses. + * @param {Array} guesses An object of guesses. * @returns {null|string} The detected manufacturer. */ function getManufacturer(guesses) { @@ -468,40 +527,7 @@ if (!result && (result = RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) )) { - // platform tokens defined at - // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - data = { - '6.3': '8.1', - '6.2': '8', - '6.1': 'Server 2008 R2 / 7', - '6.0': 'Server 2008 / Vista', - '5.2': 'Server 2003 / XP 64-bit', - '5.1': 'XP', - '5.01': '2000 SP1', - '5.0': '2000', - '4.0': 'NT', - '4.90': 'ME' - }; - // detect Windows version from platform tokens - if (/^Win/i.test(result) && - (data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) { - result = 'Windows ' + data; - } - // correct character case and cleanup - result = format(String(result) - .replace(RegExp(pattern, 'i'), guess.label || guess) - .replace(/ ce$/i, ' CE') - .replace(/hpw/i, 'web') - .replace(/Macintosh/, 'Mac OS') - .replace(/_PowerPC/i, ' OS') - .replace(/(OS X) [^ \d]+/i, '$1') - .replace(/Mac (OS X)/, '$1') - .replace(/\/(\d)/, ' $1') - .replace(/_/g, '.') - .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') - .replace(/x86\.64/gi, 'x86_64') - .split(' on ')[0]); + result = cleanupOS(result, pattern, guess.label || guess); } return result; }); @@ -578,6 +604,10 @@ if (/\bSimulator\b/i.test(ua)) { product = (product ? product + ' ' : '') + 'Simulator'; } + // detect Opera Mini 8+ running in Turbo / Uncompressed mode on iOS + if (name == 'Opera Mini' && /OPiOS/.test(ua)) { + description.push('running in Turbo / Uncompressed mode'); + } // detect iOS if (/^iP/.test(product)) { name || (name = 'Safari'); @@ -618,7 +648,7 @@ // detect non-Opera versions (order is important) if (!version) { version = getVersion([ - '(?:Cloud9|CriOS|CrMo|Iron|Opera ?Mini|OPR|Raven|Silk(?!/[\\d.]+$))', + '(?:Cloud9|CriOS|CrMo|Iron|Opera ?Mini|OPiOS|OPR|Raven|Silk(?!/[\\d.]+$))', 'Version', qualify(name), '(?:Firefox|Minefield|NetFront)' @@ -639,9 +669,12 @@ layout = ['NetFront']; } // detect IE 11 and above - if (!name && layout == 'Trident') { + if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { + if (name) { + description.push('identifying as ' + name + (version ? ' ' + version : '')); + } name = 'IE'; - version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]; + version = data[1]; } // leverage environment features if (useFeatures) { @@ -653,28 +686,23 @@ arch = data.getProperty('os.arch'); os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); } - if (isHostType(context, 'exports')) { - if (isModuleScope && isHostType(context, 'system') && (data = [context.system])[0]) { - os || (os = data[0].os || null); - try { - data[1] = (data[1] = context.require) && data[1]('ringo/engine').version; - version = data[1].join('.'); - name = 'RingoJS'; - } catch(e) { - if (data[0].global.system == context.system) { - name = 'Narwhal'; - } + if (isModuleScope && isHostType(context, 'system') && (data = [context.system])[0]) { + os || (os = data[0].os || null); + try { + data[1] = context.require('ringo/engine').version; + version = data[1].join('.'); + name = 'RingoJS'; + } catch(e) { + if (data[0].global.system == context.system) { + name = 'Narwhal'; } } - else if (typeof context.process == 'object' && (data = context.process)) { - name = 'Node.js'; - arch = data.arch; - os = data.platform; - version = /[\d.]+/.exec(data.version)[0]; - } - else if (rhino) { - name = 'Rhino'; - } + } + else if (typeof context.process == 'object' && (data = context.process)) { + name = 'Node.js'; + arch = data.arch; + os = data.platform; + version = /[\d.]+/.exec(data.version)[0]; } else if (rhino) { name = 'Rhino'; @@ -875,7 +903,7 @@ // add layout engine if (layout && !/Avant|Nook/.test(name) && ( /Browser|Lunascape|Maxthon/.test(name) || - /^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) { + /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) { // don't add layout details to description if they are falsey (data = layout[layout.length - 1]) && description.push(data); } @@ -894,13 +922,14 @@ // parse OS into an object if (os) { data = / ([\d.+]+)$/.exec(os); + isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; os = { 'architecture': 32, - 'family': data ? os.replace(data[0], '') : os, + 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, 'version': data ? data[1] : null, 'toString': function() { var version = this.version; - return this.family + (version ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); + return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); } }; } @@ -911,7 +940,7 @@ os.family = os.family.replace(RegExp(' *' + data), ''); } if (name && (/WOW64/i.test(ua) || - (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) { + (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/^win32$/i.test(nav.platform)))) { description.unshift('32-bit'); } } @@ -1011,6 +1040,11 @@ /** * The family of the OS. * + * Common values include: + * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", + * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", + * "Android", "iOS" and "Windows Phone OS" + * * @memberOf platform.os * @type string|null */ diff --git a/vendor/qunit-extras/qunit-extras.js b/vendor/qunit-extras/qunit-extras.js index 2d6aaeea75..e8ad1062e9 100644 --- a/vendor/qunit-extras/qunit-extras.js +++ b/vendor/qunit-extras/qunit-extras.js @@ -186,7 +186,7 @@ var moduleName, modulePrinted; - /** Object shortcuts */ + /** Object references */ var phantom = context.phantom, define = context.define, document = !phantom && context.document, @@ -324,7 +324,7 @@ if (!amd && typeof require == 'function') { try { return require('system').env[name]; - } catch(e) { } + } catch(e) {} } } @@ -557,7 +557,7 @@ } else { process.exit(0); } - } catch(e) { } + } catch(e) {} // exit out of Narwhal, Rhino, or RingoJS try { @@ -566,7 +566,7 @@ } else { quit(); } - } catch(e) { } + } catch(e) {} }; }()); @@ -687,9 +687,9 @@ context.setTimeout = setTimeout; } }()); - } catch(e) { } + } catch(e) {} - // expose shortcuts + // expose QUnit API on `context` // exclude `module` because some environments have it as a built-in object ('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' + 'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) { From a6ac62d628613458af2f6d2e86f2f4a8f0181a5b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 28 Jul 2014 23:23:43 -0700 Subject: [PATCH 0989/1608] Update tested versions of Opera and PhantomJS. [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea153fc6e9..48d707cd0b 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# ## Support -Tested in Chrome (19, 35-36), Firefox (3, 20, 29-30), IE 6-11, Opera 21-22, Safari 5-7, Node.js 0.8.26~0.10.29, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 35-36), Firefox (3, 20, 29-30), IE 6-11, Opera 22-23, Safari 5-7, Node.js 0.8.26~0.10.29, PhantomJS 1.9.7, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. From eaee1882449e80bee976026949039bd05398aa65 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 29 Jul 2014 08:47:23 -0700 Subject: [PATCH 0990/1608] Use `resIndex` where applied easily. --- lodash.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lodash.js b/lodash.js index b8afb9522c..e5b4200107 100644 --- a/lodash.js +++ b/lodash.js @@ -1165,12 +1165,13 @@ function arrayFilter(array, predicate) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { - result.push(value); + result[++resIndex] = value; } } return result; @@ -1928,12 +1929,13 @@ var index = -1, props = keysFunc(object), length = props.length, + resIndex = -1, result = []; while (++index < length) { var key = props[index]; if (isFunction(object[key])) { - result.push(key); + result[++resIndex] = key; } } return result; @@ -2958,12 +2960,13 @@ function replaceHolders(array, placeholder) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; - result.push(index); + result[++resIndex] = index; } } return result; @@ -3068,6 +3071,7 @@ var seen, index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { @@ -3076,7 +3080,7 @@ if (!index || seen !== computed) { seen = computed; - result.push(value); + result[++resIndex] = value; } } return result; @@ -3142,11 +3146,12 @@ function chunk(array, chunkSize) { var index = 0, length = array ? array.length : 0, + resIndex = -1, result = []; chunkSize = nativeMax(+chunkSize || 1, 1); while (index < length) { - result.push(slice(array, index, (index += chunkSize))); + result[++resIndex] = slice(array, index, (index += chunkSize)); } return result; } From 79b706fb5c25c171814fd227d7f446d08f787da1 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 29 Jul 2014 08:48:04 -0700 Subject: [PATCH 0991/1608] Add parentheses to clarify things. --- lodash.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodash.js b/lodash.js index e5b4200107..ef47add8c2 100644 --- a/lodash.js +++ b/lodash.js @@ -2063,7 +2063,7 @@ return (value != +value) ? other != +other // but treat `-0` vs. `+0` as not equal - : (value == 0 ? (1 / value == 1 / other) : value == +other); + : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); case regexpClass: case stringClass: @@ -2407,7 +2407,7 @@ while (low < high) { var mid = (low + high) >>> 1, computed = iterator(array[mid]), - setLow = retHighest ? computed <= value : computed < value; + setLow = retHighest ? (computed <= value) : (computed < value); if (hintNum && typeof computed != 'undefined') { computed = +computed; @@ -2915,7 +2915,7 @@ * equality comparisons, else `false`. */ function isStrictComparable(value) { - return value === value && (value === 0 ? (1 / value > 0) : !isObject(value)); + return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value)); } /** From 6fdaf905c40d5c91ca9e608af99d9dffeb73901e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 29 Jul 2014 09:36:39 -0700 Subject: [PATCH 0992/1608] Update "features" section of readme. [ci skip] --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 48d707cd0b..f74d938aa1 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# * Follows [semantic versioning](http://semver.org/) for releases * [_(…)](http://lodash.com/docs#_) supports intuitive chaining * [_.at](http://lodash.com/docs#at) for cherry-picking collection values + * [_.attempt](http://lodash.com/docs#attempt) to execute functions which may error without a try-catch + * [_.before](http://lodash.com/docs#before) to complement [_.after](http://lodash.com/docs#after) * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”*](http://michaux.ca/articles/lazy-function-definition-pattern) defined methods * [_.callback](http://lodash.com/docs#createCallback) for extending callbacks in methods & mixins * [_.chunk](http://lodash.com/docs#chunk) for splitting an array into chunks of a given size @@ -74,15 +76,15 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` * [_.create](http://lodash.com/docs#create) for easier object inheritance - * [_.curry](http://lodash.com/docs#curry) for creating [curried](http://hughfdjackson.com/javascript/why-curry-helps/) functions - * [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) accept additional `options` for more control + * [_.curry](http://lodash.com/docs#curry) & [_.curryRight](http://lodash.com/docs#curryRight) for creating [curried](http://hughfdjackson.com/javascript/why-curry-helps/) functions + * [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) are cancelable & accept options for more control * [_.findIndex](http://lodash.com/docs#findIndex) & [_.findKey](http://lodash.com/docs#findKey) for finding indexes & keys * [_.forEach](http://lodash.com/docs#forEach) supports exiting early - * [_.forIn](http://lodash.com/docs#forIn) for iterating own & inherited properties + * [_.forIn](http://lodash.com/docs#forIn) for iterating all enumerable properties * [_.forOwn](http://lodash.com/docs#forOwn) for iterating own properties * [_.isError](http://lodash.com/docs#isError) to check for error objects * [_.isPlainObject](http://lodash.com/docs#isPlainObject) to check for objects created by `Object` - * [_.keysIn](http://lodash.com/docs#keysIn) & [_.valuesIn](http://lodash.com/docs#valuesIn) for keys and values of own & inherited properties + * [_.keysIn](http://lodash.com/docs#keysIn) & [_.valuesIn](http://lodash.com/docs#valuesIn) for getting keys and values of all enumerable properties * [_.mapValues](http://lodash.com/docs#mapValues) for [mapping](http://lodash.com/docs#map) values to an object * [_.memoize](http://lodash.com/docs#memoize) exposes the `cache` of memoized functions * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend) @@ -95,13 +97,13 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# * [_.slice](http://lodash.com/docs#slice) for creating subsets of array-like values * [_.sortBy](http://lodash.com/docs#sortBy) supports sorting by multiple properties * [_.support](http://lodash.com/docs#support) for flagging environment features - * [_.template](http://lodash.com/docs#template) supports [*“imports”*](http://lodash.com/docs#templateSettings_imports) options & [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals) + * [_.template](http://lodash.com/docs#template) supports [*“imports”*](http://lodash.com/docs#templateSettings_imports) options & [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) * [_.transform](http://lodash.com/docs#transform) as a powerful alternative to [_.reduce](http://lodash.com/docs#reduce) for transforming objects * [_.where](http://lodash.com/docs#where) supports deep object comparisons * [_.xor](http://lodash.com/docs#xor) to complement [_.difference](http://lodash.com/docs#difference), [_.intersection](http://lodash.com/docs#intersection), & [_.union](http://lodash.com/docs#union) * [_.zip](http://lodash.com/docs#zip) is capable of unzipping values * [_.bind](http://lodash.com/docs#bind), [_.curry](http://lodash.com/docs#curry), [_.partial](http://lodash.com/docs#partial), & - [more](http://lodash.com/docs "_.bindKey, _.partialRight") support argument placeholders + [more](http://lodash.com/docs "_.bindKey, _.curryRight, _.partialRight") support argument placeholders * [_.capitalize](http://lodash.com/docs#capitalize), [_.trim](http://lodash.com/docs#trim), & [more](http://lodash.com/docs "_.camelCase, _.endsWith, _.escapeRegExp, _.kebabCase, _.pad, _.padLeft, _.padRight, _.repeat, _.snakeCase, _.startsWith, _.trimLeft, _.trimRight, _.trunc") string methods * [_.contains](http://lodash.com/docs#contains), [_.toArray](http://lodash.com/docs#toArray), & From e48b314ad00613f2fcd27f9e6f54f64da33e6ee5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 29 Jul 2014 09:37:25 -0700 Subject: [PATCH 0993/1608] Avoid type coercion of `size` in `_.chunk` unless needed. --- lodash.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lodash.js b/lodash.js index ef47add8c2..81a603b6d4 100644 --- a/lodash.js +++ b/lodash.js @@ -3125,7 +3125,7 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array of elements split into groups the length of `chunkSize`. + * Creates an array of elements split into groups the length of `size`. * If `collection` can't be split evenly, the final chunk will be the remaining * elements. * @@ -3133,7 +3133,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to process. - * @param {numer} [chunkSize=1] The size of each chunk. + * @param {numer} [size=1] The length of each chunk. * @returns {Array} Returns the new array containing chunks. * @example * @@ -3143,15 +3143,15 @@ * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ - function chunk(array, chunkSize) { + function chunk(array, size) { var index = 0, length = array ? array.length : 0, resIndex = -1, result = []; - chunkSize = nativeMax(+chunkSize || 1, 1); + size = typeof size == 'undefined' ? 1 : nativeMax(+size || 1, 1); while (index < length) { - result[++resIndex] = slice(array, index, (index += chunkSize)); + result[++resIndex] = slice(array, index, (index += size)); } return result; } From 9032cc0ecca4c0a0a22386039de8002750602034 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 29 Jul 2014 22:21:22 -0700 Subject: [PATCH 0994/1608] Updated tested Chrome versions in Sauce. --- test/saucelabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index eb0101af09..fbfc864991 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -102,8 +102,8 @@ var platforms = [ ['Windows 8.1', 'firefox', '29'], ['Windows 8.1', 'firefox', '20'], ['Windows 8.1', 'firefox', '3.0'], + ['Windows 8.1', 'chrome', '36'], ['Windows 8.1', 'chrome', '35'], - ['Windows 8.1', 'chrome', '34'], ['Windows 8.1', 'internet explorer', '11'], ['Windows 8', 'internet explorer', '10'], ['Windows 7', 'internet explorer', '9'], From 5cbc44610cbaf7a2a8e10280c909977315ae4642 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 30 Jul 2014 00:00:22 -0700 Subject: [PATCH 0995/1608] Simplify support property detection. --- lodash.js | 6 ++---- test/index.html | 23 ++++++++++------------- test/test.js | 6 +++--- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/lodash.js b/lodash.js index 81a603b6d4..77a73250b8 100644 --- a/lodash.js +++ b/lodash.js @@ -852,8 +852,6 @@ Ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new Ctor) { props.push(key); } - for (var argsKey in arguments) {} - for (var strKey in 'x') {} /** * Detect if the `[[Class]]` of `arguments` objects is resolvable @@ -912,7 +910,7 @@ * @memberOf _.support * @type boolean */ - support.nonEnumStrings = strKey != '0'; + support.nonEnumStrings = !propertyIsEnumerable.call('x', 0); /** * Detect if properties shadowing those on `Object.prototype` are @@ -1001,7 +999,7 @@ * @type boolean */ try { - support.nonEnumArgs = !(hasOwnProperty.call(arguments, 1) && propertyIsEnumerable.call(arguments, 1)); + support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); } catch(e) { support.nonEnumArgs = true; } diff --git a/test/index.html b/test/index.html index 598d3a9c0e..67e85f4e4c 100644 --- a/test/index.html +++ b/test/index.html @@ -100,19 +100,16 @@ setProperty(Object, '_keys', Object.keys); setProperty(Object, 'keys', noop); - setProperty(objectProto, 'hasOwnProperty', (function() { - function wrapper(key) { - if (key == '1' && this && typeof this == 'object' && this.length === 2 && - hasOwnProperty.call(this, 'callee') && - !propertyIsEnumerable.call(this, 'callee') && - this[0] === 0 && this[1] === 0) { - throw new Error; - } - return hasOwnProperty.call(this, key); + setProperty(objectProto, '_propertyIsEnumerable', propertyIsEnumerable); + setProperty(objectProto, 'propertyIsEnumerable', function(key) { + if (key == '1' && this && typeof this == 'object' && this.length === 2 && + hasOwnProperty.call(this, 'callee') && + !propertyIsEnumerable.call(this, 'callee') && + this[0] === 0 && this[1] === 0) { + throw new Error; } - setProperty(objectProto, '_hasOwnProperty', hasOwnProperty); - return wrapper; - }())); + return propertyIsEnumerable.call(this, key); + }); setProperty(Number, '_isFinite', Number.isFinite); setProperty(Number, 'isFinite', noop); @@ -228,7 +225,7 @@ } else { delete stringProto.contains; } - setProperty(objectProto, 'hasOwnProperty', objectProto._hasOwnProperty); + setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable); document.createDocumentFragment = document._createDocumentFragment; setProperty(document, '_createDocumentFragment', undefined); diff --git a/test/test.js b/test/test.js index e77cb4c0c2..918bb88ec0 100644 --- a/test/test.js +++ b/test/test.js @@ -375,8 +375,8 @@ var _keys = Object.keys; setProperty(Object, 'keys', _.noop); - var _hasOwnProperty = objectProto.hasOwnProperty; - setProperty(objectProto, 'hasOwnProperty', function(key) { + var _propertyIsEnumerable = objectProto.propertyIsEnumerable; + setProperty(objectProto, 'propertyIsEnumerable', function(key) { if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0])) { throw new Error; } @@ -463,7 +463,7 @@ setProperty(Object, 'getPrototypeOf', _getPrototypeOf); setProperty(Object, 'keys', _keys); - setProperty(objectProto, 'hasOwnProperty', _hasOwnProperty); + setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable); setProperty(root, 'parseInt', _parseInt); if (_isFinite) { From d2870b6df75de7077b84b297db84803e9475c43c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 31 Jul 2014 17:25:58 -0700 Subject: [PATCH 0996/1608] Change strict equality matches to SameValueZero matches. --- lodash.js | 93 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/lodash.js b/lodash.js index 77a73250b8..d793e045e5 100644 --- a/lodash.js +++ b/lodash.js @@ -350,10 +350,12 @@ */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; + length = array ? array.length : 0, + nans = value !== value; while (++index < length) { - if (array[index] === value) { + var other = array[index]; + if (other === value || (nans && other !== other)) { return index; } } @@ -1657,7 +1659,7 @@ while (++index < length) { var value = array[index]; - if (isCommon) { + if (isCommon && value === value) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { @@ -2449,7 +2451,7 @@ var value = array[index], computed = iterator ? iterator(value, index, array) : value; - if (isCommon) { + if (isCommon && value === value) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { @@ -3184,8 +3186,12 @@ } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates an array excluding all values of the provided arrays using + * `SameValueZero` for equality comparisons. + * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3552,10 +3558,14 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, + * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, * it is used as the offset from the end of the collection. If `array` is * sorted providing `true` for `fromIndex` performs a faster binary search. * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @category Array @@ -3609,7 +3619,11 @@ /** * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3717,8 +3731,10 @@ index = sortedLastIndex(array, value) - 1; return (length && array[index] === value) ? index : -1; } + var nans = value !== value; while (index--) { - if (array[index] === value) { + var other = array[index]; + if (other === value || (nans && other !== other)) { return index; } } @@ -3726,11 +3742,15 @@ } /** - * Removes all provided values from `array` using strict equality for - * comparisons, i.e. `===`. + * Removes all provided values from `array` using `SameValueZero` for equality + * comparisons. * * Note: Unlike `_.without`, this method mutates `array`. * + * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches + * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @category Array @@ -3747,17 +3767,14 @@ function pull(array) { var argsIndex = 0, argsLength = arguments.length, - length = array ? array.length : 0; + indexOf = getIndexOf(); while (++argsIndex < argsLength) { - var index = -1, + var fromIndex = 0, value = arguments[argsIndex]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); } } return array; @@ -4134,7 +4151,11 @@ /** * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4151,12 +4172,12 @@ } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a - * faster search algorithm for sorted arrays. If an iterator function is - * provided it is executed for each value in the array to generate the criterion - * by which uniqueness is computed. The `iterator` is bound to `thisArg` and - * invoked with three arguments; (value, index, array). + * Creates a duplicate-value-free version of an array using `SameValueZero` + * for equality comparisons. Providing `true` for `isSorted` performs a faster + * search algorithm for sorted arrays. If an iterator function is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The `iterator` is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * * If a property name is provided for `iterator` the created "_.pluck" style * callback returns the property value of the given element. @@ -4165,6 +4186,10 @@ * returns `true` for elements that have the properties of the given object, * else `false`. * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @alias unique @@ -4248,8 +4273,12 @@ } /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * Creates an array excluding all provided values using `SameValueZero` for + * equality comparisons. + * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4507,9 +4536,13 @@ } /** - * Checks if `value` is present in `collection` using strict equality for - * comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. + * Checks if `value` is present in `collection` using `SameValueZero` for + * equality comparisons. If `fromIndex` is negative, it is used as the offset + * from the end of the collection. + * + * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ From 2aa94301a859ff4097c8cc40918c61abbc67de2c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 1 Aug 2014 11:13:58 -0700 Subject: [PATCH 0997/1608] Rename `iterator` to `iteratee`. --- lodash.js | 474 +++++++++++++++++++++++++++--------------------------- 1 file changed, 237 insertions(+), 237 deletions(-) diff --git a/lodash.js b/lodash.js index d793e045e5..53987c9916 100644 --- a/lodash.js +++ b/lodash.js @@ -1076,15 +1076,15 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEach(array, iterator) { + function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { - if (iterator(array[index], index, array) === false) { + if (iteratee(array[index], index, array) === false) { break; } } @@ -1097,14 +1097,14 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEachRight(array, iterator) { + function arrayEachRight(array, iteratee) { var length = array.length; while (length--) { - if (iterator(array[length], length, array) === false) { + if (iteratee(array[length], length, array) === false) { break; } } @@ -1139,16 +1139,16 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function arrayMap(array, iterator) { + function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { - result[index] = iterator(array[index], index, array); + result[index] = iteratee(array[index], index, array); } return result; } @@ -1183,13 +1183,13 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduce(array, iterator, accumulator, initFromArray) { + function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; @@ -1197,7 +1197,7 @@ accumulator = array[++index]; } while (++index < length) { - accumulator = iterator(accumulator, array[index], index, array); + accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } @@ -1208,20 +1208,20 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduceRight(array, iterator, accumulator, initFromArray) { + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { var length = array.length; if (initFromArray && length) { accumulator = array[--length]; } while (length--) { - accumulator = iterator(accumulator, array[length], length, array); + accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } @@ -1681,19 +1681,19 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEach(collection, iterator) { + function baseEach(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwn(collection, iterator); + return baseForOwn(collection, iteratee); } var index = -1, iterable = toIterable(collection); while (++index < length) { - if (iterator(iterable[index], index, iterable) === false) { + if (iteratee(iterable[index], index, iterable) === false) { break; } } @@ -1706,17 +1706,17 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEachRight(collection, iterator) { + function baseEachRight(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwnRight(collection, iterator); + return baseForOwnRight(collection, iteratee); } var iterable = toIterable(collection); while (length--) { - if (iterator(iterable[length], length, iterable) === false) { + if (iteratee(iterable[length], length, iterable) === false) { break; } } @@ -1830,24 +1830,24 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iterator` for + * over `object` properties returned by `keysFunc` executing `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseFor(object, iterator, keysFunc) { + function baseFor(object, iteratee, keysFunc) { var index = -1, props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; - if (iterator(object[key], key, object) === false) { + if (iteratee(object[key], key, object) === false) { break; } } @@ -1860,17 +1860,17 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForRight(object, iterator, keysFunc) { + function baseForRight(object, iteratee, keysFunc) { var props = keysFunc(object), length = props.length; while (length--) { var key = props[length]; - if (iterator(object[key], key, object) === false) { + if (iteratee(object[key], key, object) === false) { break; } } @@ -1883,11 +1883,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForIn(object, iterator) { - return baseFor(object, iterator, keysIn); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); } /** @@ -1896,11 +1896,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwn(object, iterator) { - return baseFor(object, iterator, keys); + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); } /** @@ -1909,11 +1909,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwnRight(object, iterator) { - return baseForRight(object, iterator, keys); + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); } /** @@ -2166,14 +2166,14 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function baseMap(collection, iterator) { + function baseMap(collection, iteratee) { var result = []; baseEach(collection, function(value, key, collection) { - result.push(iterator(value, key, collection)); + result.push(iteratee(value, key, collection)); }); return result; } @@ -2347,18 +2347,18 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ - function baseReduce(collection, iterator, accumulator, initFromCollection, eachFunc) { + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) - : iterator(accumulator, value, index, collection) + : iteratee(accumulator, value, index, collection) }); return accumulator; } @@ -2390,23 +2390,23 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ - function baseSortedIndex(array, value, iterator, retHighest) { + function baseSortedIndex(array, value, iteratee, retHighest) { var low = 0, high = array ? array.length : low; - value = iterator(value); + value = iteratee(value); var hintNum = typeof value == 'number' || (value != null && isFunction(value.valueOf) && typeof value.valueOf() == 'number'); while (low < high) { var mid = (low + high) >>> 1, - computed = iterator(array[mid]), + computed = iteratee(array[mid]), setLow = retHighest ? (computed <= value) : (computed < value); if (hintNum && typeof computed != 'undefined') { @@ -2428,10 +2428,10 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function baseUniq(array, iterator) { + function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), length = array.length, @@ -2444,12 +2444,12 @@ var seen = createCache(); indexOf = cacheIndexOf; } else { - seen = iterator ? [] : result; + seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; if (isCommon && value === value) { var seenIndex = seen.length; @@ -2458,13 +2458,13 @@ continue outer; } } - if (iterator) { + if (iteratee) { seen.push(computed); } result.push(value); } else if (indexOf(seen, computed) < 0) { - if (iterator || isLarge) { + if (iteratee || isLarge) { seen.push(computed); } result.push(value); @@ -2560,7 +2560,7 @@ /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection - * through `iterator`. The given setter function sets the keys and values of + * through `iteratee`. The given setter function sets the keys and values of * the accumulator object. If `initializer` is provided it is used to initialize * the accumulator object. * @@ -2570,9 +2570,9 @@ * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { - return function(collection, iterator, thisArg) { + return function(collection, iteratee, thisArg) { var result = initializer ? initializer() : {}; - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, @@ -2580,11 +2580,11 @@ while (++index < length) { var value = collection[index]; - setter(result, value, iterator(value, index, collection), collection); + setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { - setter(result, value, iterator(value, key, collection), collection); + setter(result, value, iteratee(value, key, collection), collection); }); } return result; @@ -3064,10 +3064,10 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function sortedUniq(array, iterator) { + function sortedUniq(array, iteratee) { var seen, index = -1, length = array.length, @@ -3076,7 +3076,7 @@ while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; if (!index || seen !== computed) { seen = computed; @@ -3916,14 +3916,14 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iterator function is provided it is executed for `value` - * and each element of `array` to compute their sort ranking. The iterator + * of the array. If an iteratee function is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -3932,10 +3932,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -3948,7 +3948,7 @@ * * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * - * // using an iterator function + * // using an iteratee function * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { * return this.data[word]; * }, dict); @@ -3958,9 +3958,9 @@ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ - function sortedIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : getCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator); + function sortedIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee); } /** @@ -3973,10 +3973,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -3984,9 +3984,9 @@ * _.sortedLastIndex([4, 4, 5, 5, 6, 6], 5); * // => 4 */ - function sortedLastIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : getCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator, true); + function sortedLastIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee, true); } /** @@ -4174,15 +4174,15 @@ /** * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster - * search algorithm for sorted arrays. If an iterator function is provided it + * search algorithm for sorted arrays. If an iteratee function is provided it * is executed for each value in the array to generate the criterion by which - * uniqueness is computed. The `iterator` is bound to `thisArg` and invoked + * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4196,10 +4196,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new duplicate-value-free array. * @example * @@ -4210,7 +4210,7 @@ * _.uniq([1, 1, 2], true); * // => [1, 2] * - * // using an iterator function + * // using an iteratee function * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); * // => [1, 2.5] * @@ -4218,7 +4218,7 @@ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ - function uniq(array, isSorted, iterator, thisArg) { + function uniq(array, isSorted, iteratee, thisArg) { var length = array ? array.length : 0; if (!length) { return []; @@ -4226,21 +4226,21 @@ // juggle arguments var type = typeof isSorted; if (type != 'boolean' && isSorted != null) { - thisArg = iterator; - iterator = isSorted; + thisArg = iteratee; + iteratee = isSorted; isSorted = false; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === array) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === array) { + iteratee = null; } } - if (iterator != null) { - iterator = getCallback(iterator, thisArg, 3); + if (iteratee != null) { + iteratee = getCallback(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) - ? sortedUniq(array, iterator) - : baseUniq(array, iterator); + ? sortedUniq(array, iteratee) + : baseUniq(array, iteratee); } /** @@ -4591,15 +4591,15 @@ /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding value - * of each key is the number of times the key was returned by `iterator`. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the number of times the key was returned by `iteratee`. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4607,10 +4607,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4827,8 +4827,8 @@ } /** - * Iterates over elements of `collection` executing `iterator` for each - * element. The `iterator` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` executing `iteratee` for each + * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -4841,8 +4841,8 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * @@ -4852,10 +4852,10 @@ * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); * // => logs each value-key pair and returns the object (property order is not guaranteed across environments) */ - function forEach(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, iterator) - : baseEach(collection, baseCallback(iterator, thisArg, 3)); + function forEach(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, baseCallback(iteratee, thisArg, 3)); } /** @@ -4867,31 +4867,31 @@ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each value from right to left and returns the array */ - function forEachRight(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEachRight(collection, iterator) - : baseEachRight(collection, baseCallback(iterator, thisArg, 3)); + function forEachRight(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEachRight(collection, iteratee) + : baseEachRight(collection, baseCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding + * each element of `collection` through `iteratee`. The corresponding * value of each key is an array of the elements responsible for generating - * the key. The `iterator` is bound to `thisArg` and invoked with three + * the key. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4899,10 +4899,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4926,15 +4926,15 @@ /** * Creates an object composed of keys generated from the results of running - * each element of the collection through `iterator`. The corresponding value + * each element of the collection through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4942,10 +4942,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4995,13 +4995,13 @@ /** * Creates an array of values by running each element in the collection through - * `iterator`. The `iterator` is bound to `thisArg` and invoked with three + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5010,10 +5010,10 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * @@ -5032,24 +5032,24 @@ * _.map(characters, 'name'); * // => ['barney', 'fred'] */ - function map(collection, iterator, thisArg) { - iterator = getCallback(iterator, thisArg, 3); + function map(collection, iteratee, thisArg) { + iteratee = getCallback(iteratee, thisArg, 3); var func = isArray(collection) ? arrayMap : baseMap; - return func(collection, iterator); + return func(collection, iteratee); } /** * Retrieves the maximum value of `collection`. If the collection is empty - * or falsey `-Infinity` is returned. If an iterator function is provided it + * or falsey `-Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5057,10 +5057,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * @@ -5082,16 +5082,16 @@ * _.max(characters, 'age'); * // => { 'name': 'fred', 'age': 40 }; */ - function max(collection, iterator, thisArg) { + function max(collection, iteratee, thisArg) { var computed = -Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - var noIterator = iterator == null, + var noIterator = iteratee == null, isArr = noIterator && isArray(collection), isStr = !isArr && isString(collection); @@ -5107,12 +5107,12 @@ } } } else { - iterator = (noIterator && isStr) + iteratee = (noIterator && isStr) ? charAtCallback - : getCallback(iterator, thisArg, 3); + : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current > computed || (current === -Infinity && current === result)) { computed = current; result = value; @@ -5124,15 +5124,15 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty - * or falsey `Infinity` is returned. If an iterator function is provided it + * or falsey `Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5140,10 +5140,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * @@ -5165,16 +5165,16 @@ * _.min(characters, 'age'); * // => { 'name': 'barney', 'age': 36 }; */ - function min(collection, iterator, thisArg) { + function min(collection, iteratee, thisArg) { var computed = Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - var noIterator = iterator == null, + var noIterator = iteratee == null, isArr = noIterator && isArray(collection), isStr = !isArr && isString(collection); @@ -5190,12 +5190,12 @@ } } } else { - iterator = (noIterator && isStr) + iteratee = (noIterator && isStr) ? charAtCallback - : getCallback(iterator, thisArg, 3); + : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current < computed || (current === Infinity && current === result)) { computed = current; result = value; @@ -5278,10 +5278,10 @@ /** * Reduces a collection to a value which is the accumulated result of running - * each element in the collection through `iterator`, where each successive + * each element in the collection through `iteratee`, where each successive * execution consumes the return value of the previous execution. If `accumulator` * is not provided the first element of the collection is used as the initial - * value. The `iterator` is bound to `thisArg`and invoked with four arguments; + * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * * @static @@ -5289,9 +5289,9 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -5304,9 +5304,9 @@ * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } */ - function reduce(collection, iterator, accumulator, thisArg) { + function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; - return func(collection, getCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEach); + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** @@ -5318,9 +5318,9 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -5328,9 +5328,9 @@ * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ - function reduceRight(collection, iterator, accumulator, thisArg) { + function reduceRight(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduceRight : baseReduce; - return func(collection, getCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** @@ -5516,18 +5516,18 @@ /** * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through `iterator`. This method performs + * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an array of property names is provided for `iterator` the collection + * If an array of property names is provided for `iteratee` the collection * is sorted by each property value. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5535,10 +5535,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [iterator=identity] The function + * @param {Array|Function|Object|string} [iteratee=identity] The function * called per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. * @example * @@ -5563,28 +5563,28 @@ * _.map(_.sortBy(characters, ['name', 'age']), _.values); * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ - function sortBy(collection, iterator, thisArg) { + function sortBy(collection, iteratee, thisArg) { var index = -1, length = collection ? collection.length : 0, - multi = iterator && isArray(iterator), + multi = iteratee && isArray(iteratee), result = []; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { result.length = length; } if (!multi) { - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); } baseEach(collection, function(value, key, collection) { if (multi) { - var length = iterator.length, + var length = iteratee.length, criteria = Array(length); while (length--) { - criteria[length] = value[iterator[length]]; + criteria[length] = value[iteratee[length]]; } } else { - criteria = iterator(value, key, collection); + criteria = iteratee(value, key, collection); } result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; }); @@ -6727,7 +6727,7 @@ /** * Iterates over own and inherited enumerable properties of an object executing - * `iterator` for each property. The `iterator` is bound to `thisArg` and invoked + * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * @@ -6735,8 +6735,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6752,11 +6752,11 @@ * }); * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments) */ - function forIn(object, iterator, thisArg) { - if (typeof iterator != 'function' || typeof thisArg != 'undefined') { - iterator = baseCallback(iterator, thisArg, 3); + function forIn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = baseCallback(iteratee, thisArg, 3); } - return baseFor(object, iterator, keysIn); + return baseFor(object, iteratee, keysIn); } /** @@ -6767,8 +6767,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6784,14 +6784,14 @@ * }); * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' */ - function forInRight(object, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); - return baseForRight(object, iterator, keysIn); + function forInRight(object, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keysIn); } /** - * Iterates over own enumerable properties of an object executing `iterator` - * for each property. The `iterator` is bound to `thisArg` and invoked with + * Iterates over own enumerable properties of an object executing `iteratee` + * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * @@ -6799,8 +6799,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6809,11 +6809,11 @@ * }); * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) */ - function forOwn(object, iterator, thisArg) { - if (typeof iterator != 'function' || typeof thisArg != 'undefined') { - iterator = baseCallback(iterator, thisArg, 3); + function forOwn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = baseCallback(iteratee, thisArg, 3); } - return baseForOwn(object, iterator); + return baseForOwn(object, iteratee); } /** @@ -6824,8 +6824,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6834,9 +6834,9 @@ * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ - function forOwnRight(object, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); - return baseForRight(object, iterator, keys); + function forOwnRight(object, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keys); } /** @@ -7536,14 +7536,14 @@ /** * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through `iterator`. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * running each own enumerable property of `object` through `iteratee`. The + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, key, object). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -7551,10 +7551,10 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the new mapped object. * @example * @@ -7570,12 +7570,12 @@ * _.mapValues(characters, 'age'); * // => { 'fred': 40, 'pebbles': 1 } */ - function mapValues(object, iterator, thisArg) { + function mapValues(object, iteratee, thisArg) { var result = {}; - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); baseForOwn(object, function(value, key, object) { - result[key] = iterator(value, key, object); + result[key] = iteratee(value, key, object); }); return result; } @@ -7739,8 +7739,8 @@ /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own - * enumerable properties through `iterator`, with each execution potentially - * mutating the `accumulator` object. The `iterator` is bound to `thisArg` + * enumerable properties through `iteratee`, with each execution potentially + * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. * @@ -7748,9 +7748,9 @@ * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -7767,7 +7767,7 @@ * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ - function transform(object, iterator, accumulator, thisArg) { + function transform(object, iteratee, accumulator, thisArg) { var isArr = isArrayLike(object); if (accumulator == null) { @@ -7781,10 +7781,10 @@ accumulator = baseCreate(proto); } } - if (iterator) { - iterator = getCallback(iterator, thisArg, 4); + if (iteratee) { + iteratee = getCallback(iteratee, thisArg, 4); (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { - return iterator(accumulator, value, index, object); + return iteratee(accumulator, value, index, object); }); } return accumulator; @@ -9113,16 +9113,16 @@ } /** - * Executes the iterator function `n` times, returning an array of the results - * of each execution. The `iterator` is bound to `thisArg` and invoked with + * Executes the iteratee function `n` times, returning an array of the results + * of each execution. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iterator`. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {number} n The number of times to execute `iteratee`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example * @@ -9135,18 +9135,18 @@ * _.times(3, function(n) { this.cast(n); }, mage); * // => also calls `mage.castSpell(n)` three times */ - function times(n, iterator, thisArg) { + function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; - iterator = baseCallback(iterator, thisArg, 1); + iteratee = baseCallback(iteratee, thisArg, 1); var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); while (++index < n) { if (index < MAX_ARRAY_LENGTH) { - result[index] = iterator(index); + result[index] = iteratee(index); } else { - iterator(index); + iteratee(index); } } return result; From 4dc41749fb3d91e464a01cb18f843a32d23ef325 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 1 Aug 2014 11:27:37 -0700 Subject: [PATCH 0998/1608] Cleanup `NaN` handling in `baseIndexOf` and `_.lastINdexOf`. --- lodash.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lodash.js b/lodash.js index 53987c9916..8e9a426e5a 100644 --- a/lodash.js +++ b/lodash.js @@ -351,11 +351,11 @@ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, - nans = value !== value; + isReflexive = value === value; while (++index < length) { var other = array[index]; - if (other === value || (nans && other !== other)) { + if ((isReflexive ? other === value : other !== other)) { return index; } } @@ -3731,10 +3731,10 @@ index = sortedLastIndex(array, value) - 1; return (length && array[index] === value) ? index : -1; } - var nans = value !== value; + var isReflexive = value === value; while (index--) { var other = array[index]; - if (other === value || (nans && other !== other)) { + if ((isReflexive ? other === value : other !== other)) { return index; } } From faf658465281e311384c845b3a244d6ff1d0591b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 1 Aug 2014 16:36:44 -0700 Subject: [PATCH 0999/1608] Ensure `_.mixin` does not extend lodash when an `object` is provided with an empty `options` object. [closes #650] --- lodash.js | 29 ++++++++++++++++------------- test/test.js | 6 ++++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lodash.js b/lodash.js index 8e9a426e5a..0f17f7a5df 100644 --- a/lodash.js +++ b/lodash.js @@ -1917,17 +1917,16 @@ } /** - * The base implementation of `_.functions` which creates an array of function - * property names from those returned by `keysFunc`. + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. * * @private * @param {Object} object The object to inspect. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Array} Returns the new sorted array of property names. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. */ - function baseFunctions(object, keysFunc) { + function baseFunctions(object, props) { var index = -1, - props = keysFunc(object), length = props.length, resIndex = -1, result = []; @@ -6848,14 +6847,14 @@ * @alias methods * @category Object * @param {Object} object The object to inspect. - * @returns {Array} Returns the new sorted array of property names. + * @returns {Array} Returns the new array of property names. * @example * * _.functions(_); * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - return baseFunctions(object, keysIn); + return baseFunctions(object, keysIn(object)); } /** @@ -8784,16 +8783,20 @@ */ function mixin(object, source, options) { var chain = true, - methodNames = source && baseFunctions(source, keys); + isObj = isObject(source), + noOpts = options == null, + props = noOpts && isObj && keys(source), + methodNames = props && baseFunctions(source, props); - if (!source || (!options && !methodNames.length)) { - if (options == null) { + if (!source || (props && props.length && !methodNames.length) || (noOpts && !isObj)) { + if (noOpts) { options = source; } + methodNames = false; source = object; object = this; - methodNames = baseFunctions(source, keys); } + methodNames || (methodNames = baseFunctions(source, keys(source))); if (options === false) { chain = false; } else if (isObject(options) && 'chain' in options) { @@ -8801,7 +8804,7 @@ } var index = -1, isFunc = isFunction(object), - length = methodNames ? methodNames.length : 0; + length = methodNames.length; while (++index < length) { var methodName = methodNames[index], diff --git a/test/test.js b/test/test.js index 918bb88ec0..61e9e41306 100644 --- a/test/test.js +++ b/test/test.js @@ -7554,6 +7554,12 @@ }); }); + test('should not extend lodash when an `object` is provided with an empty `options` object', 1, function() { + _.mixin({ 'a': _.noop }, {}); + ok(!('a' in _)); + delete _.a; + }); + test('should not error for non-object `options` values', 2, function() { var pass = true; From ea219f683ed1cc4cbeacd0387c83e5597be61309 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 2 Aug 2014 13:05:55 -0700 Subject: [PATCH 1000/1608] Rename `noIterator` to `noIteratee`. [ci skip] --- lodash.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lodash.js b/lodash.js index 0f17f7a5df..4d7d767adb 100644 --- a/lodash.js +++ b/lodash.js @@ -5090,11 +5090,11 @@ if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { iteratee = null; } - var noIterator = iteratee == null, - isArr = noIterator && isArray(collection), + var noIteratee = iteratee == null, + isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); - if (noIterator && !isStr) { + if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -5106,7 +5106,7 @@ } } } else { - iteratee = (noIterator && isStr) + iteratee = (noIteratee && isStr) ? charAtCallback : getCallback(iteratee, thisArg, 3); @@ -5173,11 +5173,11 @@ if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { iteratee = null; } - var noIterator = iteratee == null, - isArr = noIterator && isArray(collection), + var noIteratee = iteratee == null, + isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); - if (noIterator && !isStr) { + if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -5189,7 +5189,7 @@ } } } else { - iteratee = (noIterator && isStr) + iteratee = (noIteratee && isStr) ? charAtCallback : getCallback(iteratee, thisArg, 3); From c3cd94b6954a993bd85e69bcf0692eec7d9e915f Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 2 Aug 2014 22:08:17 -0700 Subject: [PATCH 1001/1608] Fix coercing `arity` in `baseCurry`. --- lodash.js | 2 +- test/test.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index 4d7d767adb..bc2a0d6fa9 100644 --- a/lodash.js +++ b/lodash.js @@ -1624,7 +1624,7 @@ */ function baseCurry(func, bitmask, arity) { if (typeof arity != 'number') { - arity = +arity || (func ? func.length : 0); + arity = arity == null ? (func ? func.length : 0) : (+arity || 0); } return createWrapper([func, bitmask, arity]); } diff --git a/test/test.js b/test/test.js index 61e9e41306..4e05ca41cf 100644 --- a/test/test.js +++ b/test/test.js @@ -2229,7 +2229,7 @@ deepEqual(curried(1, 2, 3, 4), expected); }); - test('should allow specifying `arity`', 3, function(){ + test('should allow specifying `arity`', 3, function() { var curried = _.curry(fn, 3), expected = [1, 2, 3]; @@ -2238,6 +2238,21 @@ deepEqual(curried(1, 2, 3), expected); }); + test('should coerce `arity` to a number', 2, function() { + var values = ['0', 'xyz'], + expected = _.map(values, _.constant([])); + + var actual = _.map(values, function(arity) { + var curried = _.curry(fn, arity); + return curried(); + }); + + deepEqual(actual, expected); + + curried = _.curry(fn, '2'); + deepEqual(curried(1)(2), [1, 2]); + }); + test('should work with partialed methods', 2, function() { var curried = _.curry(fn), expected = [1, 2, 3, 4]; From afc369857884e5b9431d855d1e43080927cc677f Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 2 Aug 2014 22:08:37 -0700 Subject: [PATCH 1002/1608] Minor whitespace nits in test.js. [ci skip] --- test/test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test.js b/test/test.js index 4e05ca41cf..259281a97d 100644 --- a/test/test.js +++ b/test/test.js @@ -2346,7 +2346,7 @@ deepEqual(curried(1, 2, 3, 4), expected); }); - test('should allow specifying `arity`', 3, function(){ + test('should allow specifying `arity`', 3, function() { var curried = _.curryRight(fn, 3), expected = [1, 2, 3]; @@ -2721,7 +2721,7 @@ asyncTest('should defer `func` execution', 1, function() { if (!(isRhino && isModularize)) { var pass = false; - _.defer(function(){ pass = true; }); + _.defer(function() { pass = true; }); setTimeout(function() { ok(pass); @@ -2783,7 +2783,7 @@ asyncTest('should delay `func` execution', 2, function() { if (!(isRhino && isModularize)) { var pass = false; - _.delay(function(){ pass = true; }, 96); + _.delay(function() { pass = true; }, 96); setTimeout(function() { ok(!pass); @@ -3263,7 +3263,7 @@ var func = _[methodName]; test('`_.' + methodName + '` should ' + (isStrict ? '' : 'not ') + 'throw strict mode errors', 1, function() { - var object = { 'a': null, 'b': function(){} }, + var object = { 'a': null, 'b': function() {} }, pass = !isStrict; if (freeze) { From fc44d54607e26a9cd7289b1968aa0a0bf7159103 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 2 Aug 2014 23:25:20 -0700 Subject: [PATCH 1003/1608] Fix test fail. --- test/test.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index 259281a97d..e0aced2f75 100644 --- a/test/test.js +++ b/test/test.js @@ -2243,14 +2243,11 @@ expected = _.map(values, _.constant([])); var actual = _.map(values, function(arity) { - var curried = _.curry(fn, arity); - return curried(); + return _.curry(fn, arity)(); }); deepEqual(actual, expected); - - curried = _.curry(fn, '2'); - deepEqual(curried(1)(2), [1, 2]); + deepEqual(_.curry(fn, '2')(1)(2), [1, 2]); }); test('should work with partialed methods', 2, function() { From 264f7b1d300dfa194df444880343253c7c80c6a3 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 3 Aug 2014 14:03:36 -0700 Subject: [PATCH 1004/1608] Fix tests in old IE. --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 67e85f4e4c..a65a4fe9b8 100644 --- a/test/index.html +++ b/test/index.html @@ -251,7 +251,7 @@ delete Object._defineProperty; delete Object._getPrototypeOf; delete Object._keys; - delete objectProto._hasOwnProperty; + delete objectProto._propertyIsEnumerable; delete stringProto._contains; } QUnit.config.hidepassed = true; From 48acda2c3c3ffb84730535c446b9d1c0c6556111 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 3 Aug 2014 22:40:31 -0700 Subject: [PATCH 1005/1608] Add `_.iteratee` alias of `_.callback`. --- lodash.js | 2 ++ test/test.js | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index bc2a0d6fa9..629378af02 100644 --- a/lodash.js +++ b/lodash.js @@ -8610,6 +8610,7 @@ * * @static * @memberOf _ + * @alias iteratee * @category Utility * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. @@ -9280,6 +9281,7 @@ lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; + lodash.iteratee = callback; lodash.methods = functions; lodash.object = zipObject; lodash.select = filter; diff --git a/test/test.js b/test/test.js index e0aced2f75..b83802996c 100644 --- a/test/test.js +++ b/test/test.js @@ -2209,6 +2209,10 @@ skipTest(); } }); + + test('should be aliased', 1, function() { + strictEqual(_.iteratee, _.callback); + }); }()); /*--------------------------------------------------------------------------*/ @@ -11893,7 +11897,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 193, function() { + test('should accept falsey arguments', 194, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From d2444d2992e1e32be37a0390f312d68f923db883 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 4 Aug 2014 00:05:19 -0700 Subject: [PATCH 1006/1608] Remove `!source` check from `_.mixin`. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 629378af02..0d15777844 100644 --- a/lodash.js +++ b/lodash.js @@ -8789,7 +8789,7 @@ props = noOpts && isObj && keys(source), methodNames = props && baseFunctions(source, props); - if (!source || (props && props.length && !methodNames.length) || (noOpts && !isObj)) { + if ((props && props.length && !methodNames.length) || (noOpts && !isObj)) { if (noOpts) { options = source; } From e54b8ead7204c20f561c2615280759d1dfa64c2a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 6 Aug 2014 23:54:01 -0700 Subject: [PATCH 1007/1608] Rename `cloneBuffer` to `bufferClone`, split `basePick` into `pickByArray` and `pickByCallback`, and add `arrayClone`. --- lodash.js | 209 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 90 deletions(-) diff --git a/lodash.js b/lodash.js index 0d15777844..467fb9ddb1 100644 --- a/lodash.js +++ b/lodash.js @@ -298,6 +298,24 @@ /*--------------------------------------------------------------------------*/ + /** + * Creates a shallow clone of `array`. + * + * @private + * @param {Array} array The array to slice. + * @returns {Array} Returns the cloned array. + */ + function arrayClone(array) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = array[index]; + } + return result; + } + /** * The base implementation of `_.at` without support for strings and individual * key arguments. @@ -1410,7 +1428,7 @@ isShallow = !isDeep; if (isArr) { - result = isShallow ? slice(value) : value.constructor(value.length); + result = isShallow ? arrayClone(value) : value.constructor(value.length); // add array properties assigned by `RegExp#exec` if (typeof value[0] == 'string' && hasOwnProperty.call(value, 'index')) { @@ -1448,7 +1466,7 @@ else { switch (className) { case arrayBufferClass: - return cloneBuffer(value); + return bufferClone(value); case boolClass: case dateClass: @@ -1462,7 +1480,7 @@ Ctor = ctorByClass[className]; } var buffer = value.buffer; - return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, value.byteOffset, value.length); + return new Ctor(isDeep ? bufferClone(buffer) : buffer, value.byteOffset, value.length); case numberClass: case stringClass: @@ -2268,40 +2286,6 @@ return createWrapper(newData); } - /** - * The base implementation of `_.pick` without support for `this` binding - * and individual property name arguments. - * - * @private - * @param {Object} object The source object. - * @param {Function|string[]} predicate The function called per iteration or - * property names to pick. - * @returns {Object} Returns the new object. - */ - function basePick(object, predicate) { - var result = {}; - - if (typeof predicate == 'function') { - baseForIn(object, function(value, key, object) { - if (predicate(value, key, object)) { - result[key] = value; - } - }); - return result; - } - var index = -1, - props = predicate, - length = props.length; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - return result; - } - /** * The base implementation of `_.pullAt` without support for individual * index arguments. @@ -2494,6 +2478,36 @@ return result; } + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function bufferClone(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` + bufferClone = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, + offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; + } + /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. @@ -2599,27 +2613,27 @@ * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { - return function(object) { - var args = arguments, - length = args.length; + return function() { + var length = arguments.length, + object = arguments[0]; if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` - var type = typeof args[2]; - if ((type == 'number' || type == 'string') && args[3] && args[3][args[2]] === args[1]) { + var type = typeof arguments[2]; + if ((type == 'number' || type == 'string') && arguments[3] && arguments[3][arguments[2]] === arguments[1]) { length = 2; } // juggle arguments - if (length > 3 && typeof args[length - 2] == 'function') { - var customizer = baseCallback(args[--length - 1], args[length--], 5); - } else if (length > 2 && typeof args[length - 1] == 'function') { - customizer = args[--length]; + if (length > 3 && typeof arguments[length - 2] == 'function') { + var customizer = baseCallback(arguments[--length - 1], arguments[length--], 5); + } else if (length > 2 && typeof arguments[length - 1] == 'function') { + customizer = arguments[--length]; } var index = 0; while (++index < length) { - assigner(object, args[index], customizer); + assigner(object, arguments[index], customizer); } return object; }; @@ -2795,17 +2809,17 @@ var funcData = !isBindKey && func[EXPANDO]; if (funcData && funcData !== true) { // shallow clone `funcData` - funcData = slice(funcData); + funcData = arrayClone(funcData); // clone partial left arguments if (funcData[4]) { - funcData[4] = slice(funcData[4]); - funcData[5] = slice(funcData[5]); + funcData[4] = arrayClone(funcData[4]); + funcData[5] = arrayClone(funcData[5]); } // clone partial right arguments if (funcData[6]) { - funcData[6] = slice(funcData[6]); - funcData[7] = slice(funcData[7]); + funcData[6] = arrayClone(funcData[6]); + funcData[7] = arrayClone(funcData[7]); } // set arity if provided if (typeof arity == 'number') { @@ -2861,7 +2875,7 @@ function getCallback(func, thisArg, argCount) { var result = lodash.callback || callback; result = result === callback ? baseCallback : result; - return arguments.length ? result(func, thisArg, argCount) : result; + return argCount ? result(func, thisArg, argCount) : result; } /** @@ -2918,33 +2932,46 @@ } /** - * Creates a clone of the given array buffer. + * A specialized version of `_.pick` that picks `object` properties + * specified by the `props` array. * * @private - * @param {ArrayBuffer} buffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. */ - function cloneBuffer(buffer) { - return bufferSlice.call(buffer, 0); - } - if (!bufferSlice) { - // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` - cloneBuffer = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + function pickByArray(object, props) { + var index = -1, + length = props.length, + result = {}; - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); + } + return result; + } + + /** + * A specialized version of `_.pick` that picks `object` properties + * the predicate returns truthy for. + * + * @private + * @param {Object} object The source object. + * @param {Function} predicate The function called per iteration. + * @returns {Object} Returns the new object. + */ + function pickByCallback(object, predicate) { + var result = {}; + + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; } - return result; - }; + }); + return result; } /** @@ -3763,8 +3790,9 @@ * console.log(array); * // => [1, 1] */ - function pull(array) { - var argsIndex = 0, + function pull() { + var array = arguments[0], + argsIndex = 0, argsLength = arguments.length, indexOf = getIndexOf(); @@ -3903,6 +3931,9 @@ if (end < 0) { end += length; } + if (end && end == length && !start) { + return arrayClone(array); + } length = start > end ? 0 : (end - start); var result = Array(length); @@ -4290,8 +4321,8 @@ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ - function without() { - return baseDifference(arguments[0], slice(arguments, 1)); + function without(array) { + return baseDifference(array, slice(arguments, 1)); } /** @@ -5614,7 +5645,7 @@ if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { return (support.unindexedChars && isString(collection)) ? collection.split('') - : slice(collection); + : arrayClone(collection); } return values(collection); } @@ -6627,7 +6658,7 @@ if (object == null) { return object; } - var args = slice(arguments); + var args = arrayClone(arguments); args.push(assignDefaults); return assign.apply(undefined, args); } @@ -7663,11 +7694,10 @@ if (object == null) { return {}; } - if (typeof predicate == 'function') { - return basePick(object, negate(getCallback(predicate, thisArg, 3))); - } - var omitProps = baseFlatten(arguments, false, false, 1); - return basePick(toObject(object), baseDifference(keysIn(object), arrayMap(omitProps, String))); + var iterable = toObject(object); + return typeof predicate == 'function' + ? pickByCallback(iterable, negate(getCallback(predicate, thisArg, 3))) + : pickByArray(iterable, baseDifference(keysIn(iterable), arrayMap(baseFlatten(arguments, false, false, 1), String))); } /** @@ -7728,11 +7758,10 @@ if (object == null) { return {}; } - return basePick(toObject(object), - typeof predicate == 'function' - ? getCallback(predicate, thisArg, 3) - : baseFlatten(arguments, false, false, 1) - ); + var iterable = toObject(object); + return typeof predicate == 'function' + ? pickByCallback(iterable, getCallback(predicate, thisArg, 3)) + : pickByArray(iterable, baseFlatten(arguments, false, false, 1)); } /** From 476d85915bcde53c6a960428cdd02185e30c674d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 8 Aug 2014 09:28:16 -0700 Subject: [PATCH 1008/1608] Revert rename of `baseSlice` and add `initArrayClone` and `initObjectClone`. --- lodash.js | 213 +++++++++++++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 97 deletions(-) diff --git a/lodash.js b/lodash.js index 467fb9ddb1..640cc9a936 100644 --- a/lodash.js +++ b/lodash.js @@ -298,24 +298,6 @@ /*--------------------------------------------------------------------------*/ - /** - * Creates a shallow clone of `array`. - * - * @private - * @param {Array} array The array to slice. - * @returns {Array} Returns the cloned array. - */ - function arrayClone(array) { - var index = -1, - length = array ? array.length : 0, - result = Array(length); - - while (++index < length) { - result[index] = array[index]; - } - return result; - } - /** * The base implementation of `_.at` without support for strings and individual * key arguments. @@ -380,6 +362,25 @@ return -1; } + /** + * The base implementation of `_.slice` without support for `start` and `end` + * arguments. + * + * @private + * @param {Array} array The array to slice. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = array[index]; + } + return result; + } + /** * An implementation of `_.contains` for cache objects that mimics the return * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. @@ -1424,79 +1425,15 @@ if (typeof result != 'undefined') { return result; } - var isArr = isArray(value), - isShallow = !isDeep; - + var isArr = isArray(value); + result = value; if (isArr) { - result = isShallow ? arrayClone(value) : value.constructor(value.length); - - // add array properties assigned by `RegExp#exec` - if (typeof value[0] == 'string' && hasOwnProperty.call(value, 'index')) { - result.index = value.index; - result.input = value.input; - } - if (isShallow) { - return result; - } + result = initArrayClone(value, isDeep); + } else if (isObject(value)) { + result = initObjectClone(value, isDeep); + value = (isDeep && toString.call(result) == objectClass) ? value : result; } - else { - if (!isObject(value)) { - return value; - } - var className = toString.call(value); - if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) { - return value; - } - var isArgs = className == argsClass || (!support.argsClass && isArguments(value)), - isObj = !isArgs && className == objectClass; - - if (isShallow && (isArgs || isObj)) { - result = baseAssign({}, value); - if (isObj) { - return result; - } - } - var Ctor = value.constructor; - if (className == objectClass && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { - Ctor = Object; - } - if (isDeep && (isArgs || isObj)) { - result = new Ctor; - } - else { - switch (className) { - case arrayBufferClass: - return bufferClone(value); - - case boolClass: - case dateClass: - return new Ctor(+value); - - case float32Class: case float64Class: - case int8Class: case int16Class: case int32Class: - case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - // Safari 5 mobile incorrectly has `Object` as the constructor - if (Ctor instanceof Ctor) { - Ctor = ctorByClass[className]; - } - var buffer = value.buffer; - return new Ctor(isDeep ? bufferClone(buffer) : buffer, value.byteOffset, value.length); - - case numberClass: - case stringClass: - return new Ctor(value); - - case regexpClass: - result = Ctor(value.source, reFlags.exec(value)); - result.lastIndex = value.lastIndex; - return result; - } - } - } - if (isArgs) { - result.length = value.length; - } - if (isShallow) { + if (!isDeep || result === value) { return result; } // check for circular references and return corresponding clone @@ -2809,17 +2746,17 @@ var funcData = !isBindKey && func[EXPANDO]; if (funcData && funcData !== true) { // shallow clone `funcData` - funcData = arrayClone(funcData); + funcData = baseSlice(funcData); // clone partial left arguments if (funcData[4]) { - funcData[4] = arrayClone(funcData[4]); - funcData[5] = arrayClone(funcData[5]); + funcData[4] = baseSlice(funcData[4]); + funcData[5] = baseSlice(funcData[5]); } // clone partial right arguments if (funcData[6]) { - funcData[6] = arrayClone(funcData[6]); - funcData[7] = arrayClone(funcData[7]); + funcData[6] = baseSlice(funcData[6]); + funcData[7] = baseSlice(funcData[7]); } // set arity if provided if (typeof arity == 'number') { @@ -2893,6 +2830,88 @@ return collection ? result(collection, target, fromIndex) : result; } + /** + * Initializes an array clone. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @returns {*} Returns the initialized clone value. + */ + function initArrayClone(array, isDeep) { + var index = -1, + length = array.length, + result = array.constructor(length); + + if (!isDeep) { + while (++index < length) { + result[index] = array[index]; + } + } + // add array properties assigned by `RegExp#exec` + if (typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @returns {*} Returns the initialized clone value. + */ + function initObjectClone(object, isDeep) { + var className = toString.call(object); + if (!cloneableClasses[className] || (!support.nodeClass && isNode(object))) { + return object; + } + var Ctor = object.constructor, + isArgs = className == argsClass || (!support.argsClass && isArguments(object)), + isObj = className == objectClass; + + if (isObj && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { + Ctor = Object; + } + if (isArgs || isObj) { + var result = isDeep ? new Ctor : baseAssign(new Ctor, object); + if (isArgs) { + result.length = object.length; + } + return result; + } + switch (className) { + case arrayBufferClass: + return bufferClone(object); + + case boolClass: + case dateClass: + return new Ctor(+object); + + case float32Class: case float64Class: + case int8Class: case int16Class: case int32Class: + case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: + // Safari 5 mobile incorrectly has `Object` as the constructor + if (Ctor instanceof Ctor) { + Ctor = ctorByClass[className]; + } + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberClass: + case stringClass: + return new Ctor(object); + + case regexpClass: + result = Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + /** * Checks if `value` is an array-like object. * @@ -3932,7 +3951,7 @@ end += length; } if (end && end == length && !start) { - return arrayClone(array); + return baseSlice(array); } length = start > end ? 0 : (end - start); @@ -5645,7 +5664,7 @@ if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { return (support.unindexedChars && isString(collection)) ? collection.split('') - : arrayClone(collection); + : baseSlice(collection); } return values(collection); } @@ -6658,7 +6677,7 @@ if (object == null) { return object; } - var args = arrayClone(arguments); + var args = baseSlice(arguments); args.push(assignDefaults); return assign.apply(undefined, args); } From 916c728d7018a2ad19f9d4217ae5084aa99a2106 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 8 Aug 2014 10:28:18 -0700 Subject: [PATCH 1009/1608] Remove unneeded flag from `baseClone` call in `_.matches`. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 640cc9a936..ee8ecf89fd 100644 --- a/lodash.js +++ b/lodash.js @@ -8775,7 +8775,7 @@ var isStrict = isStrictComparable(value); flags[index] = isStrict; - vals[index] = isStrict ? value : baseClone(value, false); + vals[index] = isStrict ? value : baseClone(value); } return function(object) { index = length; From df4e306c643de6f1322f3e0a121e98a1ce30533b Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 8 Aug 2014 10:43:26 -0700 Subject: [PATCH 1010/1608] Add `length` check to avoid extra work in `initArrayClone`. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index ee8ecf89fd..cb30dd3ed6 100644 --- a/lodash.js +++ b/lodash.js @@ -2849,7 +2849,7 @@ } } // add array properties assigned by `RegExp#exec` - if (typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { result.index = array.index; result.input = array.input; } From 4238e84ec48104c7d625ea9503eea9c54cf8ffef Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 9 Aug 2014 09:39:29 -0700 Subject: [PATCH 1011/1608] Add tests for matching `NaN`. --- test/test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/test.js b/test/test.js index b83802996c..d0c81a4a2c 100644 --- a/test/test.js +++ b/test/test.js @@ -1902,6 +1902,10 @@ strictEqual(_.contains([3, 2, 1], 3, true), true); }); + test('should match `NaN`', 1, function() { + strictEqual(_.contains([1, NaN, 3], NaN), true); + }); + test('should be aliased', 1, function() { strictEqual(_.include, _.contains); }); @@ -2857,6 +2861,10 @@ deepEqual(actual, [1, 3]); }); + test('should match `NaN`', 1, function() { + deepEqual(_.difference([1, NaN, 3], [NaN, 5, NaN]), [1, 3]); + }); + test('should work with large arrays', 1, function() { var array1 = _.range(LARGE_ARRAY_SIZE + 1), array2 = _.range(LARGE_ARRAY_SIZE), @@ -4793,6 +4801,10 @@ deepEqual(_.intersection(array), [1, 3, 2]); }); + test('should match `NaN`', 1, function() { + deepEqual(_.intersection([1, NaN, 3], [NaN, 5, NaN]), [NaN]); + }); + test('should work with large arrays of objects', 1, function() { var object = {}, largeArray = _.times(LARGE_ARRAY_SIZE, _.constant(object)); @@ -6722,6 +6734,10 @@ strictEqual(func(empty, undefined), -1); strictEqual(func(empty, undefined, true), -1); }); + + test('`_.' + methodName + '` should match `NaN`', 1, function() { + strictEqual(func([1, NaN, 3], NaN), 1); + }); }); /*--------------------------------------------------------------------------*/ @@ -8489,6 +8505,13 @@ _.pull(array, undefined); deepEqual(array, [1, 3]); }); + + test('should match `NaN`', 1, function() { + var array = [1, NaN, 3, NaN]; + + _.pull(array, NaN); + deepEqual(array, [1, 3]); + }); }()); /*--------------------------------------------------------------------------*/ @@ -11024,6 +11047,10 @@ deepEqual(_.uniq(objects), objects); }); + test('should not treat `NaN` as uniq', 1, function() { + deepEqual(_.uniq([1, NaN, 3, NaN]), [1, NaN, 3]); + }); + test('should work with `isSorted`', 3, function() { var expected = [1, 2, 3]; deepEqual(_.uniq([1, 2, 3], true), expected); From c849fe149622c692e50370208b1e4334682586ef Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 9 Aug 2014 09:40:02 -0700 Subject: [PATCH 1012/1608] Cleanup `_.pull`. --- lodash.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lodash.js b/lodash.js index cb30dd3ed6..cf9e4eb168 100644 --- a/lodash.js +++ b/lodash.js @@ -3811,13 +3811,13 @@ */ function pull() { var array = arguments[0], - argsIndex = 0, - argsLength = arguments.length, - indexOf = getIndexOf(); + index = 0, + indexOf = getIndexOf(), + length = arguments.length; - while (++argsIndex < argsLength) { + while (++index < length) { var fromIndex = 0, - value = arguments[argsIndex]; + value = arguments[index]; while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { splice.call(array, fromIndex, 1); From 0deacc72298db67852156b26ac58c4d3fae4b798 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 10 Aug 2014 10:21:36 -0700 Subject: [PATCH 1013/1608] Add tests for large arrays and `NaN` values. --- test/test.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index d0c81a4a2c..ce77bde010 100644 --- a/test/test.js +++ b/test/test.js @@ -2886,6 +2886,11 @@ deepEqual(_.difference([object1, object2], largeArray), [object2]); }); + test('should work with large arrays of `NaN`', 1, function() { + var largeArray = _.times(LARGE_ARRAY_SIZE, _.constant(NaN)); + deepEqual(_.difference([1, NaN, 3], largeArray), [1, 3]); + }); + test('should ignore values that are not arrays or `arguments` objects', 3, function() { var array = [0, 1, null, 3]; deepEqual(_.difference(array, 3, null, { '0': 1 }), array); @@ -4820,6 +4825,11 @@ deepEqual(_.intersection(_.range(LARGE_ARRAY_SIZE), null, [1]), [1]); }); + test('should work with large arrays of `NaN`', 1, function() { + var largeArray = _.times(LARGE_ARRAY_SIZE, _.constant(NaN)); + deepEqual(_.intersection([1, NaN, 3], largeArray), [NaN]); + }); + test('should ignore values that are not arrays or `arguments` objects', 3, function() { var array = [0, 1, null, 3]; deepEqual(_.intersection(array, 3, null, { '0': 1 }), array); @@ -11119,9 +11129,9 @@ deepEqual(_.uniq(largeArray), [0, 'a', object]); }); - test('should work with large arrays of boolean, `null`, and `undefined` values', 1, function() { + test('should work with large arrays of boolean, `NaN`, `null`, and `undefined` values', 1, function() { var array = [], - expected = [true, false, null, undefined], + expected = [true, false, NaN, null, undefined], count = Math.ceil(LARGE_ARRAY_SIZE / expected.length); _.times(count, function() { From faac6300010c63a92fab422fcea40b6cd1b0597e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 10 Aug 2014 10:21:52 -0700 Subject: [PATCH 1014/1608] Update tested version of Node in readme. [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f74d938aa1..42e48bdcc7 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# ## Support -Tested in Chrome (19, 35-36), Firefox (3, 20, 29-30), IE 6-11, Opera 22-23, Safari 5-7, Node.js 0.8.26~0.10.29, PhantomJS 1.9.7, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 35-36), Firefox (3, 20, 29-30), IE 6-11, Opera 22-23, Safari 5-7, Node.js 0.8.26~0.10.30, PhantomJS 1.9.7, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. From 6dc0cf0c4421e409a59064eabb82d2ad793b3e05 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 11 Aug 2014 09:24:56 -0700 Subject: [PATCH 1015/1608] Typo nit in `_.uniq` tests. --- test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index ce77bde010..cc8fc90220 100644 --- a/test/test.js +++ b/test/test.js @@ -11053,11 +11053,11 @@ deepEqual(_.uniq(array), [1, 2, 3]); }); - test('should treat object instances as uniq', 1, function() { + test('should treat object instances as unique', 1, function() { deepEqual(_.uniq(objects), objects); }); - test('should not treat `NaN` as uniq', 1, function() { + test('should not treat `NaN` as unique', 1, function() { deepEqual(_.uniq([1, NaN, 3, NaN]), [1, NaN, 3]); }); From a2595d5107f534b7e851d90302383d0a0d221c76 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 11 Aug 2014 21:43:53 -0700 Subject: [PATCH 1016/1608] Remove native `String#contains` use in `_.contains`. --- lodash.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lodash.js b/lodash.js index cf9e4eb168..d1365e96dd 100644 --- a/lodash.js +++ b/lodash.js @@ -719,8 +719,7 @@ }()); /* Native method references for those with the same name as other `lodash` methods */ - var nativeContains = isNative(nativeContains = stringProto.contains) && nativeContains, - nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, + var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = context.isFinite, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, @@ -4627,15 +4626,9 @@ } else { fromIndex = 0; } - if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { - if (fromIndex >= length) { - return false; - } - return nativeContains - ? nativeContains.call(collection, target, fromIndex) - : collection.indexOf(target, fromIndex) > -1; - } - return getIndexOf(collection, target, fromIndex) > -1; + return (typeof collection == 'string' || !isArray(collection) && isString(collection)) + ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) + : (getIndexOf(collection, target, fromIndex) > -1); } /** From e2dd65a4035ea6301afb4a1c6b91c759d2ec62a6 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Tue, 12 Aug 2014 21:20:56 +0800 Subject: [PATCH 1017/1608] Add more emphasis on the `Note` sections --- lodash.js | 70 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/lodash.js b/lodash.js index d1365e96dd..9c961a3a11 100644 --- a/lodash.js +++ b/lodash.js @@ -207,7 +207,7 @@ /** * Used to convert characters to HTML entities. * - * Note: Though the ">" character is escaped for symmetry, characters like + * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) @@ -1283,7 +1283,7 @@ /** * Used by `_.template` to customize its `_.assign` use. * - * Note: This method is like `assignDefaults` except that it ignores + * **Note:** This method is like `assignDefaults` except that it ignores * inherited property values when checking if a property is `undefined`. * * @private @@ -3233,7 +3233,7 @@ * Creates an array excluding all values of the provided arrays using * `SameValueZero` for equality comparisons. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -3606,7 +3606,7 @@ * it is used as the offset from the end of the collection. If `array` is * sorted providing `true` for `fromIndex` performs a faster binary search. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -3665,7 +3665,7 @@ * Creates an array of unique values present in all provided arrays using * `SameValueZero` for equality comparisons. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -3789,7 +3789,7 @@ * Removes all provided values from `array` using `SameValueZero` for equality * comparisons. * - * Note: Unlike `_.without`, this method mutates `array`. + * **Note:** Unlike `_.without`, this method mutates `array`. * * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) @@ -3830,7 +3830,7 @@ * returns an array of the removed elements. Indexes may be specified as an * array of indexes or as individual arguments. * - * Note: Unlike `_.at`, this method mutates `array`. + * **Note:** Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ @@ -3866,7 +3866,7 @@ * returns `true` for elements that have the properties of the given object, * else `false`. * - * Note: Unlike `_.filter`, this method mutates `array`. + * **Note:** Unlike `_.filter`, this method mutates `array`. * * @static * @memberOf _ @@ -3926,7 +3926,7 @@ /** * Slices `array` from the `start` index up to, but not including, the `end` index. * - * Note: This function is used instead of `Array#slice` to support node lists + * **Note:** This function is used instead of `Array#slice` to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @static @@ -4201,7 +4201,7 @@ * Creates an array of unique values, in order, of the provided arrays using * `SameValueZero` for equality comparisons. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -4234,7 +4234,7 @@ * returns `true` for elements that have the properties of the given object, * else `false`. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -4324,7 +4324,7 @@ * Creates an array excluding all provided values using `SameValueZero` for * equality comparisons. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -4588,7 +4588,7 @@ * equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of the collection. * - * Note: `SameValueZero` is like strict equality, e.g. `===`, except that + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * @@ -4874,7 +4874,7 @@ * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * - * Note: As with other "Collections" methods, objects with a `length` property + * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * @@ -5765,7 +5765,7 @@ * and prepends any additional `bind` arguments to those provided to the bound * function. * - * Note: Unlike native `Function#bind` this method does not set the `length` + * **Note:** Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static @@ -5801,7 +5801,7 @@ * of method names. If no method names are provided all enumerable function * properties, own and inherited, of `object` are bound. * - * Note: This method does not set the `length` property of bound functions. + * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ @@ -5934,7 +5934,7 @@ * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. * - * Note: This method does not set the `length` property of curried functions. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ @@ -5967,7 +5967,7 @@ * This method is like `_.curry` except that arguments are applied to `func` * in the manner of `_.partialRight` instead of `_.partial`. * - * Note: This method does not set the `length` property of curried functions. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ @@ -6004,7 +6004,7 @@ * and/or trailing edge of the `wait` timeout. Subsequent calls to the * debounced function return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * @@ -6325,7 +6325,7 @@ * prepended to those provided to the new function. This method is similar to * `_.bind` except it does **not** alter the `this` binding. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -6352,7 +6352,7 @@ * This method is like `_.partial` except that partially applied arguments * are appended to those provided to the new function. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -6394,7 +6394,7 @@ * Subsequent calls to the throttled function return the result of the last * `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * @@ -6507,7 +6507,7 @@ * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -6570,7 +6570,7 @@ * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -6652,7 +6652,7 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property are ignored. * - * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * **Note:** See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. * * @static @@ -7134,7 +7134,7 @@ * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). * - * Note: This method supports comparing arrays, booleans, `Date` objects, + * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. @@ -7197,7 +7197,7 @@ /** * Checks if `value` is a finite primitive number. * - * Note: This method is based on ES6 `Number.isFinite`. See the + * **Note:** This method is based on ES6 `Number.isFinite`. See the * [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) * for more details. * @@ -7259,7 +7259,7 @@ * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * Note: See the [ES5 spec](http://es5.github.io/#x8) for more details. + * **Note:** See the [ES5 spec](http://es5.github.io/#x8) for more details. * * @static * @memberOf _ @@ -7287,7 +7287,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which returns `true` + * **Note:** This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -7339,7 +7339,7 @@ /** * Checks if `value` is classified as a `Number` primitive or object. * - * Note: To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static @@ -7368,7 +7368,7 @@ * Checks if `value` is an object created by the `Object` constructor or has * a `[[Prototype]]` of `null`. * - * Note: This method assumes objects created by the `Object` constructor + * **Note:** This method assumes objects created by the `Object` constructor * have no inherited enumerable properties. * * @static @@ -7964,7 +7964,7 @@ * Converts the characters "&", "<", ">", '"', and "'" in `string` to * their corresponding HTML entities. * - * Note: No other characters are escaped. To escape additional characters + * **Note:** No other characters are escaped. To escape additional characters * use a third-party library like [_he_](http://mths.be/he). * * When working with HTML you should always quote attribute values to reduce @@ -8231,7 +8231,7 @@ * properties may be accessed as free variables in the template. If a setting * object is provided it overrides `_.templateSettings` for the template. * - * Note: In the development build `_.template` utilizes sourceURLs for easier debugging. + * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * @@ -8593,7 +8593,7 @@ * `&`, `<`, `>`, `"`, and `'` in `string` to their * corresponding characters. * - * Note: No other HTML entities are unescaped. To unescape additional HTML + * **Note:** No other HTML entities are unescaped. To unescape additional HTML * entities use a third-party library like [_he_](http://mths.be/he). * * @static @@ -8930,7 +8930,7 @@ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * Note: This method avoids differences in native ES3 and ES5 `parseInt` + * **Note:** This method avoids differences in native ES3 and ES5 `parseInt` * implementations. See the [ES5 spec](http://es5.github.io/#E) * for more details. * From ce36bf6134d6c66badc564cb29b2520499188d8a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 12 Aug 2014 10:33:53 -0700 Subject: [PATCH 1018/1608] Update tested Firefox versions. --- README.md | 2 +- test/saucelabs.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 42e48bdcc7..ef0dedfe0b 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# ## Support -Tested in Chrome (19, 35-36), Firefox (3, 20, 29-30), IE 6-11, Opera 22-23, Safari 5-7, Node.js 0.8.26~0.10.30, PhantomJS 1.9.7, RingoJS 0.9, & Rhino 1.7RC5. +Tested in Chrome (19, 35-36), Firefox (3, 20, 30-31), IE 6-11, Opera 22-23, Safari 5-7, Node.js 0.8.26~0.10.30, PhantomJS 1.9.7, RingoJS 0.9, & Rhino 1.7RC5. Automated browser test runs [are available](https://saucelabs.com/u/lodash) as well as CI runs for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash). Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. diff --git a/test/saucelabs.js b/test/saucelabs.js index fbfc864991..5879926599 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -98,8 +98,8 @@ var browserNameMap = { var platforms = [ ['Linux', 'android', '4.3'], ['Linux', 'android', '4.0'], + ['Windows 8.1', 'firefox', '31'], ['Windows 8.1', 'firefox', '30'], - ['Windows 8.1', 'firefox', '29'], ['Windows 8.1', 'firefox', '20'], ['Windows 8.1', 'firefox', '3.0'], ['Windows 8.1', 'chrome', '36'], From 67b0c4cddd03077c720aff779e955e2ee825e3ca Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 12 Aug 2014 21:16:22 -0700 Subject: [PATCH 1019/1608] Use `_.createCallback` if `_.matches` is unavailable for the perf test. --- perf/perf.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/perf/perf.js b/perf/perf.js index f5f8841b4a..6248b71a66 100644 --- a/perf/perf.js +++ b/perf/perf.js @@ -444,10 +444,10 @@ var source = { "num": 9 };\ \ var _findWhere = _.findWhere || _.find,\ - _match = _.matches && _.matches(source);\ + _match = (_.matches || _.createCallback || _.noop)(source);\ \ var lodashFindWhere = lodash.findWhere || lodash.find,\ - lodashMatch = lodash.matches && lodash.matches(source);\ + lodashMatch = (lodash.matches || lodash.createCallback || lodash.noop)(source);\ }\ if (typeof multiArrays != "undefined") {\ var twentyValues = belt.shuffle(belt.range(20)),\ From c139a0d9edfdfbcbb1cc22e594e3d5a15b06b008 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 14 Aug 2014 09:22:55 -0700 Subject: [PATCH 1020/1608] Avoid internally passing around metadata arrays. --- lodash.js | 343 +++++++++++++++++++++++++----------------------------- 1 file changed, 157 insertions(+), 186 deletions(-) diff --git a/lodash.js b/lodash.js index 9c961a3a11..c3ab49e2ab 100644 --- a/lodash.js +++ b/lodash.js @@ -1338,7 +1338,7 @@ while (++index < length) { var key = methodNames[index]; - object[key] = createWrapper([object[key], BIND_FLAG, null, object]); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -1487,85 +1487,6 @@ }()); } - /** - * The base implementation of `createWrapper` which creates the wrapper and - * sets its metadata. - * - * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(data) { - var bitmask = data[1]; - if (bitmask == BIND_FLAG) { - return setData(createBindWrapper(data), data); - } - var partialHolders = data[5]; - if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { - return setData(createPartialWrapper(data), data); - } - var func = data[0], - arity = data[2], - thisArg = data[3], - partialArgs = data[4], - partialRightArgs = data[6], - partialRightHolders = data[7]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryRight = bitmask & CURRY_RIGHT_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG; - - var Ctor = !isBindKey && createCtorWrapper(func), - key = func; - - var wrapper = function() { - var length = arguments.length, - index = length, - args = Array(length); - - while (index--) { - args[index] = arguments[index]; - } - if (partialArgs) { - args = composeArgs(partialArgs, partialHolders, args); - } - if (partialRightArgs) { - args = composeArgsRight(partialRightArgs, partialRightHolders, args); - } - if (isCurry || isCurryRight) { - var placeholder = wrapper.placeholder, - newPartialHolders = replaceHolders(args, placeholder); - - length -= newPartialHolders.length; - - if (length < arity) { - bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); - bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); - - if (!isCurryBound) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); - } - var newData = [func, bitmask, nativeMax(arity - length, 0), thisArg, null, null]; - newData[isCurry ? 4 : 6] = args; - newData[isCurry ? 5 : 7] = newPartialHolders; - - var result = baseCreateWrapper(newData); - result.placeholder = placeholder; - return result; - } - } - var thisBinding = isBind ? thisArg : this; - if (isBindKey) { - func = thisBinding[key]; - } - return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); - }; - - return setData(wrapper, data); - } - /** * The base implementation of `_.curry` and `_.curryRight` which handles * resolving the default arity of `func`. @@ -1578,9 +1499,9 @@ */ function baseCurry(func, bitmask, arity) { if (typeof arity != 'number') { - arity = arity == null ? (func ? func.length : 0) : (+arity || 0); + arity = arity == null ? (func ? func.length : 0) : nativeMax(+arity || 0, 0); } - return createWrapper([func, bitmask, arity]); + return createWrapper(func, bitmask, arity); } /** @@ -2214,12 +2135,9 @@ arity -= args.length; } - var isPartial = bitmask & PARTIAL_FLAG, - newData = [func, bitmask, arity, thisArg, null, null]; - - newData[isPartial ? 4 : 6] = args; - newData[isPartial ? 5 : 7] = holders; - return createWrapper(newData); + return (bitmask & PARTIAL_FLAG) + ? createWrapper(func, bitmask, arity, thisArg, args, holders) + : createWrapper(func, bitmask, arity, thisArg, null, null, args, holders); } /** @@ -2576,17 +2494,16 @@ } /** - * Creates a function that invokes the function specified in the metadata - * with its associated `this` binding. + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new bound function. + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. */ - function createBindWrapper(data) { - var func = data[0], - thisArg = data[3], - Ctor = createCtorWrapper(func); + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); function wrapper() { return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); @@ -2631,6 +2548,77 @@ }; } + /** + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. + * @returns {Function} Returns the new function. + */ + function createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG; + + var Ctor = !isBindKey && createCtorWrapper(func), + key = func; + + function wrapper() { + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partialArgs) { + args = composeArgs(partialArgs, partialHolders, args); + } + if (partialRightArgs) { + args = composeArgsRight(partialRightArgs, partialRightHolders, args); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, + holders = replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + var newArity = nativeMax(arity - length, 0), + newPartialArgs = isCurry ? args : null, + newPartialHolders = isCurry ? holders : null, + newPartialRightArgs = isCurry ? null : args, + newPartialRightHolders = isCurry ? null : holders; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var result = createHybridWrapper(func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders); + result.placeholder = placeholder; + return setData(result, [func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders]); + } + } + var thisBinding = isBind ? thisArg : this; + if (isBindKey) { + func = thisBinding[key]; + } + return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); + } + return wrapper; + } + /** * Creates the pad required for `string` based on the given padding length. * The `chars` string may be truncated if the number of padding characters @@ -2655,19 +2643,19 @@ } /** - * Creates a function that invokes the function specified in the metadata - * with its associated partially applied arguments and optional `this` binding. + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partialArgs` prepended to those provided to + * the wrapper. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {Array} partialArgs An array of arguments to prepend to those provided to the new function. + * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new bound function. */ - function createPartialWrapper(data) { - var func = data[0], - thisArg = data[3], - partialArgs = data[4]; - - var isBind = data[1] & BIND_FLAG, + function createPartialWrapper(func, bitmask, partialArgs, thisArg) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { @@ -2695,9 +2683,8 @@ * `this` binding and partially applied arguments. * * @private - * @param {Array} data The metadata array. - * @param {Function|string} data[0] The function or method name to reference. - * @param {number} data[1] The bitmask of flags to compose. + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` @@ -2706,97 +2693,79 @@ * 16 - `_.curry` or `_.curryRight` of a bound function * 32 - `_.partial` * 64 - `_.partialRight` - * @param {number} data[2] The arity of `data[0]`. - * @param {*} [data[3]] The `this` binding of `data[0]`. - * @param {Array} [data[4]] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [data[5]] An array of `data[4]` placeholder indexes. - * @param {Array} [data[6]] An array of arguments to append to those - * provided to the new function. - * @param {Array} [data[7]] An array of `data[6]` placeholder indexes. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ - function createWrapper(data) { - var func = data[0], - bitmask = data[1]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isPartial = bitmask & PARTIAL_FLAG, - isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; - + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && !isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } - var arity = data[2], - partialArgs = data[4], - partialRightArgs = data[6]; - + var isPartial = bitmask & PARTIAL_FLAG; if (isPartial && !partialArgs.length) { + bitmask &= ~PARTIAL_FLAG; isPartial = false; - data[1] = (bitmask &= ~PARTIAL_FLAG); - data[4] = data[5] = partialArgs = null; + partialArgs = partialHolders = null; } + var isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (isPartialRight && !partialRightArgs.length) { + bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = false; - data[1] = (bitmask &= ~PARTIAL_RIGHT_FLAG); - data[6] = data[7] = partialRightArgs = null; - } - var funcData = !isBindKey && func[EXPANDO]; - if (funcData && funcData !== true) { - // shallow clone `funcData` - funcData = baseSlice(funcData); - - // clone partial left arguments - if (funcData[4]) { - funcData[4] = baseSlice(funcData[4]); - funcData[5] = baseSlice(funcData[5]); - } - // clone partial right arguments - if (funcData[6]) { - funcData[6] = baseSlice(funcData[6]); - funcData[7] = baseSlice(funcData[7]); - } - // set arity if provided - if (typeof arity == 'number') { - funcData[2] = arity; + partialRightArgs = partialRightHolders = null; + } + var data = !isBindKey && func[EXPANDO]; + if (data && data !== true) { + var funcBitmask = data[1], + funcIsBind = funcBitmask & BIND_FLAG, + isBind = bitmask & BIND_FLAG; + + // use metadata `func` and merge bitmasks + func = data[0]; + bitmask |= funcBitmask; + + // use metadata `arity` if not provided + if (arity == null) { + arity = data[2]; } - // set `thisArg` if not previously bound - var bound = funcData[1] & BIND_FLAG; - if (isBind && !bound) { - funcData[3] = data[3]; + // use metadata `thisArg` if available + if (funcIsBind) { + thisArg = data[3]; } // set if currying a bound function - if (!isBind && bound) { + if (!isBind && funcIsBind) { bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments - if (isPartial) { - var funcPartialArgs = funcData[4]; - if (funcPartialArgs) { - funcPartialArgs = composeArgs(funcPartialArgs, funcData[5], partialArgs); - } - funcData[4] = funcPartialArgs || partialArgs; - funcData[5] = funcPartialArgs ? replaceHolders(funcPartialArgs, PLACEHOLDER) : data[5]; + var funcArgs = data[4]; + if (funcArgs) { + var funcHolders = data[5]; + partialArgs = isPartial ? composeArgs(funcArgs, funcHolders, partialArgs) : baseSlice(funcArgs); + partialHolders = isPartial ? replaceHolders(partialArgs, PLACEHOLDER) : baseSlice(funcHolders); } // prepend partial right arguments - if (isPartialRight) { - var funcPartialRightArgs = funcData[6]; - if (funcPartialRightArgs) { - funcPartialRightArgs = composeArgsRight(funcPartialRightArgs, funcData[7], partialRightArgs); - } - funcData[6] = funcPartialRightArgs || partialRightArgs; - funcData[7] = funcPartialRightArgs ? replaceHolders(funcPartialRightArgs, PLACEHOLDER) : data[7]; + funcArgs = data[6]; + if (funcArgs) { + funcHolders = data[7]; + partialRightArgs = isPartialRight ? composeArgsRight(funcArgs, funcHolders, partialRightArgs) : baseSlice(funcArgs); + partialRightHolders = isPartialRight ? replaceHolders(partialRightArgs, PLACEHOLDER) : baseSlice(funcHolders); } - // merge flags - funcData[1] |= bitmask; - return createWrapper(funcData); } if (arity == null) { arity = isBindKey ? 0 : func.length; } - data[2] = nativeMax(arity, 0); - return baseCreateWrapper(data); + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(func, thisArg); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { + result = createPartialWrapper(func, bitmask, partialArgs, thisArg); + } else { + result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); + } + return setData(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); } /** @@ -5787,12 +5756,12 @@ */ function bind(func, thisArg) { if (arguments.length < 3) { - return createWrapper([func, BIND_FLAG, null, thisArg]); + return createWrapper(func, BIND_FLAG, null, thisArg); } var args = slice(arguments, 2), - partialHolders = replaceHolders(args, bind.placeholder); + holders = replaceHolders(args, bind.placeholder); - return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, partialHolders, thisArg); + return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, holders, thisArg); } /** @@ -5865,12 +5834,14 @@ * // => 'hiya fred!' */ function bindKey(object, key) { - var data = [key, BIND_FLAG | BIND_KEY_FLAG, null, object]; + var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (arguments.length > 2) { var args = slice(arguments, 2); - data.push(args, replaceHolders(args, bindKey.placeholder)); + holders = replaceHolders(args, bindKey.placeholder); } - return createWrapper(data); + return args + ? createWrapper(key, bitmask, null, object, args, holders) + : createWrapper(key, bitmask, null, object); } /** @@ -6343,9 +6314,9 @@ */ function partial(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partial.placeholder); + holders = replaceHolders(args, partial.placeholder); - return basePartial(func, PARTIAL_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_FLAG, args, holders); } /** @@ -6381,9 +6352,9 @@ */ function partialRight(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partialRight.placeholder); + holders = replaceHolders(args, partialRight.placeholder); - return basePartial(func, PARTIAL_RIGHT_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_RIGHT_FLAG, args, holders); } /** From d6850ab358628f3e9c8d946d73622f8f45bf7ce9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 14 Aug 2014 09:37:15 -0700 Subject: [PATCH 1021/1608] Use WeakMaps if available to store function metadata. --- lodash.js | 55 +++++++++++++++++++++++++++++++++++++------------ test/index.html | 10 ++++++++- test/test.js | 7 ++++--- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/lodash.js b/lodash.js index c3ab49e2ab..3dc6b18fc5 100644 --- a/lodash.js +++ b/lodash.js @@ -121,7 +121,8 @@ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'window', 'WinRTError' + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ @@ -693,7 +694,8 @@ setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, - unshift = arrayProto.unshift; + unshift = arrayProto.unshift, + WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers */ var Float64Array = (function() { @@ -733,6 +735,9 @@ /** Used as the size, in bytes, of each Float64Array element */ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; + /** Used to store function metadata */ + var metaMap = WeakMap && new WeakMap; + /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; ctorByClass[float32Class] = context.Float32Array; @@ -1360,7 +1365,7 @@ if (typeof thisArg == 'undefined') { return func; } - var data = func[EXPANDO]; + var data = getData(func); if (typeof data == 'undefined') { if (support.funcNames) { data = !func.name; @@ -2130,7 +2135,7 @@ */ function basePartial(func, bitmask, args, holders, thisArg) { if (func) { - var data = func[EXPANDO], + var data = getData(func), arity = data ? data[2] : func.length; arity -= args.length; @@ -2718,7 +2723,7 @@ isPartialRight = false; partialRightArgs = partialRightHolders = null; } - var data = !isBindKey && func[EXPANDO]; + var data = !isBindKey && getData(func); if (data && data !== true) { var funcBitmask = data[1], funcIsBind = funcBitmask & BIND_FLAG, @@ -2783,6 +2788,23 @@ return argCount ? result(func, thisArg, argCount) : result; } + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + function getData(func) { + return metaMap.get(func); + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + getData = !defineProperty ? noop : function(func) { + return func[EXPANDO]; + }; + } + /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns @@ -2986,19 +3008,26 @@ } /** - * Sets wrapper metadata on a given function. + * Sets metadata for `func`. * * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = !defineProperty ? identity : function(func, value) { - descriptor.value = value; - defineProperty(func, EXPANDO, descriptor); - descriptor.value = null; + function setData(func, data) { + metaMap.set(func, data); return func; - }; + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + setData = !defineProperty ? identity : function(func, value) { + descriptor.value = value; + defineProperty(func, EXPANDO, descriptor); + descriptor.value = null; + return func; + }; + } /** * A fallback implementation of `_.isPlainObject` which checks if `value` diff --git a/test/index.html b/test/index.html index a65a4fe9b8..9efa47dc2a 100644 --- a/test/index.html +++ b/test/index.html @@ -54,7 +54,7 @@ var hasOwnProperty = objectProto.hasOwnProperty, fnToString = funcProto.toString, nativeString = fnToString.call(objectProto.toString), - noop = function() {}, + noop = function() { }, propertyIsEnumerable = objectProto.propertyIsEnumerable, reToString = /toString/g, whitespace = ' \t\x0B\f\xA0\ufeff\n\r\u2028\u2029\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; @@ -154,6 +154,9 @@ return Float64Array; }()); } + setProperty(window, '_WeakMap', window.WeakMap); + setProperty(window, 'WeakMap', noop); + setProperty(window, '_parseInt', parseInt); setProperty(window, 'parseInt', (function(_parseInt) { var checkStr = whitespace + '08', @@ -235,6 +238,11 @@ } setProperty(window, '_ArrayBuffer', undefined); + if (window._WeakMap) { + WeakMap = _WeakMap; + } + setProperty(window, '_WeakMap', undefined); + setProperty(window, 'parseInt', window._parseInt); setProperty(window, '_parseInt', undefined); diff --git a/test/test.js b/test/test.js index cc8fc90220..3becd5f6c2 100644 --- a/test/test.js +++ b/test/test.js @@ -38,7 +38,8 @@ slice = arrayProto.slice, system = root.system, toString = objectProto.toString, - Uint8Array = root.Uint8Array; + Uint8Array = root.Uint8Array, + WeakMap = root.WeakMap; /** The file path of the Lo-Dash file to test */ var filePath = (function() { @@ -2179,7 +2180,7 @@ var object = {}; - if (defineProperty && _.support.funcDecomp) { + if ((defineProperty && !WeakMap) && _.support.funcDecomp) { _.callback(a, object); ok(EXPANDO in a); @@ -2205,7 +2206,7 @@ test('should not write metadata when `_.support.funcDecomp` is `false`', 1, function() { function a() {}; - if (defineProperty && lodashBizarro) { + if ((defineProperty && !WeakMap) && lodashBizarro) { lodashBizarro.callback(a, {}); ok(!(EXPANDO in a)); } From 9b0aadccf86bf1c64fc02815c29d72bd7897ce0e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 14 Aug 2014 14:27:33 -0700 Subject: [PATCH 1022/1608] Fix accidental leaked var. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 3dc6b18fc5..0f664de6bf 100644 --- a/lodash.js +++ b/lodash.js @@ -5865,7 +5865,7 @@ function bindKey(object, key) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (arguments.length > 2) { - var args = slice(arguments, 2); + var args = slice(arguments, 2), holders = replaceHolders(args, bindKey.placeholder); } return args From d317171a4574f01cac7f8545b5a5de240c89da79 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 15 Aug 2014 08:38:50 -0700 Subject: [PATCH 1023/1608] Remove sauce testing of older Firefox. --- test/saucelabs.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index 5879926599..91dd32bbdb 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -101,7 +101,6 @@ var platforms = [ ['Windows 8.1', 'firefox', '31'], ['Windows 8.1', 'firefox', '30'], ['Windows 8.1', 'firefox', '20'], - ['Windows 8.1', 'firefox', '3.0'], ['Windows 8.1', 'chrome', '36'], ['Windows 8.1', 'chrome', '35'], ['Windows 8.1', 'internet explorer', '11'], From cfeb8d053f0362fdd5cdb7f7c36dc157f9099b2c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 16 Aug 2014 23:03:43 -0700 Subject: [PATCH 1024/1608] Attempt to throttle `seData`. --- lodash.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index 0f664de6bf..afec72c8b1 100644 --- a/lodash.js +++ b/lodash.js @@ -3015,13 +3015,13 @@ * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - function setData(func, data) { + function baseSetData(func, data) { metaMap.set(func, data); return func; } // fallback for environments without `WeakMap` if (!WeakMap) { - setData = !defineProperty ? identity : function(func, value) { + baseSetData = !defineProperty ? identity : function(func, value) { descriptor.value = value; defineProperty(func, EXPANDO, descriptor); descriptor.value = null; @@ -3029,6 +3029,31 @@ }; } + function trip(func, times, wait) { + var count = 0, + lastCalled = 0; + + return function(key, value) { + var stamp = now ? now() : 0, + remaining = wait - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count > times) { + var dataFunc = typeof value == 'object' && isFunction(dataFunc = value[0]) && dataFunc; + if (typeof getData(key) == 'undefined' && !(dataFunc && getData(dataFunc) != 'undefined')) { + return key; + } + } + } else { + count = 0; + } + return func(key, value); + } + } + + var setData = trip(baseSetData, 50, 16); + /** * A fallback implementation of `_.isPlainObject` which checks if `value` * is an object created by the `Object` constructor or has a `[[Prototype]]` From 6f898c6c9739002d3855e94ad20c7fb8029aab4d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 13:42:07 -0700 Subject: [PATCH 1025/1608] Fix perf regression in _.omit & _.reject. --- lodash.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lodash.js b/lodash.js index afec72c8b1..a6ad667c85 100644 --- a/lodash.js +++ b/lodash.js @@ -5437,8 +5437,12 @@ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); - return filter(collection, negate(predicate)); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); } /** @@ -7732,9 +7736,14 @@ return {}; } var iterable = toObject(object); - return typeof predicate == 'function' - ? pickByCallback(iterable, negate(getCallback(predicate, thisArg, 3))) - : pickByArray(iterable, baseDifference(keysIn(iterable), arrayMap(baseFlatten(arguments, false, false, 1), String))); + if (typeof predicate != 'function') { + var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + return pickByArray(iterable, baseDifference(keysIn(iterable), props)); + } + predicate = getCallback(predicate, thisArg, 3); + return pickByCallback(iterable, function(value, key, object) { + return !predicate(value, key, object); + }); } /** From 8ff97468ccffb82300b3a1f30c37b37ebdeb3466 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 13:42:24 -0700 Subject: [PATCH 1026/1608] Minor style nits. --- lodash.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lodash.js b/lodash.js index a6ad667c85..4ec5e877ce 100644 --- a/lodash.js +++ b/lodash.js @@ -4734,10 +4734,10 @@ * // => false */ function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arrayEvery : baseEvery; return func(collection, predicate); } @@ -4782,9 +4782,9 @@ * // => [{ 'name': 'barney', 'age': 36 }] */ function filter(collection, predicate, thisArg) { - predicate = getCallback(predicate, thisArg, 3); - var func = isArray(collection) ? arrayFilter : baseFilter; + + predicate = getCallback(predicate, thisArg, 3); return func(collection, predicate); } @@ -5576,10 +5576,10 @@ * // => false */ function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arraySome : baseSome; return func(collection, predicate); } From ee10e17ce78f772d85b180708d2133ce4b522c51 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 14:10:47 -0700 Subject: [PATCH 1027/1608] Fix perf regression of `_.zip`. --- lodash.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 4ec5e877ce..b95b2ab860 100644 --- a/lodash.js +++ b/lodash.js @@ -4415,7 +4415,13 @@ * // => [['fred', 30, true], ['barney', 40, false]] */ function zip() { - return unzip(arguments); + var length = arguments.length, + array = Array(length); + + while (length--) { + array[length] = arguments[length]; + } + return unzip(array); } /** From 54d22a23b5fe23cf253a72493c74a0dba4122484 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 14:12:13 -0700 Subject: [PATCH 1028/1608] Avoid metadata cache for perf tests of slow paths of `_.bind` and `_.partial`. --- perf/perf.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/perf/perf.js b/perf/perf.js index 6248b71a66..f00aad74b3 100644 --- a/perf/perf.js +++ b/perf/perf.js @@ -586,11 +586,11 @@ suites.push( Benchmark.Suite('`_.bind` (slow path)') .add(buildName, { - 'fn': 'lodash.bind(func, { "name": "fred" })', + 'fn': 'lodash.bind(function() { return this.name; }, { "name": "fred" })', 'teardown': 'function bind(){}' }) .add(otherName, { - 'fn': '_.bind(func, { "name": "fred" })', + 'fn': '_.bind(function() { return this.name; }, { "name": "fred" })', 'teardown': 'function bind(){}' }) ); @@ -1533,11 +1533,11 @@ suites.push( Benchmark.Suite('`_.partial` (slow path)') .add(buildName, { - 'fn': 'lodash.partial(func, "hi")', + 'fn': 'lodash.partial(function(greeting) { return greeting + " " + this.name; }, "hi")', 'teardown': 'function partial(){}' }) .add(otherName, { - 'fn': '_.partial(func, "hi")', + 'fn': '_.partial(function(greeting) { return greeting + " " + this.name; }, "hi")', 'teardown': 'function partial(){}' }) ); From 34b575da03fe01d8c633d017ea1809e7ce08d00a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 14:37:50 -0700 Subject: [PATCH 1029/1608] Minor var nit in `createPartialWrapper`. --- lodash.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.js b/lodash.js index b95b2ab860..1385e36fb5 100644 --- a/lodash.js +++ b/lodash.js @@ -2666,7 +2666,7 @@ function wrapper() { // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` - var argsIndex = 0, + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partialArgs.length, @@ -2676,7 +2676,7 @@ args[leftIndex] = partialArgs[leftIndex]; } while (argsLength--) { - args[leftIndex++] = arguments[argsIndex++]; + args[leftIndex++] = arguments[++argsIndex]; } return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); } From 9a147218ce81d2418b04a206b2cb8c474f8b1fb9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 15:39:54 -0700 Subject: [PATCH 1030/1608] Add `console.log` shim to avoid errors while deving. --- test/asset/worker.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/asset/worker.js b/test/asset/worker.js index d925de5239..ed40d4a7ea 100644 --- a/test/asset/worker.js +++ b/test/asset/worker.js @@ -1,9 +1,12 @@ +if (!self.console) { + console = { 'log': function() {} }; +} addEventListener('message', function(e) { if (e.data) { try { importScripts('../' + e.data); } catch(e) { - self._ = {}; + self._ = { 'VERSION': e.message }; } postMessage(_.VERSION); } From 1416655d533e41e23db150f26b87fc69e8598885 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 17 Aug 2014 15:40:16 -0700 Subject: [PATCH 1031/1608] Minor whitespace nit. --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 9efa47dc2a..8e80e4e461 100644 --- a/test/index.html +++ b/test/index.html @@ -54,7 +54,7 @@ var hasOwnProperty = objectProto.hasOwnProperty, fnToString = funcProto.toString, nativeString = fnToString.call(objectProto.toString), - noop = function() { }, + noop = function() {}, propertyIsEnumerable = objectProto.propertyIsEnumerable, reToString = /toString/g, whitespace = ' \t\x0B\f\xA0\ufeff\n\r\u2028\u2029\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; From 8f9eed154e474f455a015a743cf23b11b640d8bf Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 18 Aug 2014 00:35:04 -0700 Subject: [PATCH 1032/1608] Cleanup `setData`. --- lodash.js | 72 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/lodash.js b/lodash.js index 1385e36fb5..177ecb4413 100644 --- a/lodash.js +++ b/lodash.js @@ -23,6 +23,10 @@ PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64; + /** Used to detect when a function becomes hot */ + var HOT_COUNT = 150, + HOT_SPAN = 16; + /** Used as the property name for wrapper metadata */ var EXPANDO = '__lodash_' + VERSION.replace(/[-.]/g, '_') + '__'; @@ -1379,7 +1383,7 @@ if (!data) { // checks if `func` references the `this` keyword and stores the result data = reThis.test(source) || isNative(func); - setData(func, data); + baseSetData(func, data); } } } @@ -2205,6 +2209,28 @@ return accumulator; } + /** + * The base implementation of `setData` without support for hot loop detection. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + function baseSetData(func, data) { + metaMap.set(func, data); + return func; + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + baseSetData = !defineProperty ? identity : function(func, value) { + descriptor.value = value; + defineProperty(func, EXPANDO, descriptor); + descriptor.value = null; + return func; + }; + } + /** * The base implementation of `_.some` without support for callback shorthands * or `this` binding. @@ -2723,8 +2749,8 @@ isPartialRight = false; partialRightArgs = partialRightHolders = null; } - var data = !isBindKey && getData(func); - if (data && data !== true) { + var data = (data = !isBindKey && getData(func)) && data !== true && data; + if (data) { var funcBitmask = data[1], funcIsBind = funcBitmask & BIND_FLAG, isBind = bitmask & BIND_FLAG; @@ -2770,7 +2796,8 @@ } else { result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); } - return setData(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); + var setter = data ? baseSetData : setData; + return setter(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); } /** @@ -3010,49 +3037,34 @@ /** * Sets metadata for `func`. * + * **Note**: If this function becomes hot, i.e. is called a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses. + * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - function baseSetData(func, data) { - metaMap.set(func, data); - return func; - } - // fallback for environments without `WeakMap` - if (!WeakMap) { - baseSetData = !defineProperty ? identity : function(func, value) { - descriptor.value = value; - defineProperty(func, EXPANDO, descriptor); - descriptor.value = null; - return func; - }; - } - - function trip(func, times, wait) { + var setData = (function() { var count = 0, lastCalled = 0; return function(key, value) { var stamp = now ? now() : 0, - remaining = wait - (stamp - lastCalled); + remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { - if (++count > times) { - var dataFunc = typeof value == 'object' && isFunction(dataFunc = value[0]) && dataFunc; - if (typeof getData(key) == 'undefined' && !(dataFunc && getData(dataFunc) != 'undefined')) { - return key; - } + if (++count > HOT_COUNT) { + return key; } } else { count = 0; } - return func(key, value); - } - } - - var setData = trip(baseSetData, 50, 16); + return baseSetData(key, value); + }; + }()); /** * A fallback implementation of `_.isPlainObject` which checks if `value` From d4e058a84430697bb0f706bc93bd81fc2f6f73e4 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 19 Aug 2014 09:08:04 -0700 Subject: [PATCH 1033/1608] Add `_.negate` unit test. --- test/test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/test.js b/test/test.js index 3becd5f6c2..51e4cf6b81 100644 --- a/test/test.js +++ b/test/test.js @@ -7656,6 +7656,22 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.negate'); + + (function() { + test('should create a function that negates the result of `func`', 2, function() { + function isEven(n) { + return n % 2 == 0; + } + + var negate = _.negate(isEven); + strictEqual(negate(1), true); + strictEqual(negate(2), false); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.noop'); (function() { From 921209580a5fe7cf8ecc1be74102934e1bf9b380 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 19 Aug 2014 10:32:37 -0700 Subject: [PATCH 1034/1608] Add DOM node check to `_.isFunction` test. --- test/test.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/test/test.js b/test/test.js index 51e4cf6b81..117ab8b11e 100644 --- a/test/test.js +++ b/test/test.js @@ -5983,17 +5983,18 @@ strictEqual(_.isFunction('a'), false); }); - test('should work with host objects in non-edge document modes (test in IE 11)', 1, function() { - if (xml) { - // trigger Chakra bug - // https://github.com/jashkenas/underscore/issues/1621 - _.times(100, _.isFunction); - - strictEqual(_.isFunction(xml), false); - } - else { - skipTest(); - } + test('should work with host objects in IE 8 document mode (test in IE 11)', 2, function() { + // trigger Chakra bug + // https://github.com/jashkenas/underscore/issues/1621 + _.each([body, xml], function(object) { + if (object) { + _.times(100, _.isFunction); + strictEqual(_.isFunction(object), false); + } + else { + skipTest(); + } + }); }); test('should work with functions from another realm', 1, function() { From df3540b0f950fe8aa2ddeb3cbeef3cf44cd30552 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 19 Aug 2014 23:48:46 -0700 Subject: [PATCH 1035/1608] Expose `_.isNative`. --- lodash.js | 61 +++++++++++-------- test/test.js | 166 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 172 insertions(+), 55 deletions(-) diff --git a/lodash.js b/lodash.js index 177ecb4413..9957c7bcdf 100644 --- a/lodash.js +++ b/lodash.js @@ -672,6 +672,9 @@ /** 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 restore the original `_` reference in `_.noConflict` */ var oldDash = context._; @@ -691,7 +694,6 @@ clearTimeout = context.clearTimeout, floor = Math.floor, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, - hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = isNative(Set = context.Set) && Set, @@ -801,17 +803,17 @@ * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, - * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, - * `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, - * `isString`, `isUndefined`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, - * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, - * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, - * `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, - * `unescape`, `uniqueId`, and `value` + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, + * `lastIndexOf`, `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, + * `padRight`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, + * `result`, `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, + * `sortedLastIndex`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `unescape`, `uniqueId`, and `value` * * The wrapper function `sample` will return a wrapped value when `n` is * provided, otherwise it will return an unwrapped value. @@ -2941,20 +2943,6 @@ arrayLikeClasses[toString.call(value)]) || false; } - /** - * Checks if `value` is a native function. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, else `false`. - */ - function isNative(value) { - var type = typeof value; - return type == 'function' - ? reNative.test(fnToString.call(value)) - : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; - } - /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * @@ -7363,6 +7351,28 @@ return isNumber(value) && value != +value; } + /** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Object + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + */ + function isNative(value) { + var type = typeof value; + if (type == 'function') { + return reNative.test(fnToString.call(value)); + } + if (value && type == 'object') { + return !('constructor' in value && 'toString' in value) + ? reNative.test(value) + : reHostCtor.test(toString.call(value)); + } + return false; + } + /** * Checks if `value` is `null`. * @@ -9419,6 +9429,7 @@ lodash.isFinite = isFinite; lodash.isFunction = isFunction; lodash.isNaN = isNaN; + lodash.isNative = isNative; lodash.isNull = isNull; lodash.isNumber = isNumber; lodash.isObject = isObject; diff --git a/test/test.js b/test/test.js index 117ab8b11e..51af1b1a21 100644 --- a/test/test.js +++ b/test/test.js @@ -4937,27 +4937,29 @@ strictEqual(_.isArguments(args), true); }); - test('should return `false` for non `arguments` objects', 10, function() { + test('should return `false` for non `arguments` objects', 12, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { return index ? _.isArguments(value) : _.isArguments(); }); + deepEqual(actual, expected); + strictEqual(_.isArguments([1, 2, 3]), false); strictEqual(_.isArguments(true), false); strictEqual(_.isArguments(new Date), false); strictEqual(_.isArguments(new Error), false); strictEqual(_.isArguments(_), false); + strictEqual(_.isArguments(slice), false); strictEqual(_.isArguments({ '0': 1, 'callee': _.noop, 'length': 1 }), false); strictEqual(_.isArguments(1), false); + strictEqual(_.isArguments(NaN), false); strictEqual(_.isArguments(/x/), false); strictEqual(_.isArguments('a'), false); - - deepEqual(actual, expected); }); - test('should work with `arguments` objects from another realm', 1, function() { + test('should work with an `arguments` object from another realm', 1, function() { if (_._object) { strictEqual(_.isArguments(_._arguments), true); } @@ -4978,7 +4980,7 @@ strictEqual(_.isArray([1, 2, 3]), true); }); - test('should return `false` for non arrays', 10, function() { + test('should return `false` for non arrays', 12, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { @@ -4992,13 +4994,15 @@ strictEqual(_.isArray(new Date), false); strictEqual(_.isArray(new Error), false); strictEqual(_.isArray(_), false); + strictEqual(_.isArray(slice), false); strictEqual(_.isArray({ '0': 1, 'length': 1 }), false); strictEqual(_.isArray(1), false); + strictEqual(_.isArray(NaN), false); strictEqual(_.isArray(/x/), false); strictEqual(_.isArray('a'), false); }); - test('should work with arrays from another realm', 1, function() { + test('should work with an array from another realm', 1, function() { if (_._object) { strictEqual(_.isArray(_._array), true); } @@ -5022,7 +5026,7 @@ strictEqual(_.isBoolean(Object(false)), true); }); - test('should return `false` for non booleans', 10, function() { + test('should return `false` for non booleans', 12, function() { var expected = _.map(falsey, function(value) { return value === false; }); var actual = _.map(falsey, function(value, index) { @@ -5036,13 +5040,15 @@ strictEqual(_.isBoolean(new Date), false); strictEqual(_.isBoolean(new Error), false); strictEqual(_.isBoolean(_), false); + strictEqual(_.isBoolean(slice), false); strictEqual(_.isBoolean({ 'a': 1 }), false); strictEqual(_.isBoolean(1), false); + strictEqual(_.isBoolean(NaN), false); strictEqual(_.isBoolean(/x/), false); strictEqual(_.isBoolean('a'), false); }); - test('should work with booleans from another realm', 1, function() { + test('should work with a boolean from another realm', 1, function() { if (_._object) { strictEqual(_.isBoolean(_._boolean), true); } @@ -5063,7 +5069,7 @@ strictEqual(_.isDate(new Date), true); }); - test('should return `false` for non dates', 10, function() { + test('should return `false` for non dates', 12, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { @@ -5077,13 +5083,15 @@ strictEqual(_.isDate(true), false); strictEqual(_.isDate(new Error), false); strictEqual(_.isDate(_), false); + strictEqual(_.isDate(slice), false); strictEqual(_.isDate({ 'a': 1 }), false); strictEqual(_.isDate(1), false); + strictEqual(_.isDate(NaN), false); strictEqual(_.isDate(/x/), false); strictEqual(_.isDate('a'), false); }); - test('should work with dates from another realm', 1, function() { + test('should work with a date object from another realm', 1, function() { if (_._object) { strictEqual(_.isDate(_._date), true); } @@ -5130,7 +5138,7 @@ } }); - test('should return `false` for non DOM elements', 11, function() { + test('should return `false` for non DOM elements', 13, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { @@ -5145,13 +5153,15 @@ strictEqual(_.isElement(new Date), false); strictEqual(_.isElement(new Error), false); strictEqual(_.isElement(_), false); + strictEqual(_.isElement(slice), false); strictEqual(_.isElement({ 'a': 1 }), false); strictEqual(_.isElement(1), false); + strictEqual(_.isElement(NaN), false); strictEqual(_.isElement(/x/), false); strictEqual(_.isElement('a'), false); }); - test('should work with DOM elements from another realm', 1, function() { + test('should work with a DOM element from another realm', 1, function() { if (_._element) { strictEqual(_.isElement(_._element), true); } @@ -5168,7 +5178,7 @@ (function() { var args = arguments; - test('should return `true` for empty or falsey values', 3, function() { + test('should return `true` for empty or falsey values', 9, function() { var expected = _.map(empties, _.constant(true)); var actual = _.map(empties, function(value) { @@ -5177,8 +5187,14 @@ deepEqual(actual, expected); - strictEqual(_.isEmpty(), true); + strictEqual(_.isEmpty(true), true); + strictEqual(_.isEmpty(new Date), true); + strictEqual(_.isEmpty(new Error), true); + strictEqual(_.isEmpty(slice), true); + strictEqual(_.isEmpty(1), true); + strictEqual(_.isEmpty(NaN), true); strictEqual(_.isEmpty(/x/), true); + strictEqual(_.isEmpty(), true); }); test('should return `false` for non-empty values', 3, function() { @@ -5866,7 +5882,7 @@ deepEqual(actual, expected); }); - test('should return `false` for non-error objects', 10, function() { + test('should return `false` for non-error objects', 12, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { @@ -5880,8 +5896,10 @@ strictEqual(_.isError(true), false); strictEqual(_.isError(new Date), false); strictEqual(_.isError(_), false); + strictEqual(_.isError(slice), false); strictEqual(_.isError({ 'a': 1 }), false); strictEqual(_.isError(1), false); + strictEqual(_.isError(NaN), false); strictEqual(_.isError(/x/), false); strictEqual(_.isError('a'), false); }); @@ -5907,6 +5925,8 @@ QUnit.module('lodash.isFinite'); (function() { + var args = arguments; + test('should return `true` for finite values', 1, function() { var values = [0, 1, 3.14, -1], expected = _.map(values, _.constant(true)); @@ -5918,7 +5938,7 @@ deepEqual(actual, expected); }); - test('should return `false` for non-finite values', 1, function() { + test('should return `false` for non-finite values', 9, function() { var values = [NaN, Infinity, -Infinity, Object(1)], expected = _.map(values, _.constant(false)); @@ -5927,6 +5947,15 @@ }); deepEqual(actual, expected); + + strictEqual(_.isFinite(args), false); + strictEqual(_.isFinite([1, 2, 3]), false); + strictEqual(_.isFinite(true), false); + strictEqual(_.isFinite(new Date), false); + strictEqual(_.isFinite(new Error), false); + strictEqual(_.isFinite({ 'a': 1 }), false); + strictEqual(_.isFinite(/x/), false); + strictEqual(_.isFinite('a'), false); }); test('should return `false` for non-numeric values', 1, function() { @@ -5950,7 +5979,7 @@ deepEqual(actual, expected); }); - }()); + }(1, 2, 3)); /*--------------------------------------------------------------------------*/ @@ -5959,11 +5988,12 @@ (function() { var args = arguments; - test('should return `true` for functions', 1, function() { + test('should return `true` for functions', 2, function() { strictEqual(_.isFunction(_), true); + strictEqual(_.isFunction(slice), true); }); - test('should return `false` for non functions', 10, function() { + test('should return `false` for non functions', 11, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { @@ -5979,6 +6009,7 @@ strictEqual(_.isFunction(new Error), false); strictEqual(_.isFunction({ 'a': 1 }), false); strictEqual(_.isFunction(1), false); + strictEqual(_.isFunction(NaN), false); strictEqual(_.isFunction(/x/), false); strictEqual(_.isFunction('a'), false); }); @@ -5997,7 +6028,7 @@ }); }); - test('should work with functions from another realm', 1, function() { + test('should work with a function from another realm', 1, function() { if (_._object) { strictEqual(_.isFunction(_._function), true); } @@ -6019,7 +6050,7 @@ strictEqual(_.isNaN(Object(NaN)), true); }); - test('should return `false` for non NaNs', 11, function() { + test('should return `false` for non NaNs', 12, function() { var expected = _.map(falsey, function(value) { return value !== value; }); var actual = _.map(falsey, function(value, index) { @@ -6034,13 +6065,14 @@ strictEqual(_.isNaN(new Date), false); strictEqual(_.isNaN(new Error), false); strictEqual(_.isNaN(_), false); + strictEqual(_.isNaN(slice), false); strictEqual(_.isNaN({ 'a': 1 }), false); strictEqual(_.isNaN(1), false); strictEqual(_.isNaN(/x/), false); strictEqual(_.isNaN('a'), false); }); - test('should work with NaNs from another realm', 1, function() { + test('should work with `NaN` from another realm', 1, function() { if (_._object) { strictEqual(_.isNaN(_._nan), true); } @@ -6052,6 +6084,69 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.isNative'); + + (function() { + var args = arguments; + + test('should return `true` for native methods', 10, function() { + _.each([root.alert, Array, create, freeze, root.prompt, push, slice, Uint8Array, WeakMap], function(func, i) { + if (func) { + strictEqual(_.isNative(func), true, String(i)); + } + else { + skipTest(); + } + }); + + if (body) { + strictEqual(_.isNative(body.cloneNode), true); + } + else { + skipTest(); + } + }); + + test('should return `false` for non native methods', 12, function() { + var expected = _.map(falsey, _.constant(false)); + + var actual = _.map(falsey, function(value, index) { + return index ? _.isNative(value) : _.isNative(); + }); + + deepEqual(actual, expected); + + strictEqual(_.isNative(args), false); + strictEqual(_.isNative([1, 2, 3]), false); + strictEqual(_.isNative(true), false); + strictEqual(_.isNative(new Date), false); + strictEqual(_.isNative(new Error), false); + strictEqual(_.isNative(_), false); + strictEqual(_.isNative({ 'a': 1 }), false); + strictEqual(_.isNative(1), false); + strictEqual(_.isNative(NaN), false); + strictEqual(_.isNative(/x/), false); + strictEqual(_.isNative('a'), false); + }); + + test('should work with native functions from another realm', 2, function() { + if (_._element) { + strictEqual(_.isNative(_._element.cloneNode), true); + } + else { + skipTest(); + } + if (_._object) { + strictEqual(_.isNative(_._object.valueOf), true); + } + else { + skipTest(); + } + }); + }(1, 2, 3)); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.isNull'); (function() { @@ -6061,7 +6156,7 @@ strictEqual(_.isNull(null), true); }); - test('should return `false` for non nulls', 11, function() { + test('should return `false` for non nulls', 13, function() { var expected = _.map(falsey, function(value) { return value === null; }); var actual = _.map(falsey, function(value, index) { @@ -6076,8 +6171,10 @@ strictEqual(_.isNull(new Date), false); strictEqual(_.isNull(new Error), false); strictEqual(_.isNull(_), false); + strictEqual(_.isNull(slice), false); strictEqual(_.isNull({ 'a': 1 }), false); strictEqual(_.isNull(1), false); + strictEqual(_.isNull(NaN), false); strictEqual(_.isNull(/x/), false); strictEqual(_.isNull('a'), false); }); @@ -6099,12 +6196,13 @@ (function() { var args = arguments; - test('should return `true` for numbers', 2, function() { + test('should return `true` for numbers', 3, function() { strictEqual(_.isNumber(0), true); strictEqual(_.isNumber(Object(0)), true); + strictEqual(_.isNumber(NaN), true); }); - test('should return `false` for non numbers', 10, function() { + test('should return `false` for non numbers', 11, function() { var expected = _.map(falsey, function(value) { return typeof value == 'number'; }); var actual = _.map(falsey, function(value, index) { @@ -6119,6 +6217,7 @@ strictEqual(_.isNumber(new Date), false); strictEqual(_.isNumber(new Error), false); strictEqual(_.isNumber(_), false); + strictEqual(_.isNumber(slice), false); strictEqual(_.isNumber({ 'a': 1 }), false); strictEqual(_.isNumber(/x/), false); strictEqual(_.isNumber('a'), false); @@ -6145,13 +6244,14 @@ (function() { var args = arguments; - test('should return `true` for objects', 11, function() { + test('should return `true` for objects', 12, function() { strictEqual(_.isObject(args), true); strictEqual(_.isObject([1, 2, 3]), true); strictEqual(_.isObject(Object(false)), true); strictEqual(_.isObject(new Date), true); strictEqual(_.isObject(new Error), true); strictEqual(_.isObject(_), true); + strictEqual(_.isObject(slice), true); strictEqual(_.isObject({ 'a': 1 }), true); strictEqual(_.isObject(Object(0)), true); strictEqual(_.isObject(/x/), true); @@ -6301,7 +6401,7 @@ strictEqual(_.isRegExp(RegExp('x')), true); }); - test('should return `false` for non regexes', 10, function() { + test('should return `false` for non regexes', 12, function() { var expected = _.map(falsey, _.constant(false)); var actual = _.map(falsey, function(value, index) { @@ -6316,8 +6416,10 @@ strictEqual(_.isRegExp(new Date), false); strictEqual(_.isRegExp(new Error), false); strictEqual(_.isRegExp(_), false); + strictEqual(_.isRegExp(slice), false); strictEqual(_.isRegExp({ 'a': 1 }), false); strictEqual(_.isRegExp(1), false); + strictEqual(_.isRegExp(NaN), false); strictEqual(_.isRegExp('a'), false); }); @@ -6343,7 +6445,7 @@ strictEqual(_.isString(Object('a')), true); }); - test('should return `false` for non strings', 10, function() { + test('should return `false` for non strings', 12, function() { var expected = _.map(falsey, function(value) { return value === ''; }); var actual = _.map(falsey, function(value, index) { @@ -6358,8 +6460,10 @@ strictEqual(_.isString(new Date), false); strictEqual(_.isString(new Error), false); strictEqual(_.isString(_), false); + strictEqual(_.isString(slice), false); strictEqual(_.isString({ '0': 1, 'length': 1 }), false); strictEqual(_.isString(1), false); + strictEqual(_.isString(NaN), false); strictEqual(_.isString(/x/), false); }); @@ -6385,7 +6489,7 @@ strictEqual(_.isUndefined(undefined), true); }); - test('should return `false` for non `undefined` values', 11, function() { + test('should return `false` for non `undefined` values', 13, function() { var expected = _.map(falsey, function(value) { return value === undefined; }); var actual = _.map(falsey, function(value, index) { @@ -6400,8 +6504,10 @@ strictEqual(_.isUndefined(new Date), false); strictEqual(_.isUndefined(new Error), false); strictEqual(_.isUndefined(_), false); + strictEqual(_.isUndefined(slice), false); strictEqual(_.isUndefined({ 'a': 1 }), false); strictEqual(_.isUndefined(1), false); + strictEqual(_.isUndefined(NaN), false); strictEqual(_.isUndefined(/x/), false); strictEqual(_.isUndefined('a'), false); }); @@ -11952,7 +12058,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 194, function() { + test('should accept falsey arguments', 195, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From 1423dcb619477920067a34a950f4106beeb9832f Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 20 Aug 2014 01:24:33 -0700 Subject: [PATCH 1036/1608] `_.sortBy` should not error on nullish elements when sorting by multiple properties. --- lodash.js | 2 +- test/test.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 9957c7bcdf..a22315ea8a 100644 --- a/lodash.js +++ b/lodash.js @@ -5656,7 +5656,7 @@ criteria = Array(length); while (length--) { - criteria[length] = value[iteratee[length]]; + criteria[length] = value == null ? undefined : value[iteratee[length]]; } } else { criteria = iteratee(value, key, collection); diff --git a/test/test.js b/test/test.js index 51af1b1a21..1b5339bd0d 100644 --- a/test/test.js +++ b/test/test.js @@ -9755,6 +9755,11 @@ deepEqual(actual, [objects[2], objects[0], objects[3], objects[1]]); }); + test('should not error on nullish elements when sorting by multiple properties', 1, function() { + var actual = _.sortBy(objects.concat(undefined), ['a', 'b']); + deepEqual(actual, [objects[2], objects[0], objects[3], objects[1], undefined]); + }); + test('should perform a stable sort when sorting by multiple properties (test in IE > 8, Opera, and V8)', 1, function() { var actual = _.sortBy(stableOrder, ['a', 'c']); deepEqual(actual, stableOrder); From 58b3e9f20180b696bf2f7f7966f55a776e931513 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 20 Aug 2014 01:29:48 -0700 Subject: [PATCH 1037/1608] Avoid test issues with error objects across environments. --- test/test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 1b5339bd0d..e36232356f 100644 --- a/test/test.js +++ b/test/test.js @@ -5178,7 +5178,7 @@ (function() { var args = arguments; - test('should return `true` for empty or falsey values', 9, function() { + test('should return `true` for empty or falsey values', 8, function() { var expected = _.map(empties, _.constant(true)); var actual = _.map(empties, function(value) { @@ -5189,7 +5189,6 @@ strictEqual(_.isEmpty(true), true); strictEqual(_.isEmpty(new Date), true); - strictEqual(_.isEmpty(new Error), true); strictEqual(_.isEmpty(slice), true); strictEqual(_.isEmpty(1), true); strictEqual(_.isEmpty(NaN), true); From bde931f2f5189ea919b2ab7b5151195dadf9debc Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 20 Aug 2014 02:29:02 -0700 Subject: [PATCH 1038/1608] Avoid testing constructors which may be shimmed. --- test/test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index e36232356f..f2f6f0f428 100644 --- a/test/test.js +++ b/test/test.js @@ -6088,10 +6088,10 @@ (function() { var args = arguments; - test('should return `true` for native methods', 10, function() { - _.each([root.alert, Array, create, freeze, root.prompt, push, slice, Uint8Array, WeakMap], function(func, i) { + test('should return `true` for native methods', 8, function() { + _.each([root.alert, Array, create, freeze, root.prompt, slice, Uint8Array], function(func) { if (func) { - strictEqual(_.isNative(func), true, String(i)); + strictEqual(_.isNative(func), true); } else { skipTest(); From c3126e24ce908f73c61bbfa11178f0e8687b0b94 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 20 Aug 2014 22:32:57 -0700 Subject: [PATCH 1039/1608] Add `_.support.hostObject` and rename `isNode` to `isHostObject`. --- lodash.js | 57 ++++++++++++++++++++++++++++------------------------ test/test.js | 1 + 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lodash.js b/lodash.js index a22315ea8a..3a84a8ec9d 100644 --- a/lodash.js +++ b/lodash.js @@ -544,19 +544,6 @@ return '\\' + stringEscapes[chr]; } - /** - * Checks if `value` is a DOM node in IE < 9. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM node, else `false`. - */ - function isNode(value) { - // IE < 9 presents DOM nodes as `Object` objects except they have `toString` - // methods that are `typeof` "string" and still can coerce nodes to strings - return typeof value.toString != 'function' && typeof (value + '') == 'string'; - } - /** * Used by `_.trimmedLeftIndex` and `_.trimmedRightIndex` to determine if a * character code is whitespace. @@ -1004,19 +991,25 @@ } /** - * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9) - * and that the JS engine errors when attempting to coerce an object to a - * string without a `toString` function. + * Detect if the host objects are detectable (IE < 9). * * @memberOf _.support * @type boolean */ try { - support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + '')); + support.hostObject = !({ 'toString': 0 } + ''); } catch(e) { - support.nodeClass = true; + support.hostObject = false; } + /** + * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). + * + * @memberOf _.support + * @type boolean + */ + support.nodeClass = !(toString.call(document) == objectClass && support.hostObject); + /** * Detect if `arguments` object indexes are non-enumerable. * @@ -1882,7 +1875,7 @@ return false; } } - else if (isErr || (valClass == objectClass && (support.nodeClass || !(isNode(value) || isNode(other))))) { + else if (isErr || (valClass == objectClass && (support.nodeClass || !(isHostObject(value) || isHostObject(other))))) { // unwrap any `lodash` wrapped values var valWrapped = hasOwnProperty.call(value, '__wrapped__'), othWrapped = hasOwnProperty.call(other, '__wrapped__'); @@ -2885,7 +2878,7 @@ */ function initObjectClone(object, isDeep) { var className = toString.call(object); - if (!cloneableClasses[className] || (!support.nodeClass && isNode(object))) { + if (!cloneableClasses[className] || (!support.nodeClass && isHostObject(object))) { return object; } var Ctor = object.constructor, @@ -2943,6 +2936,19 @@ arrayLikeClasses[toString.call(value)]) || false; } + /** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ + var isHostObject = support.hostObject ? constant(false) : function(value) { + // IE < 9 presents many host objects as `Object` objects that can coerce to + // strings despite having improperly defined `toString` methods + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + }; + /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * @@ -3072,7 +3078,7 @@ (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor))) || (!support.argsClass && isArguments(value)) || - (!support.nodeClass && isNode(value))) { + (!support.nodeClass && isHostObject(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first @@ -7112,7 +7118,7 @@ */ function isElement(value) { return (value && typeof value == 'object' && value.nodeType === 1 && - (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value))) || false; + (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isHostObject(value))) || false; } // fallback for environments without DOM support if (!support.dom) { @@ -7361,12 +7367,11 @@ * @returns {boolean} Returns `true` if `value` is a native function, else `false`. */ function isNative(value) { - var type = typeof value; - if (type == 'function') { + if (isFunction(value)) { return reNative.test(fnToString.call(value)); } - if (value && type == 'object') { - return !('constructor' in value && 'toString' in value) + if (value && typeof value == 'object') { + return !('constructor' in value) && isHostObject(value) ? reNative.test(value) : reHostCtor.test(toString.call(value)); } diff --git a/test/test.js b/test/test.js index f2f6f0f428..0856f291a1 100644 --- a/test/test.js +++ b/test/test.js @@ -9923,6 +9923,7 @@ 'fastBind', 'funcDecomp', 'funcNames', + 'hostObject', 'nodeClass', 'nonEnumArgs', 'nonEnumShadows', From e696331e2a08e1726ba7857e0da8b066ba1f330d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 20 Aug 2014 22:35:55 -0700 Subject: [PATCH 1040/1608] Tweak property order note in method docs. [ci skip] --- lodash.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lodash.js b/lodash.js index 3a84a8ec9d..58d8e69456 100644 --- a/lodash.js +++ b/lodash.js @@ -4927,7 +4927,7 @@ * // => logs each value and returns the array * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); - * // => logs each value-key pair and returns the object (property order is not guaranteed across environments) + * // => logs each value-key pair and returns the object (property order is not guaranteed) */ function forEach(collection, iteratee, thisArg) { return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) @@ -5098,7 +5098,7 @@ * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) + * // => [3, 6, 9] (property order is not guaranteed) * * var characters = [ * { 'name': 'barney', 'age': 36 }, @@ -5379,7 +5379,7 @@ * result[key] = n * 3; * return result; * }, {}); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * // => { 'a': 3, 'b': 6, 'c': 9 } (property order is not guaranteed) */ function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; @@ -6747,7 +6747,7 @@ * _.findKey(characters, function(chr) { * return chr.age < 40; * }); - * // => 'barney' (property order is not guaranteed across environments) + * // => 'barney' (property order is not guaranteed) * * // using "_.where" callback shorthand * _.findKey(characters, { 'age': 1 }); @@ -6833,7 +6833,7 @@ * _.forIn(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments) + * // => logs 'x', 'y', and 'z' (property order is not guaranteed) */ function forIn(object, iteratee, thisArg) { if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { @@ -6890,7 +6890,7 @@ * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) + * // => logs '0', '1', and 'length' (property order is not guaranteed) */ function forOwn(object, iteratee, thisArg) { if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { @@ -7548,7 +7548,7 @@ * Shape.prototype.z = 0; * * _.keys(new Shape); - * // => ['x', 'y'] (property order is not guaranteed across environments) + * // => ['x', 'y'] (property order is not guaranteed) */ var keys = !nativeKeys ? shimKeys : function(object) { object = toObject(object); @@ -7582,7 +7582,7 @@ * Shape.prototype.z = 0; * * _.keysIn(new Shape); - * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) + * // => ['x', 'y', 'z'] (property order is not guaranteed) */ function keysIn(object) { if (object == null) { @@ -7791,7 +7791,7 @@ * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed) */ function pairs(object) { var index = -1, @@ -7915,7 +7915,7 @@ * Shape.prototype.z = 0; * * _.values(new Shape(2, 1)); - * // => [2, 1] (property order is not guaranteed across environments) + * // => [2, 1] (property order is not guaranteed) */ function values(object) { return baseValues(object, keys); @@ -7940,7 +7940,7 @@ * Shape.prototype.z = 0; * * _.valuesIn(new Shape(2, 1)); - * // => [2, 1, 0] (property order is not guaranteed across environments) + * // => [2, 1, 0] (property order is not guaranteed) */ function valuesIn(object) { return baseValues(object, keysIn); From 309a2ad0a3dfb2218d32588e917b391576b3f668 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 20 Aug 2014 23:11:04 -0700 Subject: [PATCH 1041/1608] Rebuild dist. --- dist/lodash.compat.js | 1676 ++++++++++++++++++--------------- dist/lodash.compat.min.js | 141 +-- dist/lodash.js | 1643 +++++++++++++++++--------------- dist/lodash.min.js | 133 +-- dist/lodash.underscore.js | 918 +++++++++--------- dist/lodash.underscore.min.js | 81 +- 6 files changed, 2473 insertions(+), 2119 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index c020f04d19..73d98faad3 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -24,6 +24,10 @@ PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64; + /** Used to detect when a function becomes hot */ + var HOT_COUNT = 150, + HOT_SPAN = 16; + /** Used as the property name for wrapper metadata */ var EXPANDO = '__lodash_' + VERSION.replace(/[-.]/g, '_') + '__'; @@ -122,7 +126,8 @@ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'window', 'WinRTError' + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ @@ -208,7 +213,7 @@ /** * Used to convert characters to HTML entities. * - * Note: Though the ">" character is escaped for symmetry, characters like + * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) @@ -351,16 +356,37 @@ */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; + length = array ? array.length : 0, + isReflexive = value === value; while (++index < length) { - if (array[index] === value) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { return index; } } return -1; } + /** + * The base implementation of `_.slice` without support for `start` and `end` + * arguments. + * + * @private + * @param {Array} array The array to slice. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = array[index]; + } + return result; + } + /** * An implementation of `_.contains` for cache objects that mimics the return * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. @@ -399,7 +425,7 @@ var index = -1, length = string.length; - while (++index < length && chars.indexOf(string.charAt(index)) > -1) { } + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} return index; } @@ -415,7 +441,7 @@ function charsRightIndex(string, chars) { var index = string.length; - while (index-- && chars.indexOf(string.charAt(index)) > -1) { } + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} return index; } @@ -519,19 +545,6 @@ return '\\' + stringEscapes[chr]; } - /** - * Checks if `value` is a DOM node in IE < 9. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM node, else `false`. - */ - function isNode(value) { - // IE < 9 presents DOM nodes as `Object` objects except they have `toString` - // methods that are `typeof` "string" and still can coerce nodes to strings - return typeof value.toString != 'function' && typeof (value + '') == 'string'; - } - /** * Used by `_.trimmedLeftIndex` and `_.trimmedRightIndex` to determine if a * character code is whitespace. @@ -557,7 +570,7 @@ var index = -1, length = string.length; - while (++index < length && isWhitespace(string.charCodeAt(index))) { } + while (++index < length && isWhitespace(string.charCodeAt(index))) {} return index; } @@ -572,7 +585,7 @@ function trimmedRightIndex(string) { var index = string.length; - while (index-- && isWhitespace(string.charCodeAt(index))) { } + while (index-- && isWhitespace(string.charCodeAt(index))) {} return index; } @@ -647,6 +660,9 @@ /** 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 restore the original `_` reference in `_.noConflict` */ var oldDash = context._; @@ -666,13 +682,13 @@ clearTimeout = context.clearTimeout, floor = Math.floor, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, - hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, - Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array; + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, + WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers */ var Float64Array = (function() { @@ -682,7 +698,7 @@ try { var func = isNative(func = context.Float64Array) && func, result = new func(new ArrayBuffer(10), 0, 1) && func; - } catch(e) { } + } catch(e) {} return result; }()); @@ -693,13 +709,12 @@ var o = {}, func = isNative(func = Object.defineProperty) && func, result = func(o, o, o) && func; - } catch(e) { } + } catch(e) {} return result; }()); /* Native method references for those with the same name as other `lodash` methods */ - var nativeContains = isNative(nativeContains = stringProto.contains) && nativeContains, - nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, + var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = context.isFinite, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, @@ -713,6 +728,9 @@ /** Used as the size, in bytes, of each Float64Array element */ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; + /** Used to store function metadata */ + var metaMap = WeakMap && new WeakMap; + /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; ctorByClass[float32Class] = context.Float32Array; @@ -772,17 +790,17 @@ * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, - * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, - * `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, - * `isString`, `isUndefined`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, - * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, - * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, - * `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, - * `unescape`, `uniqueId`, and `value` + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, + * `lastIndexOf`, `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, + * `padRight`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, + * `result`, `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, + * `sortedLastIndex`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `unescape`, `uniqueId`, and `value` * * The wrapper function `sample` will return a wrapped value when `n` is * provided, otherwise it will return an unwrapped value. @@ -852,8 +870,6 @@ Ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new Ctor) { props.push(key); } - for (var argsKey in arguments) { } - for (var strKey in 'x') { } /** * Detect if the `[[Class]]` of `arguments` objects is resolvable @@ -912,7 +928,7 @@ * @memberOf _.support * @type boolean */ - support.nonEnumStrings = strKey != '0'; + support.nonEnumStrings = !propertyIsEnumerable.call('x', 0); /** * Detect if properties shadowing those on `Object.prototype` are @@ -975,19 +991,25 @@ } /** - * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9) - * and that the JS engine errors when attempting to coerce an object to a - * string without a `toString` function. + * Detect if the host objects are detectable (IE < 9). * * @memberOf _.support * @type boolean */ try { - support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + '')); + support.hostObject = !({ 'toString': 0 } + ''); } catch(e) { - support.nodeClass = true; + support.hostObject = false; } + /** + * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). + * + * @memberOf _.support + * @type boolean + */ + support.nodeClass = !(toString.call(document) == objectClass && support.hostObject); + /** * Detect if `arguments` object indexes are non-enumerable. * @@ -1001,7 +1023,7 @@ * @type boolean */ try { - support.nonEnumArgs = !(hasOwnProperty.call(arguments, 1) && propertyIsEnumerable.call(arguments, 1)); + support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); } catch(e) { support.nonEnumArgs = true; } @@ -1076,15 +1098,15 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEach(array, iterator) { + function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { - if (iterator(array[index], index, array) === false) { + if (iteratee(array[index], index, array) === false) { break; } } @@ -1097,14 +1119,14 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEachRight(array, iterator) { + function arrayEachRight(array, iteratee) { var length = array.length; while (length--) { - if (iterator(array[length], length, array) === false) { + if (iteratee(array[length], length, array) === false) { break; } } @@ -1139,16 +1161,16 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function arrayMap(array, iterator) { + function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { - result[index] = iterator(array[index], index, array); + result[index] = iteratee(array[index], index, array); } return result; } @@ -1165,12 +1187,13 @@ function arrayFilter(array, predicate) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { - result.push(value); + result[++resIndex] = value; } } return result; @@ -1182,13 +1205,13 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduce(array, iterator, accumulator, initFromArray) { + function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; @@ -1196,7 +1219,7 @@ accumulator = array[++index]; } while (++index < length) { - accumulator = iterator(accumulator, array[index], index, array); + accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } @@ -1207,20 +1230,20 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduceRight(array, iterator, accumulator, initFromArray) { + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { var length = array.length; if (initFromArray && length) { accumulator = array[--length]; } while (length--) { - accumulator = iterator(accumulator, array[length], length, array); + accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } @@ -1264,7 +1287,7 @@ /** * Used by `_.template` to customize its `_.assign` use. * - * Note: This method is like `assignDefaults` except that it ignores + * **Note:** This method is like `assignDefaults` except that it ignores * inherited property values when checking if a property is `undefined`. * * @private @@ -1319,7 +1342,7 @@ while (++index < length) { var key = methodNames[index]; - object[key] = createWrapper([object[key], BIND_FLAG, null, object]); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -1341,7 +1364,7 @@ if (typeof thisArg == 'undefined') { return func; } - var data = func[EXPANDO]; + var data = getData(func); if (typeof data == 'undefined') { if (support.funcNames) { data = !func.name; @@ -1355,7 +1378,7 @@ if (!data) { // checks if `func` references the `this` keyword and stores the result data = reThis.test(source) || isNative(func); - setData(func, data); + baseSetData(func, data); } } } @@ -1405,79 +1428,15 @@ if (typeof result != 'undefined') { return result; } - var isArr = isArray(value), - isShallow = !isDeep; - + var isArr = isArray(value); + result = value; if (isArr) { - result = isShallow ? slice(value) : value.constructor(value.length); - - // add array properties assigned by `RegExp#exec` - if (typeof value[0] == 'string' && hasOwnProperty.call(value, 'index')) { - result.index = value.index; - result.input = value.input; - } - if (isShallow) { - return result; - } + result = initArrayClone(value, isDeep); + } else if (isObject(value)) { + result = initObjectClone(value, isDeep); + value = (isDeep && toString.call(result) == objectClass) ? value : result; } - else { - if (!isObject(value)) { - return value; - } - var className = toString.call(value); - if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) { - return value; - } - var isArgs = className == argsClass || (!support.argsClass && isArguments(value)), - isObj = !isArgs && className == objectClass; - - if (isShallow && (isArgs || isObj)) { - result = baseAssign({}, value); - if (isObj) { - return result; - } - } - var Ctor = value.constructor; - if (className == objectClass && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { - Ctor = Object; - } - if (isDeep && (isArgs || isObj)) { - result = new Ctor; - } - else { - switch (className) { - case arrayBufferClass: - return cloneBuffer(value); - - case boolClass: - case dateClass: - return new Ctor(+value); - - case float32Class: case float64Class: - case int8Class: case int16Class: case int32Class: - case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - // Safari 5 mobile incorrectly has `Object` as the constructor - if (Ctor instanceof Ctor) { - Ctor = ctorByClass[className]; - } - var buffer = value.buffer; - return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, value.byteOffset, value.length); - - case numberClass: - case stringClass: - return new Ctor(value); - - case regexpClass: - result = Ctor(value.source, reFlags.exec(value)); - result.lastIndex = value.lastIndex; - return result; - } - } - } - if (isArgs) { - result.length = value.length; - } - if (isShallow) { + if (!isDeep || result === value) { return result; } // check for circular references and return corresponding clone @@ -1532,85 +1491,6 @@ }()); } - /** - * The base implementation of `createWrapper` which creates the wrapper and - * sets its metadata. - * - * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(data) { - var bitmask = data[1]; - if (bitmask == BIND_FLAG) { - return setData(createBindWrapper(data), data); - } - var partialHolders = data[5]; - if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { - return setData(createPartialWrapper(data), data); - } - var func = data[0], - arity = data[2], - thisArg = data[3], - partialArgs = data[4], - partialRightArgs = data[6], - partialRightHolders = data[7]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryRight = bitmask & CURRY_RIGHT_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG; - - var Ctor = !isBindKey && createCtorWrapper(func), - key = func; - - var wrapper = function() { - var length = arguments.length, - index = length, - args = Array(length); - - while (index--) { - args[index] = arguments[index]; - } - if (partialArgs) { - args = composeArgs(partialArgs, partialHolders, args); - } - if (partialRightArgs) { - args = composeArgsRight(partialRightArgs, partialRightHolders, args); - } - if (isCurry || isCurryRight) { - var placeholder = wrapper.placeholder, - newPartialHolders = replaceHolders(args, placeholder); - - length -= newPartialHolders.length; - - if (length < arity) { - bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); - bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); - - if (!isCurryBound) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); - } - var newData = [func, bitmask, nativeMax(arity - length, 0), thisArg, null, null]; - newData[isCurry ? 4 : 6] = args; - newData[isCurry ? 5 : 7] = newPartialHolders; - - var result = baseCreateWrapper(newData); - result.placeholder = placeholder; - return result; - } - } - var thisBinding = isBind ? thisArg : this; - if (isBindKey) { - func = thisBinding[key]; - } - return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); - }; - - return setData(wrapper, data); - } - /** * The base implementation of `_.curry` and `_.curryRight` which handles * resolving the default arity of `func`. @@ -1623,9 +1503,9 @@ */ function baseCurry(func, bitmask, arity) { if (typeof arity != 'number') { - arity = +arity || (func ? func.length : 0); + arity = arity == null ? (func ? func.length : 0) : nativeMax(+arity || 0, 0); } - return createWrapper([func, bitmask, arity]); + return createWrapper(func, bitmask, arity); } /** @@ -1658,7 +1538,7 @@ while (++index < length) { var value = array[index]; - if (isCommon) { + if (isCommon && value === value) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { @@ -1680,19 +1560,19 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEach(collection, iterator) { + function baseEach(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwn(collection, iterator); + return baseForOwn(collection, iteratee); } var index = -1, iterable = toIterable(collection); while (++index < length) { - if (iterator(iterable[index], index, iterable) === false) { + if (iteratee(iterable[index], index, iterable) === false) { break; } } @@ -1705,17 +1585,17 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEachRight(collection, iterator) { + function baseEachRight(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwnRight(collection, iterator); + return baseForOwnRight(collection, iteratee); } var iterable = toIterable(collection); while (length--) { - if (iterator(iterable[length], length, iterable) === false) { + if (iteratee(iterable[length], length, iterable) === false) { break; } } @@ -1829,24 +1709,24 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iterator` for + * over `object` properties returned by `keysFunc` executing `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseFor(object, iterator, keysFunc) { + function baseFor(object, iteratee, keysFunc) { var index = -1, props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; - if (iterator(object[key], key, object) === false) { + if (iteratee(object[key], key, object) === false) { break; } } @@ -1859,17 +1739,17 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForRight(object, iterator, keysFunc) { + function baseForRight(object, iteratee, keysFunc) { var props = keysFunc(object), length = props.length; while (length--) { var key = props[length]; - if (iterator(object[key], key, object) === false) { + if (iteratee(object[key], key, object) === false) { break; } } @@ -1882,11 +1762,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForIn(object, iterator) { - return baseFor(object, iterator, keysIn); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); } /** @@ -1895,11 +1775,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwn(object, iterator) { - return baseFor(object, iterator, keys); + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); } /** @@ -1908,32 +1788,32 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwnRight(object, iterator) { - return baseForRight(object, iterator, keys); + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); } /** - * The base implementation of `_.functions` which creates an array of function - * property names from those returned by `keysFunc`. + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. * * @private * @param {Object} object The object to inspect. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Array} Returns the new sorted array of property names. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. */ - function baseFunctions(object, keysFunc) { + function baseFunctions(object, props) { var index = -1, - props = keysFunc(object), length = props.length, + resIndex = -1, result = []; while (++index < length) { var key = props[index]; if (isFunction(object[key])) { - result.push(key); + result[++resIndex] = key; } } return result; @@ -1995,7 +1875,7 @@ return false; } } - else if (isErr || (valClass == objectClass && (support.nodeClass || !(isNode(value) || isNode(other))))) { + else if (isErr || (valClass == objectClass && (support.nodeClass || !(isHostObject(value) || isHostObject(other))))) { // unwrap any `lodash` wrapped values var valWrapped = hasOwnProperty.call(value, '__wrapped__'), othWrapped = hasOwnProperty.call(other, '__wrapped__'); @@ -2061,7 +1941,7 @@ return (value != +value) ? other != +other // but treat `-0` vs. `+0` as not equal - : (value == 0 ? (1 / value == 1 / other) : value == +other); + : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); case regexpClass: case stringClass: @@ -2164,14 +2044,14 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function baseMap(collection, iterator) { + function baseMap(collection, iteratee) { var result = []; baseEach(collection, function(value, key, collection) { - result.push(iterator(value, key, collection)); + result.push(iteratee(value, key, collection)); }); return result; } @@ -2254,51 +2134,14 @@ */ function basePartial(func, bitmask, args, holders, thisArg) { if (func) { - var data = func[EXPANDO], + var data = getData(func), arity = data ? data[2] : func.length; arity -= args.length; } - var isPartial = bitmask & PARTIAL_FLAG, - newData = [func, bitmask, arity, thisArg, null, null]; - - newData[isPartial ? 4 : 6] = args; - newData[isPartial ? 5 : 7] = holders; - return createWrapper(newData); - } - - /** - * The base implementation of `_.pick` without support for `this` binding - * and individual property name arguments. - * - * @private - * @param {Object} object The source object. - * @param {Function|string[]} predicate The function called per iteration or - * property names to pick. - * @returns {Object} Returns the new object. - */ - function basePick(object, predicate) { - var result = {}; - - if (typeof predicate == 'function') { - baseForIn(object, function(value, key, object) { - if (predicate(value, key, object)) { - result[key] = value; - } - }); - return result; - } - var index = -1, - props = predicate, - length = props.length; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - return result; + return (bitmask & PARTIAL_FLAG) + ? createWrapper(func, bitmask, arity, thisArg, args, holders) + : createWrapper(func, bitmask, arity, thisArg, null, null, args, holders); } /** @@ -2345,22 +2188,44 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ - function baseReduce(collection, iterator, accumulator, initFromCollection, eachFunc) { + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) - : iterator(accumulator, value, index, collection) + : iteratee(accumulator, value, index, collection) }); return accumulator; } + /** + * The base implementation of `setData` without support for hot loop detection. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + function baseSetData(func, data) { + metaMap.set(func, data); + return func; + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + baseSetData = !defineProperty ? identity : function(func, value) { + descriptor.value = value; + defineProperty(func, EXPANDO, descriptor); + descriptor.value = null; + return func; + }; + } + /** * The base implementation of `_.some` without support for callback shorthands * or `this` binding. @@ -2388,24 +2253,24 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ - function baseSortedIndex(array, value, iterator, retHighest) { + function baseSortedIndex(array, value, iteratee, retHighest) { var low = 0, high = array ? array.length : low; - value = iterator(value); + value = iteratee(value); var hintNum = typeof value == 'number' || (value != null && isFunction(value.valueOf) && typeof value.valueOf() == 'number'); while (low < high) { var mid = (low + high) >>> 1, - computed = iterator(array[mid]), - setLow = retHighest ? computed <= value : computed < value; + computed = iteratee(array[mid]), + setLow = retHighest ? (computed <= value) : (computed < value); if (hintNum && typeof computed != 'undefined') { computed = +computed; @@ -2426,10 +2291,10 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function baseUniq(array, iterator) { + function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), length = array.length, @@ -2442,27 +2307,27 @@ var seen = createCache(); indexOf = cacheIndexOf; } else { - seen = iterator ? [] : result; + seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; - if (isCommon) { + if (isCommon && value === value) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } - if (iterator) { + if (iteratee) { seen.push(computed); } result.push(value); } else if (indexOf(seen, computed) < 0) { - if (iterator || isLarge) { + if (iteratee || isLarge) { seen.push(computed); } result.push(value); @@ -2493,6 +2358,36 @@ return result; } + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function bufferClone(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` + bufferClone = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, + offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; + } + /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. @@ -2558,7 +2453,7 @@ /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection - * through `iterator`. The given setter function sets the keys and values of + * through `iteratee`. The given setter function sets the keys and values of * the accumulator object. If `initializer` is provided it is used to initialize * the accumulator object. * @@ -2568,9 +2463,9 @@ * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { - return function(collection, iterator, thisArg) { + return function(collection, iteratee, thisArg) { var result = initializer ? initializer() : {}; - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, @@ -2578,11 +2473,11 @@ while (++index < length) { var value = collection[index]; - setter(result, value, iterator(value, index, collection), collection); + setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { - setter(result, value, iterator(value, key, collection), collection); + setter(result, value, iteratee(value, key, collection), collection); }); } return result; @@ -2598,44 +2493,43 @@ * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { - return function(object) { - var args = arguments, - length = args.length; + return function() { + var length = arguments.length, + object = arguments[0]; if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` - var type = typeof args[2]; - if ((type == 'number' || type == 'string') && args[3] && args[3][args[2]] === args[1]) { + var type = typeof arguments[2]; + if ((type == 'number' || type == 'string') && arguments[3] && arguments[3][arguments[2]] === arguments[1]) { length = 2; } // juggle arguments - if (length > 3 && typeof args[length - 2] == 'function') { - var customizer = baseCallback(args[--length - 1], args[length--], 5); - } else if (length > 2 && typeof args[length - 1] == 'function') { - customizer = args[--length]; + if (length > 3 && typeof arguments[length - 2] == 'function') { + var customizer = baseCallback(arguments[--length - 1], arguments[length--], 5); + } else if (length > 2 && typeof arguments[length - 1] == 'function') { + customizer = arguments[--length]; } var index = 0; while (++index < length) { - assigner(object, args[index], customizer); + assigner(object, arguments[index], customizer); } return object; }; } /** - * Creates a function that invokes the function specified in the metadata - * with its associated `this` binding. + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new bound function. + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. */ - function createBindWrapper(data) { - var func = data[0], - thisArg = data[3], - Ctor = createCtorWrapper(func); + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); function wrapper() { return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); @@ -2680,6 +2574,77 @@ }; } + /** + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. + * @returns {Function} Returns the new function. + */ + function createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG; + + var Ctor = !isBindKey && createCtorWrapper(func), + key = func; + + function wrapper() { + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partialArgs) { + args = composeArgs(partialArgs, partialHolders, args); + } + if (partialRightArgs) { + args = composeArgsRight(partialRightArgs, partialRightHolders, args); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, + holders = replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + var newArity = nativeMax(arity - length, 0), + newPartialArgs = isCurry ? args : null, + newPartialHolders = isCurry ? holders : null, + newPartialRightArgs = isCurry ? null : args, + newPartialRightHolders = isCurry ? null : holders; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var result = createHybridWrapper(func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders); + result.placeholder = placeholder; + return setData(result, [func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders]); + } + } + var thisBinding = isBind ? thisArg : this; + if (isBindKey) { + func = thisBinding[key]; + } + return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); + } + return wrapper; + } + /** * Creates the pad required for `string` based on the given padding length. * The `chars` string may be truncated if the number of padding characters @@ -2704,25 +2669,25 @@ } /** - * Creates a function that invokes the function specified in the metadata - * with its associated partially applied arguments and optional `this` binding. + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partialArgs` prepended to those provided to + * the wrapper. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {Array} partialArgs An array of arguments to prepend to those provided to the new function. + * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new bound function. */ - function createPartialWrapper(data) { - var func = data[0], - thisArg = data[3], - partialArgs = data[4]; - - var isBind = data[1] & BIND_FLAG, + function createPartialWrapper(func, bitmask, partialArgs, thisArg) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` - var argsIndex = 0, + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partialArgs.length, @@ -2732,7 +2697,7 @@ args[leftIndex] = partialArgs[leftIndex]; } while (argsLength--) { - args[leftIndex++] = arguments[argsIndex++]; + args[leftIndex++] = arguments[++argsIndex]; } return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); } @@ -2744,9 +2709,8 @@ * `this` binding and partially applied arguments. * * @private - * @param {Array} data The metadata array. - * @param {Function|string} data[0] The function or method name to reference. - * @param {number} data[1] The bitmask of flags to compose. + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` @@ -2755,97 +2719,80 @@ * 16 - `_.curry` or `_.curryRight` of a bound function * 32 - `_.partial` * 64 - `_.partialRight` - * @param {number} data[2] The arity of `data[0]`. - * @param {*} [data[3]] The `this` binding of `data[0]`. - * @param {Array} [data[4]] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [data[5]] An array of `data[4]` placeholder indexes. - * @param {Array} [data[6]] An array of arguments to append to those - * provided to the new function. - * @param {Array} [data[7]] An array of `data[6]` placeholder indexes. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ - function createWrapper(data) { - var func = data[0], - bitmask = data[1]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isPartial = bitmask & PARTIAL_FLAG, - isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; - + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && !isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } - var arity = data[2], - partialArgs = data[4], - partialRightArgs = data[6]; - + var isPartial = bitmask & PARTIAL_FLAG; if (isPartial && !partialArgs.length) { + bitmask &= ~PARTIAL_FLAG; isPartial = false; - data[1] = (bitmask &= ~PARTIAL_FLAG); - data[4] = data[5] = partialArgs = null; + partialArgs = partialHolders = null; } + var isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (isPartialRight && !partialRightArgs.length) { + bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = false; - data[1] = (bitmask &= ~PARTIAL_RIGHT_FLAG); - data[6] = data[7] = partialRightArgs = null; - } - var funcData = !isBindKey && func[EXPANDO]; - if (funcData && funcData !== true) { - // shallow clone `funcData` - funcData = slice(funcData); - - // clone partial left arguments - if (funcData[4]) { - funcData[4] = slice(funcData[4]); - funcData[5] = slice(funcData[5]); - } - // clone partial right arguments - if (funcData[6]) { - funcData[6] = slice(funcData[6]); - funcData[7] = slice(funcData[7]); - } - // set arity if provided - if (typeof arity == 'number') { - funcData[2] = arity; + partialRightArgs = partialRightHolders = null; + } + var data = (data = !isBindKey && getData(func)) && data !== true && data; + if (data) { + var funcBitmask = data[1], + funcIsBind = funcBitmask & BIND_FLAG, + isBind = bitmask & BIND_FLAG; + + // use metadata `func` and merge bitmasks + func = data[0]; + bitmask |= funcBitmask; + + // use metadata `arity` if not provided + if (arity == null) { + arity = data[2]; } - // set `thisArg` if not previously bound - var bound = funcData[1] & BIND_FLAG; - if (isBind && !bound) { - funcData[3] = data[3]; + // use metadata `thisArg` if available + if (funcIsBind) { + thisArg = data[3]; } // set if currying a bound function - if (!isBind && bound) { + if (!isBind && funcIsBind) { bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments - if (isPartial) { - var funcPartialArgs = funcData[4]; - if (funcPartialArgs) { - funcPartialArgs = composeArgs(funcPartialArgs, funcData[5], partialArgs); - } - funcData[4] = funcPartialArgs || partialArgs; - funcData[5] = funcPartialArgs ? replaceHolders(funcPartialArgs, PLACEHOLDER) : data[5]; + var funcArgs = data[4]; + if (funcArgs) { + var funcHolders = data[5]; + partialArgs = isPartial ? composeArgs(funcArgs, funcHolders, partialArgs) : baseSlice(funcArgs); + partialHolders = isPartial ? replaceHolders(partialArgs, PLACEHOLDER) : baseSlice(funcHolders); } // prepend partial right arguments - if (isPartialRight) { - var funcPartialRightArgs = funcData[6]; - if (funcPartialRightArgs) { - funcPartialRightArgs = composeArgsRight(funcPartialRightArgs, funcData[7], partialRightArgs); - } - funcData[6] = funcPartialRightArgs || partialRightArgs; - funcData[7] = funcPartialRightArgs ? replaceHolders(funcPartialRightArgs, PLACEHOLDER) : data[7]; + funcArgs = data[6]; + if (funcArgs) { + funcHolders = data[7]; + partialRightArgs = isPartialRight ? composeArgsRight(funcArgs, funcHolders, partialRightArgs) : baseSlice(funcArgs); + partialRightHolders = isPartialRight ? replaceHolders(partialRightArgs, PLACEHOLDER) : baseSlice(funcHolders); } - // merge flags - funcData[1] |= bitmask; - return createWrapper(funcData); } if (arity == null) { arity = isBindKey ? 0 : func.length; } - data[2] = nativeMax(arity, 0); - return baseCreateWrapper(data); + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(func, thisArg); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { + result = createPartialWrapper(func, bitmask, partialArgs, thisArg); + } else { + result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); + } + var setter = data ? baseSetData : setData; + return setter(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); } /** @@ -2860,7 +2807,24 @@ function getCallback(func, thisArg, argCount) { var result = lodash.callback || callback; result = result === callback ? baseCallback : result; - return arguments.length ? result(func, thisArg, argCount) : result; + return argCount ? result(func, thisArg, argCount) : result; + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + function getData(func) { + return metaMap.get(func); + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + getData = !defineProperty ? noop : function(func) { + return func[EXPANDO]; + }; } /** @@ -2878,6 +2842,88 @@ return collection ? result(collection, target, fromIndex) : result; } + /** + * Initializes an array clone. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @returns {*} Returns the initialized clone value. + */ + function initArrayClone(array, isDeep) { + var index = -1, + length = array.length, + result = array.constructor(length); + + if (!isDeep) { + while (++index < length) { + result[index] = array[index]; + } + } + // add array properties assigned by `RegExp#exec` + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @returns {*} Returns the initialized clone value. + */ + function initObjectClone(object, isDeep) { + var className = toString.call(object); + if (!cloneableClasses[className] || (!support.nodeClass && isHostObject(object))) { + return object; + } + var Ctor = object.constructor, + isArgs = className == argsClass || (!support.argsClass && isArguments(object)), + isObj = className == objectClass; + + if (isObj && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { + Ctor = Object; + } + if (isArgs || isObj) { + var result = isDeep ? new Ctor : baseAssign(new Ctor, object); + if (isArgs) { + result.length = object.length; + } + return result; + } + switch (className) { + case arrayBufferClass: + return bufferClone(object); + + case boolClass: + case dateClass: + return new Ctor(+object); + + case float32Class: case float64Class: + case int8Class: case int16Class: case int32Class: + case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: + // Safari 5 mobile incorrectly has `Object` as the constructor + if (Ctor instanceof Ctor) { + Ctor = ctorByClass[className]; + } + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberClass: + case stringClass: + return new Ctor(object); + + case regexpClass: + result = Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + /** * Checks if `value` is an array-like object. * @@ -2891,18 +2937,17 @@ } /** - * Checks if `value` is a native function. + * Checks if `value` is a host object in IE < 9. * * @private * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ - function isNative(value) { - var type = typeof value; - return type == 'function' - ? reNative.test(fnToString.call(value)) - : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; - } + var isHostObject = support.hostObject ? constant(false) : function(value) { + // IE < 9 presents many host objects as `Object` objects that can coerce to + // strings despite having improperly defined `toString` methods + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + }; /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. @@ -2913,37 +2958,50 @@ * equality comparisons, else `false`. */ function isStrictComparable(value) { - return value === value && (value === 0 ? (1 / value > 0) : !isObject(value)); + return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value)); } /** - * Creates a clone of the given array buffer. + * A specialized version of `_.pick` that picks `object` properties + * specified by the `props` array. * * @private - * @param {ArrayBuffer} buffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. */ - function cloneBuffer(buffer) { - return bufferSlice.call(buffer, 0); - } - if (!bufferSlice) { - // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` - cloneBuffer = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + function pickByArray(object, props) { + var index = -1, + length = props.length, + result = {}; - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); + } + return result; + } + + /** + * A specialized version of `_.pick` that picks `object` properties + * the predicate returns truthy for. + * + * @private + * @param {Object} object The source object. + * @param {Function} predicate The function called per iteration. + * @returns {Object} Returns the new object. + */ + function pickByCallback(object, predicate) { + var result = {}; + + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; } - return result; - }; + }); + return result; } /** @@ -2958,31 +3016,49 @@ function replaceHolders(array, placeholder) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; - result.push(index); + result[++resIndex] = index; } } return result; } /** - * Sets wrapper metadata on a given function. + * Sets metadata for `func`. + * + * **Note**: If this function becomes hot, i.e. is called a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses. * * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = !defineProperty ? identity : function(func, value) { - descriptor.value = value; - defineProperty(func, EXPANDO, descriptor); - descriptor.value = null; - return func; - }; + var setData = (function() { + var count = 0, + lastCalled = 0; + + return function(key, value) { + var stamp = now ? now() : 0, + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count > HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }()); /** * A fallback implementation of `_.isPlainObject` which checks if `value` @@ -3002,7 +3078,7 @@ (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor))) || (!support.argsClass && isArguments(value)) || - (!support.nodeClass && isNode(value))) { + (!support.nodeClass && isHostObject(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first @@ -3061,22 +3137,23 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function sortedUniq(array, iterator) { + function sortedUniq(array, iteratee) { var seen, index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; if (!index || seen !== computed) { seen = computed; - result.push(value); + result[++resIndex] = value; } } return result; @@ -3121,7 +3198,7 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array of elements split into groups the length of `chunkSize`. + * Creates an array of elements split into groups the length of `size`. * If `collection` can't be split evenly, the final chunk will be the remaining * elements. * @@ -3129,7 +3206,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to process. - * @param {numer} [chunkSize=1] The size of each chunk. + * @param {numer} [size=1] The length of each chunk. * @returns {Array} Returns the new array containing chunks. * @example * @@ -3139,14 +3216,15 @@ * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ - function chunk(array, chunkSize) { + function chunk(array, size) { var index = 0, length = array ? array.length : 0, + resIndex = -1, result = []; - chunkSize = nativeMax(+chunkSize || 1, 1); + size = typeof size == 'undefined' ? 1 : nativeMax(+size || 1, 1); while (index < length) { - result.push(slice(array, index, (index += chunkSize))); + result[++resIndex] = slice(array, index, (index += size)); } return result; } @@ -3181,8 +3259,12 @@ } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates an array excluding all values of the provided arrays using + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3315,7 +3397,7 @@ index = length; predicate = getCallback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { } + while (index-- && predicate(array[index], index, array)) {} return slice(array, 0, index + 1); } @@ -3364,7 +3446,7 @@ length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { } + while (++index < length && predicate(array[index], index, array)) {} return slice(array, index); } @@ -3549,10 +3631,14 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, + * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, * it is used as the offset from the end of the collection. If `array` is * sorted providing `true` for `fromIndex` performs a faster binary search. * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @category Array @@ -3606,7 +3692,11 @@ /** * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3714,8 +3804,10 @@ index = sortedLastIndex(array, value) - 1; return (length && array[index] === value) ? index : -1; } + var isReflexive = value === value; while (index--) { - if (array[index] === value) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { return index; } } @@ -3723,10 +3815,14 @@ } /** - * Removes all provided values from `array` using strict equality for - * comparisons, i.e. `===`. + * Removes all provided values from `array` using `SameValueZero` for equality + * comparisons. * - * Note: Unlike `_.without`, this method mutates `array`. + * **Note:** Unlike `_.without`, this method mutates `array`. + * + * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches + * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3741,20 +3837,18 @@ * console.log(array); * // => [1, 1] */ - function pull(array) { - var argsIndex = 0, - argsLength = arguments.length, - length = array ? array.length : 0; + function pull() { + var array = arguments[0], + index = 0, + indexOf = getIndexOf(), + length = arguments.length; - while (++argsIndex < argsLength) { - var index = -1, - value = arguments[argsIndex]; + while (++index < length) { + var fromIndex = 0, + value = arguments[index]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); } } return array; @@ -3765,7 +3859,7 @@ * returns an array of the removed elements. Indexes may be specified as an * array of indexes or as individual arguments. * - * Note: Unlike `_.at`, this method mutates `array`. + * **Note:** Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ @@ -3801,7 +3895,7 @@ * returns `true` for elements that have the properties of the given object, * else `false`. * - * Note: Unlike `_.filter`, this method mutates `array`. + * **Note:** Unlike `_.filter`, this method mutates `array`. * * @static * @memberOf _ @@ -3861,7 +3955,7 @@ /** * Slices `array` from the `start` index up to, but not including, the `end` index. * - * Note: This function is used instead of `Array#slice` to support node lists + * **Note:** This function is used instead of `Array#slice` to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @static @@ -3884,6 +3978,9 @@ if (end < 0) { end += length; } + if (end && end == length && !start) { + return baseSlice(array); + } length = start > end ? 0 : (end - start); var result = Array(length); @@ -3896,14 +3993,14 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iterator function is provided it is executed for `value` - * and each element of `array` to compute their sort ranking. The iterator + * of the array. If an iteratee function is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -3912,10 +4009,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -3928,7 +4025,7 @@ * * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * - * // using an iterator function + * // using an iteratee function * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { * return this.data[word]; * }, dict); @@ -3938,9 +4035,9 @@ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ - function sortedIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : getCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator); + function sortedIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee); } /** @@ -3953,10 +4050,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -3964,9 +4061,9 @@ * _.sortedLastIndex([4, 4, 5, 5, 6, 6], 5); * // => 4 */ - function sortedLastIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : getCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator, true); + function sortedLastIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee, true); } /** @@ -4076,7 +4173,7 @@ index = length; predicate = getCallback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { } + while (index-- && predicate(array[index], index, array)) {} return slice(array, index + 1); } @@ -4125,13 +4222,17 @@ length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { } + while (++index < length && predicate(array[index], index, array)) {} return slice(array, 0, index); } /** * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4148,30 +4249,34 @@ } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a - * faster search algorithm for sorted arrays. If an iterator function is - * provided it is executed for each value in the array to generate the criterion - * by which uniqueness is computed. The `iterator` is bound to `thisArg` and - * invoked with three arguments; (value, index, array). + * Creates a duplicate-value-free version of an array using `SameValueZero` + * for equality comparisons. Providing `true` for `isSorted` performs a faster + * search algorithm for sorted arrays. If an iteratee function is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @alias unique * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new duplicate-value-free array. * @example * @@ -4182,7 +4287,7 @@ * _.uniq([1, 1, 2], true); * // => [1, 2] * - * // using an iterator function + * // using an iteratee function * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); * // => [1, 2.5] * @@ -4190,7 +4295,7 @@ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ - function uniq(array, isSorted, iterator, thisArg) { + function uniq(array, isSorted, iteratee, thisArg) { var length = array ? array.length : 0; if (!length) { return []; @@ -4198,21 +4303,21 @@ // juggle arguments var type = typeof isSorted; if (type != 'boolean' && isSorted != null) { - thisArg = iterator; - iterator = isSorted; + thisArg = iteratee; + iteratee = isSorted; isSorted = false; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === array) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === array) { + iteratee = null; } } - if (iterator != null) { - iterator = getCallback(iterator, thisArg, 3); + if (iteratee != null) { + iteratee = getCallback(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) - ? sortedUniq(array, iterator) - : baseUniq(array, iterator); + ? sortedUniq(array, iteratee) + : baseUniq(array, iteratee); } /** @@ -4245,8 +4350,12 @@ } /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * Creates an array excluding all provided values using `SameValueZero` for + * equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4259,8 +4368,8 @@ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ - function without() { - return baseDifference(arguments[0], slice(arguments, 1)); + function without(array) { + return baseDifference(array, slice(arguments, 1)); } /** @@ -4312,7 +4421,13 @@ * // => [['fred', 30, true], ['barney', 40, false]] */ function zip() { - return unzip(arguments); + var length = arguments.length, + array = Array(length); + + while (length--) { + array[length] = arguments[length]; + } + return unzip(array); } /** @@ -4504,9 +4619,13 @@ } /** - * Checks if `value` is present in `collection` using strict equality for - * comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. + * Checks if `value` is present in `collection` using `SameValueZero` for + * equality comparisons. If `fromIndex` is negative, it is used as the offset + * from the end of the collection. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4542,28 +4661,22 @@ } else { fromIndex = 0; } - if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { - if (fromIndex >= length) { - return false; - } - return nativeContains - ? nativeContains.call(collection, target, fromIndex) - : collection.indexOf(target, fromIndex) > -1; - } - return getIndexOf(collection, target, fromIndex) > -1; + return (typeof collection == 'string' || !isArray(collection) && isString(collection)) + ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) + : (getIndexOf(collection, target, fromIndex) > -1); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding value - * of each key is the number of times the key was returned by `iterator`. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the number of times the key was returned by `iteratee`. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4571,10 +4684,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4633,10 +4746,10 @@ * // => false */ function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arrayEvery : baseEvery; return func(collection, predicate); } @@ -4681,9 +4794,9 @@ * // => [{ 'name': 'barney', 'age': 36 }] */ function filter(collection, predicate, thisArg) { - predicate = getCallback(predicate, thisArg, 3); - var func = isArray(collection) ? arrayFilter : baseFilter; + + predicate = getCallback(predicate, thisArg, 3); return func(collection, predicate); } @@ -4791,12 +4904,12 @@ } /** - * Iterates over elements of `collection` executing `iterator` for each - * element. The `iterator` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` executing `iteratee` for each + * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * - * Note: As with other "Collections" methods, objects with a `length` property + * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * @@ -4805,8 +4918,8 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * @@ -4814,12 +4927,12 @@ * // => logs each value and returns the array * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); - * // => logs each value-key pair and returns the object (property order is not guaranteed across environments) + * // => logs each value-key pair and returns the object (property order is not guaranteed) */ - function forEach(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, iterator) - : baseEach(collection, baseCallback(iterator, thisArg, 3)); + function forEach(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, baseCallback(iteratee, thisArg, 3)); } /** @@ -4831,31 +4944,31 @@ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each value from right to left and returns the array */ - function forEachRight(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEachRight(collection, iterator) - : baseEachRight(collection, baseCallback(iterator, thisArg, 3)); + function forEachRight(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEachRight(collection, iteratee) + : baseEachRight(collection, baseCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding + * each element of `collection` through `iteratee`. The corresponding * value of each key is an array of the elements responsible for generating - * the key. The `iterator` is bound to `thisArg` and invoked with three + * the key. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4863,10 +4976,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4890,15 +5003,15 @@ /** * Creates an object composed of keys generated from the results of running - * each element of the collection through `iterator`. The corresponding value + * each element of the collection through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4906,10 +5019,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4959,13 +5072,13 @@ /** * Creates an array of values by running each element in the collection through - * `iterator`. The `iterator` is bound to `thisArg` and invoked with three + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4974,10 +5087,10 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * @@ -4985,7 +5098,7 @@ * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) + * // => [3, 6, 9] (property order is not guaranteed) * * var characters = [ * { 'name': 'barney', 'age': 36 }, @@ -4996,24 +5109,24 @@ * _.map(characters, 'name'); * // => ['barney', 'fred'] */ - function map(collection, iterator, thisArg) { - iterator = getCallback(iterator, thisArg, 3); + function map(collection, iteratee, thisArg) { + iteratee = getCallback(iteratee, thisArg, 3); var func = isArray(collection) ? arrayMap : baseMap; - return func(collection, iterator); + return func(collection, iteratee); } /** * Retrieves the maximum value of `collection`. If the collection is empty - * or falsey `-Infinity` is returned. If an iterator function is provided it + * or falsey `-Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5021,10 +5134,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * @@ -5046,20 +5159,20 @@ * _.max(characters, 'age'); * // => { 'name': 'fred', 'age': 40 }; */ - function max(collection, iterator, thisArg) { + function max(collection, iteratee, thisArg) { var computed = -Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - var noIterator = iterator == null, - isArr = noIterator && isArray(collection), + var noIteratee = iteratee == null, + isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); - if (noIterator && !isStr) { + if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -5071,12 +5184,12 @@ } } } else { - iterator = (noIterator && isStr) + iteratee = (noIteratee && isStr) ? charAtCallback - : getCallback(iterator, thisArg, 3); + : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current > computed || (current === -Infinity && current === result)) { computed = current; result = value; @@ -5088,15 +5201,15 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty - * or falsey `Infinity` is returned. If an iterator function is provided it + * or falsey `Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5104,10 +5217,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * @@ -5129,20 +5242,20 @@ * _.min(characters, 'age'); * // => { 'name': 'barney', 'age': 36 }; */ - function min(collection, iterator, thisArg) { + function min(collection, iteratee, thisArg) { var computed = Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - var noIterator = iterator == null, - isArr = noIterator && isArray(collection), + var noIteratee = iteratee == null, + isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); - if (noIterator && !isStr) { + if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -5154,12 +5267,12 @@ } } } else { - iterator = (noIterator && isStr) + iteratee = (noIteratee && isStr) ? charAtCallback - : getCallback(iterator, thisArg, 3); + : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current < computed || (current === Infinity && current === result)) { computed = current; result = value; @@ -5242,10 +5355,10 @@ /** * Reduces a collection to a value which is the accumulated result of running - * each element in the collection through `iterator`, where each successive + * each element in the collection through `iteratee`, where each successive * execution consumes the return value of the previous execution. If `accumulator` * is not provided the first element of the collection is used as the initial - * value. The `iterator` is bound to `thisArg`and invoked with four arguments; + * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * * @static @@ -5253,9 +5366,9 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -5266,11 +5379,11 @@ * result[key] = n * 3; * return result; * }, {}); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * // => { 'a': 3, 'b': 6, 'c': 9 } (property order is not guaranteed) */ - function reduce(collection, iterator, accumulator, thisArg) { + function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; - return func(collection, getCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEach); + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** @@ -5282,9 +5395,9 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -5292,9 +5405,9 @@ * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ - function reduceRight(collection, iterator, accumulator, thisArg) { + function reduceRight(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduceRight : baseReduce; - return func(collection, getCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** @@ -5336,8 +5449,12 @@ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); - return filter(collection, negate(predicate)); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); } /** @@ -5471,27 +5588,27 @@ * // => false */ function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arraySome : baseSome; return func(collection, predicate); } /** * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through `iterator`. This method performs + * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an array of property names is provided for `iterator` the collection + * If an array of property names is provided for `iteratee` the collection * is sorted by each property value. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5499,10 +5616,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [iterator=identity] The function + * @param {Array|Function|Object|string} [iteratee=identity] The function * called per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. * @example * @@ -5527,28 +5644,28 @@ * _.map(_.sortBy(characters, ['name', 'age']), _.values); * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ - function sortBy(collection, iterator, thisArg) { + function sortBy(collection, iteratee, thisArg) { var index = -1, length = collection ? collection.length : 0, - multi = iterator && isArray(iterator), + multi = iteratee && isArray(iteratee), result = []; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { result.length = length; } if (!multi) { - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); } baseEach(collection, function(value, key, collection) { if (multi) { - var length = iterator.length, + var length = iteratee.length, criteria = Array(length); while (length--) { - criteria[length] = value[iterator[length]]; + criteria[length] = value == null ? undefined : value[iteratee[length]]; } } else { - criteria = iterator(value, key, collection); + criteria = iteratee(value, key, collection); } result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; }); @@ -5579,7 +5696,7 @@ if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { return (support.unindexedChars && isString(collection)) ? collection.split('') - : slice(collection); + : baseSlice(collection); } return values(collection); } @@ -5687,7 +5804,7 @@ * and prepends any additional `bind` arguments to those provided to the bound * function. * - * Note: Unlike native `Function#bind` this method does not set the `length` + * **Note:** Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static @@ -5709,12 +5826,12 @@ */ function bind(func, thisArg) { if (arguments.length < 3) { - return createWrapper([func, BIND_FLAG, null, thisArg]); + return createWrapper(func, BIND_FLAG, null, thisArg); } var args = slice(arguments, 2), - partialHolders = replaceHolders(args, bind.placeholder); + holders = replaceHolders(args, bind.placeholder); - return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, partialHolders, thisArg); + return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, holders, thisArg); } /** @@ -5723,7 +5840,7 @@ * of method names. If no method names are provided all enumerable function * properties, own and inherited, of `object` are bound. * - * Note: This method does not set the `length` property of bound functions. + * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ @@ -5787,12 +5904,14 @@ * // => 'hiya fred!' */ function bindKey(object, key) { - var data = [key, BIND_FLAG | BIND_KEY_FLAG, null, object]; + var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (arguments.length > 2) { - var args = slice(arguments, 2); - data.push(args, replaceHolders(args, bindKey.placeholder)); + var args = slice(arguments, 2), + holders = replaceHolders(args, bindKey.placeholder); } - return createWrapper(data); + return args + ? createWrapper(key, bitmask, null, object, args, holders) + : createWrapper(key, bitmask, null, object); } /** @@ -5856,7 +5975,7 @@ * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. * - * Note: This method does not set the `length` property of curried functions. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ @@ -5889,7 +6008,7 @@ * This method is like `_.curry` except that arguments are applied to `func` * in the manner of `_.partialRight` instead of `_.partial`. * - * Note: This method does not set the `length` property of curried functions. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ @@ -5926,7 +6045,7 @@ * and/or trailing edge of the `wait` timeout. Subsequent calls to the * debounced function return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * @@ -6247,7 +6366,7 @@ * prepended to those provided to the new function. This method is similar to * `_.bind` except it does **not** alter the `this` binding. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -6265,16 +6384,16 @@ */ function partial(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partial.placeholder); + holders = replaceHolders(args, partial.placeholder); - return basePartial(func, PARTIAL_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_FLAG, args, holders); } /** * This method is like `_.partial` except that partially applied arguments * are appended to those provided to the new function. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -6303,9 +6422,9 @@ */ function partialRight(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partialRight.placeholder); + holders = replaceHolders(args, partialRight.placeholder); - return basePartial(func, PARTIAL_RIGHT_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_RIGHT_FLAG, args, holders); } /** @@ -6316,7 +6435,7 @@ * Subsequent calls to the throttled function return the result of the last * `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * @@ -6429,7 +6548,7 @@ * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -6492,7 +6611,7 @@ * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -6574,7 +6693,7 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property are ignored. * - * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * **Note:** See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. * * @static @@ -6592,7 +6711,7 @@ if (object == null) { return object; } - var args = slice(arguments); + var args = baseSlice(arguments); args.push(assignDefaults); return assign.apply(undefined, args); } @@ -6628,7 +6747,7 @@ * _.findKey(characters, function(chr) { * return chr.age < 40; * }); - * // => 'barney' (property order is not guaranteed across environments) + * // => 'barney' (property order is not guaranteed) * * // using "_.where" callback shorthand * _.findKey(characters, { 'age': 1 }); @@ -6691,7 +6810,7 @@ /** * Iterates over own and inherited enumerable properties of an object executing - * `iterator` for each property. The `iterator` is bound to `thisArg` and invoked + * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * @@ -6699,8 +6818,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6714,13 +6833,13 @@ * _.forIn(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments) + * // => logs 'x', 'y', and 'z' (property order is not guaranteed) */ - function forIn(object, iterator, thisArg) { - if (typeof iterator != 'function' || typeof thisArg != 'undefined') { - iterator = baseCallback(iterator, thisArg, 3); + function forIn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = baseCallback(iteratee, thisArg, 3); } - return baseFor(object, iterator, keysIn); + return baseFor(object, iteratee, keysIn); } /** @@ -6731,8 +6850,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6748,14 +6867,14 @@ * }); * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' */ - function forInRight(object, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); - return baseForRight(object, iterator, keysIn); + function forInRight(object, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keysIn); } /** - * Iterates over own enumerable properties of an object executing `iterator` - * for each property. The `iterator` is bound to `thisArg` and invoked with + * Iterates over own enumerable properties of an object executing `iteratee` + * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * @@ -6763,21 +6882,21 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) + * // => logs '0', '1', and 'length' (property order is not guaranteed) */ - function forOwn(object, iterator, thisArg) { - if (typeof iterator != 'function' || typeof thisArg != 'undefined') { - iterator = baseCallback(iterator, thisArg, 3); + function forOwn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = baseCallback(iteratee, thisArg, 3); } - return baseForOwn(object, iterator); + return baseForOwn(object, iteratee); } /** @@ -6788,8 +6907,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6798,9 +6917,9 @@ * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ - function forOwnRight(object, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); - return baseForRight(object, iterator, keys); + function forOwnRight(object, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keys); } /** @@ -6812,14 +6931,14 @@ * @alias methods * @category Object * @param {Object} object The object to inspect. - * @returns {Array} Returns the new sorted array of property names. + * @returns {Array} Returns the new array of property names. * @example * * _.functions(_); * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - return baseFunctions(object, keysIn); + return baseFunctions(object, keysIn(object)); } /** @@ -6999,7 +7118,7 @@ */ function isElement(value) { return (value && typeof value == 'object' && value.nodeType === 1 && - (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value))) || false; + (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isHostObject(value))) || false; } // fallback for environments without DOM support if (!support.dom) { @@ -7056,7 +7175,7 @@ * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). * - * Note: This method supports comparing arrays, booleans, `Date` objects, + * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. @@ -7119,7 +7238,7 @@ /** * Checks if `value` is a finite primitive number. * - * Note: This method is based on ES6 `Number.isFinite`. See the + * **Note:** This method is based on ES6 `Number.isFinite`. See the * [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) * for more details. * @@ -7181,7 +7300,7 @@ * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * Note: See the [ES5 spec](http://es5.github.io/#x8) for more details. + * **Note:** See the [ES5 spec](http://es5.github.io/#x8) for more details. * * @static * @memberOf _ @@ -7209,7 +7328,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which returns `true` + * **Note:** This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -7238,6 +7357,27 @@ return isNumber(value) && value != +value; } + /** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Object + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + */ + function isNative(value) { + if (isFunction(value)) { + return reNative.test(fnToString.call(value)); + } + if (value && typeof value == 'object') { + return !('constructor' in value) && isHostObject(value) + ? reNative.test(value) + : reHostCtor.test(toString.call(value)); + } + return false; + } + /** * Checks if `value` is `null`. * @@ -7261,7 +7401,7 @@ /** * Checks if `value` is classified as a `Number` primitive or object. * - * Note: To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static @@ -7290,7 +7430,7 @@ * Checks if `value` is an object created by the `Object` constructor or has * a `[[Prototype]]` of `null`. * - * Note: This method assumes objects created by the `Object` constructor + * **Note:** This method assumes objects created by the `Object` constructor * have no inherited enumerable properties. * * @static @@ -7408,7 +7548,7 @@ * Shape.prototype.z = 0; * * _.keys(new Shape); - * // => ['x', 'y'] (property order is not guaranteed across environments) + * // => ['x', 'y'] (property order is not guaranteed) */ var keys = !nativeKeys ? shimKeys : function(object) { object = toObject(object); @@ -7442,7 +7582,7 @@ * Shape.prototype.z = 0; * * _.keysIn(new Shape); - * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) + * // => ['x', 'y', 'z'] (property order is not guaranteed) */ function keysIn(object) { if (object == null) { @@ -7500,14 +7640,14 @@ /** * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through `iterator`. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * running each own enumerable property of `object` through `iteratee`. The + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, key, object). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -7515,10 +7655,10 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the new mapped object. * @example * @@ -7534,12 +7674,12 @@ * _.mapValues(characters, 'age'); * // => { 'fred': 40, 'pebbles': 1 } */ - function mapValues(object, iterator, thisArg) { + function mapValues(object, iteratee, thisArg) { var result = {}; - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); baseForOwn(object, function(value, key, object) { - result[key] = iterator(value, key, object); + result[key] = iteratee(value, key, object); }); return result; } @@ -7628,11 +7768,15 @@ if (object == null) { return {}; } - if (typeof predicate == 'function') { - return basePick(object, negate(getCallback(predicate, thisArg, 3))); + var iterable = toObject(object); + if (typeof predicate != 'function') { + var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + return pickByArray(iterable, baseDifference(keysIn(iterable), props)); } - var omitProps = baseFlatten(arguments, false, false, 1); - return basePick(toObject(object), baseDifference(keysIn(object), arrayMap(omitProps, String))); + predicate = getCallback(predicate, thisArg, 3); + return pickByCallback(iterable, function(value, key, object) { + return !predicate(value, key, object); + }); } /** @@ -7647,7 +7791,7 @@ * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed) */ function pairs(object) { var index = -1, @@ -7693,18 +7837,17 @@ if (object == null) { return {}; } - return basePick(toObject(object), - typeof predicate == 'function' - ? getCallback(predicate, thisArg, 3) - : baseFlatten(arguments, false, false, 1) - ); + var iterable = toObject(object); + return typeof predicate == 'function' + ? pickByCallback(iterable, getCallback(predicate, thisArg, 3)) + : pickByArray(iterable, baseFlatten(arguments, false, false, 1)); } /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own - * enumerable properties through `iterator`, with each execution potentially - * mutating the `accumulator` object. The `iterator` is bound to `thisArg` + * enumerable properties through `iteratee`, with each execution potentially + * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. * @@ -7712,9 +7855,9 @@ * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -7731,7 +7874,7 @@ * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ - function transform(object, iterator, accumulator, thisArg) { + function transform(object, iteratee, accumulator, thisArg) { var isArr = isArrayLike(object); if (accumulator == null) { @@ -7745,10 +7888,10 @@ accumulator = baseCreate(proto); } } - if (iterator) { - iterator = getCallback(iterator, thisArg, 4); + if (iteratee) { + iteratee = getCallback(iteratee, thisArg, 4); (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { - return iterator(accumulator, value, index, object); + return iteratee(accumulator, value, index, object); }); } return accumulator; @@ -7772,7 +7915,7 @@ * Shape.prototype.z = 0; * * _.values(new Shape(2, 1)); - * // => [2, 1] (property order is not guaranteed across environments) + * // => [2, 1] (property order is not guaranteed) */ function values(object) { return baseValues(object, keys); @@ -7797,7 +7940,7 @@ * Shape.prototype.z = 0; * * _.valuesIn(new Shape(2, 1)); - * // => [2, 1, 0] (property order is not guaranteed across environments) + * // => [2, 1, 0] (property order is not guaranteed) */ function valuesIn(object) { return baseValues(object, keysIn); @@ -7888,7 +8031,7 @@ * Converts the characters "&", "<", ">", '"', and "'" in `string` to * their corresponding HTML entities. * - * Note: No other characters are escaped. To escape additional characters + * **Note:** No other characters are escaped. To escape additional characters * use a third-party library like [_he_](http://mths.be/he). * * When working with HTML you should always quote attribute values to reduce @@ -8155,7 +8298,7 @@ * properties may be accessed as free variables in the template. If a setting * object is provided it overrides `_.templateSettings` for the template. * - * Note: In the development build `_.template` utilizes sourceURLs for easier debugging. + * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * @@ -8517,7 +8660,7 @@ * `&`, `<`, `>`, `"`, and `'` in `string` to their * corresponding characters. * - * Note: No other HTML entities are unescaped. To unescape additional HTML + * **Note:** No other HTML entities are unescaped. To unescape additional HTML * entities use a third-party library like [_he_](http://mths.be/he). * * @static @@ -8575,6 +8718,7 @@ * * @static * @memberOf _ + * @alias iteratee * @category Utility * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. @@ -8691,7 +8835,7 @@ var isStrict = isStrictComparable(value); flags[index] = isStrict; - vals[index] = isStrict ? value : baseClone(value, false); + vals[index] = isStrict ? value : baseClone(value); } return function(object) { index = length; @@ -8748,16 +8892,20 @@ */ function mixin(object, source, options) { var chain = true, - methodNames = source && baseFunctions(source, keys); + isObj = isObject(source), + noOpts = options == null, + props = noOpts && isObj && keys(source), + methodNames = props && baseFunctions(source, props); - if (!source || (!options && !methodNames.length)) { - if (options == null) { + if ((props && props.length && !methodNames.length) || (noOpts && !isObj)) { + if (noOpts) { options = source; } + methodNames = false; source = object; object = this; - methodNames = baseFunctions(source, keys); } + methodNames || (methodNames = baseFunctions(source, keys(source))); if (options === false) { chain = false; } else if (isObject(options) && 'chain' in options) { @@ -8765,7 +8913,7 @@ } var index = -1, isFunc = isFunction(object), - length = methodNames ? methodNames.length : 0; + length = methodNames.length; while (++index < length) { var methodName = methodNames[index], @@ -8849,7 +8997,7 @@ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * Note: This method avoids differences in native ES3 and ES5 `parseInt` + * **Note:** This method avoids differences in native ES3 and ES5 `parseInt` * implementations. See the [ES5 spec](http://es5.github.io/#E) * for more details. * @@ -9077,16 +9225,16 @@ } /** - * Executes the iterator function `n` times, returning an array of the results - * of each execution. The `iterator` is bound to `thisArg` and invoked with + * Executes the iteratee function `n` times, returning an array of the results + * of each execution. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iterator`. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {number} n The number of times to execute `iteratee`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example * @@ -9099,18 +9247,18 @@ * _.times(3, function(n) { this.cast(n); }, mage); * // => also calls `mage.castSpell(n)` three times */ - function times(n, iterator, thisArg) { + function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; - iterator = baseCallback(iterator, thisArg, 1); + iteratee = baseCallback(iteratee, thisArg, 1); var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); while (++index < n) { if (index < MAX_ARRAY_LENGTH) { - result[index] = iterator(index); + result[index] = iteratee(index); } else { - iterator(index); + iteratee(index); } } return result; @@ -9241,6 +9389,7 @@ lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; + lodash.iteratee = callback; lodash.methods = functions; lodash.object = zipObject; lodash.select = filter; @@ -9285,6 +9434,7 @@ lodash.isFinite = isFinite; lodash.isFunction = isFunction; lodash.isNaN = isNaN; + lodash.isNative = isNative; lodash.isNull = isNull; lodash.isNumber = isNumber; lodash.isObject = isObject; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 359d9fb81c..1f6ea7fcda 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -3,73 +3,74 @@ * Lo-Dash 3.0.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.compat.js` */ -;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) -}function v(n){for(var t=-1,r=n.length;++ti(t,f)&&l.push(f);return l}function qt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>k)return Qt(n,t);for(var e=-1,u=Fr(n);++e=r||r>k)return nr(n,t);for(var e=Fr(n);r--&&false!==t(e[r],r,e););return n}function Kt(n,t){var r=true;return qt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Vt(n,t){var r=[];return qt(n,function(n,e,u){t(n,e,u)&&r.push(n) -}),r}function Yt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function Jt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++e>>1,f=r(n[a]),l=e?f<=t:fo(c,p)&&((t||f)&&c.push(p),l.push(s))}return l}function hr(n,t){for(var r=-1,e=t(n),u=e.length,o=Te(u);++re)return t;var u=typeof r[2]; -if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3=t||t>k)return Ae(n);if(n=Ur(n),Cu.unindexedChars&&we(n))for(var r=-1;++re?_u(u+e,0):e||0;else if(e)return e=$r(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function Nr(n){return Pr(n,1) -}function Pr(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t&&(t=-t>u?0:u+t),r=typeof r=="undefined"||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t,r=Te(u);++er?_u(e+r,0):r||0:0,typeof n=="string"||!Nu(n)&&we(n)?ro&&(o=a);else t=i&&a?u:Ar(t,r,3),qt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Qr(n,t){return Gr(n,Ue(t))}function ne(n,t,r,e){return(Nu(n)?Rt:lr)(n,Ar(t,e,4),r,3>arguments.length,qt)}function te(n,t,r,e){return(Nu(n)?kt:lr)(n,Ar(t,e,4),r,3>arguments.length,Zt)}function re(n){n=Fr(n); -for(var t=-1,r=n.length,e=Te(r);++targuments.length)return jr([n,w,null,t]);var r=Pr(arguments,2),e=Sr(r,oe.placeholder);return ir(n,w|E,r,e,t)}function ie(n,t){var r=[t,w|j,null,n];if(2=r||r>t?(a&&ru(a),r=p,a=s=p=_,r&&(h=Zu(),f=n.apply(c,i),s||a||(i=c=null))):s=lu(e,r)}function u(){s&&ru(s),a=s=p=_,(v||g!==t)&&(h=Zu(),f=n.apply(c,i),s||a||(i=c=null))}function o(){if(i=arguments,l=Zu(),c=this,p=v&&(s||!y),false===g)var r=y&&!s;else{a||y||(h=l);var o=g-(l-h),d=0>=o||o>g; -d?(a&&(a=ru(a)),h=l,f=n.apply(c,i)):a||(a=lu(u,o))}return d&&s?s=ru(s):s||t===g||(s=lu(e,t)),r&&(d=true,f=n.apply(c,i)),!d||s||a||(i=c=null),f}var i,a,f,l,c,s,p,h=0,g=false,v=true;if(!de(n))throw new ze(S);if(t=0>t?0:t,true===r)var y=true,v=false;else me(r)&&(y=r.leading,g="maxWait"in r&&_u(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&ru(s),a&&ru(a),a=s=p=_},o}function ce(n){if(!de(n))throw new ze(S);return function(){return!n.apply(this,arguments)}}function se(n){var t=Pr(arguments,1),r=Sr(t,se.placeholder); -return ir(n,E,t,r)}function pe(n){var t=Pr(arguments,1),r=Sr(t,pe.placeholder);return ir(n,I,t,r)}function he(n){return tr(n,je)}function ge(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ge.call(n)==et||false}function ve(n){return n&&typeof n=="object"&&1===n.nodeType&&(Cu.nodeClass?-1t||null==n||!du(t))return r;n=Me(n);do t%2&&(r+=n),t=eu(t/2),n+=n; -while(t);return r}function Ee(n,t){return(n=null==n?"":Me(n))?null==t?n.slice(v(n),y(n)+1):(t=Me(t),n.slice(o(n,t),i(n,t)+1)):n}function Ie(n){try{return n()}catch(t){return ye(t)?t:We(t)}}function Ce(n,t){return Pt(n,t)}function Se(n){return n}function Re(n){var t=Bu(n),r=t.length;if(1==r){var e=t[0],u=n[e];if(Ir(u))return function(n){return null!=n&&u===n[e]&&ou.call(n,e)}}for(var o=r,i=Te(r),a=Te(r);o--;){var u=n[t[o]],f=Ir(u);i[o]=f,a[o]=f?u:$t(u,false)}return function(n){if(o=r,null==n)return!o; -for(;o--;)if(i[o]?a[o]!==n[t[o]]:!ou.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!ou.call(n,t[o]):!rr(a[o],n[t[o]],null,true))return false;return true}}function ke(n,t,r){var e=true,u=t&&tr(t,Bu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=tr(t,Bu)),false===r?e=false:me(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=de(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},g.assign=Wu,g.at=function(t){var r=t?t.length:0;return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),Pr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Ar(t,r,3);e--&&t(n[e],e,n););return Pr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Ar(t,r,3);++e(p?e(p,f):i(s,f))){for(t=u;--t;){var h=o[t];if(0>(h?e(h,f):i(n[t],f)))continue n}p&&p.push(f),s.push(f)}return s},g.invert=function(n,t){for(var r=-1,e=Bu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0; -return t=e-((null==t||r?1:t)||0),Pr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Ar(t,r,3);e--&&t(n[e],e,n););return Pr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Ar(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Me(n),$.lastIndex=0,$.test(n)?n.replace($,s):n -},g.escapeRegExp=xe,g.every=Kr,g.find=Yr,g.findIndex=Tr,g.findKey=function(n,t,r){return t=Ar(t,r,3),Yt(n,t,Qt,true)},g.findLast=function(n,t,r){return t=Ar(t,r,3),Yt(n,t,Zt)},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=Ar(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},g.findLastKey=function(n,t,r){return t=Ar(t,r,3),Yt(n,t,nr,true)},g.findWhere=function(n,t){return Yr(n,Re(t))},g.first=Lr,g.has=function(n,t){return n?ou.call(n,t):false},g.identity=Se,g.indexOf=Wr,g.isArguments=ge,g.isArray=Nu,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&Ge.call(n)==ot||false -},g.isDate=function(n){return n&&typeof n=="object"&&Ge.call(n)==it||false},g.isElement=ve,g.isEmpty=function(n){if(null==n)return true;var t=n.length;return typeof t=="number"&&-1r?_u(u+r,0):bu(r||0,u-1))+1;else if(r)return u=Br(n,t)-1,e&&n[u]===t?u:-1;for(;u--;)if(n[u]===t)return u;return-1},g.max=Hr,g.min=function(n,t,r){var e=1/0,o=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,a=!(i&&Nu(n))&&we(n);if(i&&!a)for(r=-1,n=Fr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=Wu({},r||t,e,Wt),n=Me(null==n?"":n),r=Wu({},t.imports,e.imports,Wt); -var u,o,i=Bu(r),a=Ae(r),f=0;r=t.interpolate||J;var l="__p+='";if(r=De((t.escape||J).source+"|"+r.source+"|"+(r===M?z:J).source+"|"+(t.evaluate||J).source+"|$","g"),n.replace(r,function(t,r,e,i,a,c){return e||(e=i),l+=n.slice(f,c).replace(H,p),r&&(u=true,l+="'+__e("+r+")+'"),a&&(o=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),f=c+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(L,""):l).replace(W,"$1").replace(N,"$1;"),l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Ie(function(){return Ne(i,"return "+l).apply(_,a) -}),t.source=l,ye(t))throw t;return t},g.trim=Ee,g.trimLeft=function(n,t){return(n=null==n?"":Me(n))?null==t?n.slice(v(n)):(t=Me(t),n.slice(o(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Me(n))?null==t?n.slice(0,y(n)+1):(t=Me(t),n.slice(0,i(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(me(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Me(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Me(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; -if(r=n.slice(0,o),null==u)return r+e;if(be(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=De(u.source,(q.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},Qt(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new Y(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=qr,g.prototype.toString=function(){return Me(this.__wrapped__) -},g.prototype.value=qr,g.prototype.valueOf=qr,Q(["join","pop","shift"],function(n){var t=qe[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new Y(r,n):r}}),Q(["push","reverse","sort","unshift"],function(n){var t=qe[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Q(["concat","splice"],function(n){var t=qe[n];g.prototype[n]=function(){return new Y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Cu.spliceObjects||Q(["pop","shift","splice"],function(n){var t=qe[n],r="splice"==n; -g.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new Y(u,n):u}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,O=16,E=32,I=64,C="__lodash_"+b.replace(/[-.]/g,"_")+"__",S="Expected a function",R=Math.pow(2,32)-1,k=Math.pow(2,53)-1,F="__lodash_placeholder__",U=0,T=/^[A-Z]+$/,L=/\b__p\+='';/g,W=/\b(__p\+=)''\+/g,N=/(__e\(.*?\)|\b__t\))\+'';/g,P=/&(?:amp|lt|gt|quot|#39|#96);/g,$=/[&<>"'`]/g,B=/<%-([\s\S]+?)%>/g,D=/<%([\s\S]+?)%>/g,M=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,q=/\w*$/,Z=/^\s*function[ \n\r\t]+\w/,K=/^0[xX]/,V=/^\[object .+?Constructor\]$/,Y=/[\xC0-\xFF]/g,J=/($^)/,X=/[.*+?^${}()|[\]\/\\]/g,G=/\bthis\b/,H=/['\n\r\u2028\u2029\\]/g,Q=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,nt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",tt="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),rt="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),et="[object Arguments]",ut="[object Array]",ot="[object Boolean]",it="[object Date]",at="[object Error]",ft="[object Function]",lt="[object Number]",ct="[object Object]",st="[object RegExp]",pt="[object String]",ht="[object ArrayBuffer]",gt="[object Float32Array]",vt="[object Float64Array]",yt="[object Int8Array]",dt="[object Int16Array]",mt="[object Int32Array]",_t="[object Uint8Array]",bt="[object Uint8ClampedArray]",wt="[object Uint16Array]",jt="[object Uint32Array]",At={}; -At[et]=At[ut]=At[gt]=At[vt]=At[yt]=At[dt]=At[mt]=At[_t]=At[bt]=At[wt]=At[jt]=true,At[ht]=At[ot]=At[it]=At[at]=At[ft]=At["[object Map]"]=At[lt]=At[ct]=At[st]=At["[object Set]"]=At[pt]=At["[object WeakMap]"]=false;var xt={};xt[et]=xt[ut]=xt[ht]=xt[ot]=xt[it]=xt[gt]=xt[vt]=xt[yt]=xt[dt]=xt[mt]=xt[lt]=xt[ct]=xt[st]=xt[pt]=xt[_t]=xt[bt]=xt[wt]=xt[jt]=true,xt[at]=xt[ft]=xt["[object Map]"]=xt["[object Set]"]=xt["[object WeakMap]"]=false;var Ot={leading:false,maxWait:0,trailing:false},Et={configurable:false,enumerable:false,value:null,writable:false},It={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Ct={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},St={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},Rt={"function":true,object:true},kt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ft=Rt[typeof window]&&window||this,Ut=Rt[typeof exports]&&exports&&!exports.nodeType&&exports,Rt=Rt[typeof module]&&module&&!module.nodeType&&module,Tt=Ut&&Rt&&typeof global=="object"&&global; -!Tt||Tt.global!==Tt&&Tt.window!==Tt&&Tt.self!==Tt||(Ft=Tt);var Tt=Rt&&Rt.exports===Ut&&Ut,Lt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ft._=Lt, define(function(){return Lt})):Ut&&Rt?Tt?(Rt.exports=Lt)._=Lt:Ut._=Lt:Ft._=Lt}).call(this); \ No newline at end of file +;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) +}function v(n){for(var t=-1,r=n.length;++ti(t,f)&&l.push(f);return l}function Zt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>U)return nr(n,t); +for(var e=-1,u=Pr(n);++e=r||r>U)return tr(n,t);for(var e=Pr(n);r--&&false!==t(e[r],r,e););return n}function Vt(n,t){var r=true;return Zt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Yt(n,t){var r=[];return Zt(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function Jt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function Xt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++e>>1,f=r(n[a]),l=e?f<=t:fo(c,p)&&((t||f)&&c.push(p),l.push(s))}return l}function gr(n,t){for(var r=-1,e=t(n),u=e.length,o=Me(u);++rt)return r;var e=typeof arguments[2];if("number"!=e&&"string"!=e||!arguments[3]||arguments[3][arguments[2]]!==arguments[1]||(t=2),3=t||t>U)return Se(n);if(n=$r(n),Nu.unindexedChars&&Ie(n))for(var r=-1;++re?Iu(u+e,0):e||0;else if(e)return e=Zr(n,t),u&&n[e]===t?e:-1; +return r(n,t,e)}function zr(n){return qr(n,1)}function qr(n,t,r){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),r=typeof r=="undefined"||r>o?o:+r||0,0>r&&(r+=o),r&&r==o&&!t)return e(n);for(o=t>r?0:r-t,r=Me(o);++ur?Iu(e+r,0):r||0:0,typeof n=="string"||!Vu(n)&&Ie(n)?ru&&(u=a);else t=i&&a?o:Er(t,r,3),Zt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function oe(n,t){return ee(n,De(t))}function ie(n,t,r,e){return(Vu(n)?Ft:lr)(n,Er(t,e,4),r,3>arguments.length,Zt)}function ae(n,t,r,e){return(Vu(n)?Ut:lr)(n,Er(t,e,4),r,3>arguments.length,Kt) +}function fe(n){n=Pr(n);for(var t=-1,r=n.length,e=Me(r);++targuments.length)return Or(n,w,null,t);var r=qr(arguments,2),e=Lr(r,se.placeholder);return ar(n,w|E,r,e,t)}function pe(n,t){var r=w|j;if(2=r||r>t?(a&&su(a),r=p,a=s=p=_,r&&(h=to(),f=n.apply(c,i),s||a||(i=c=null))):s=du(e,r)}function u(){s&&su(s),a=s=p=_,(v||g!==t)&&(h=to(),f=n.apply(c,i),s||a||(i=c=null))}function o(){if(i=arguments,l=to(),c=this,p=v&&(s||!y),false===g)var r=y&&!s;else{a||y||(h=l);var o=g-(l-h),d=0>=o||o>g; +d?(a&&(a=su(a)),h=l,f=n.apply(c,i)):a||(a=du(u,o))}return d&&s?s=su(s):s||t===g||(s=du(e,t)),r&&(d=true,f=n.apply(c,i)),!d||s||a||(i=c=null),f}var i,a,f,l,c,s,p,h=0,g=false,v=true;if(!je(n))throw new Ge(R);if(t=0>t?0:t,true===r)var y=true,v=false;else Ae(r)&&(y=r.leading,g="maxWait"in r&&Iu(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&su(s),a&&su(a),a=s=p=_},o}function ye(n){var t=qr(arguments,1),r=Lr(t,ye.placeholder);return ar(n,E,t,r)}function de(n){var t=qr(arguments,1),r=Lr(t,de.placeholder); +return ar(n,I,t,r)}function me(n){return rr(n,Ce(n))}function _e(n){return n&&typeof n=="object"&&typeof n.length=="number"&&iu.call(n)==ot||false}function be(n){return n&&typeof n=="object"&&1===n.nodeType&&(Nu.nodeClass?-1t||null==n||!Ou(t))return r;n=Xe(n);do t%2&&(r+=n),t=pu(t/2),n+=n; +while(t);return r}function Fe(n,t){return(n=null==n?"":Xe(n))?null==t?n.slice(v(n),y(n)+1):(t=Xe(t),n.slice(i(n,t),a(n,t)+1)):n}function Ue(n){try{return n()}catch(t){return we(t)?t:qe(t)}}function Te(n,t){return Bt(n,t)}function Le(n){return function(){return n}}function We(n){return n}function Ne(n){var t=Xu(n),r=t.length;if(1==r){var e=t[0],u=n[e];if(Fr(u))return function(n){return null!=n&&u===n[e]&&uu.call(n,e)}}for(var o=r,i=Me(r),a=Me(r);o--;){var u=n[t[o]],f=Fr(u);i[o]=f,a[o]=f?u:Dt(u)}return function(n){if(o=r,null==n)return!o; +for(;o--;)if(i[o]?a[o]!==n[t[o]]:!uu.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!uu.call(n,t[o]):!er(a[o],n[t[o]],null,true))return false;return true}}function Pe(n,t,r){var e=true,u=Ae(t),o=null==r,i=o&&u&&Xu(t),a=i&&rr(t,i);(i&&i.length&&!a.length||o&&!u)&&(o&&(r=t),a=false,t=n,n=this),a||(a=rr(t,Xu(t))),false===r?e=false:Ae(r)&&"chain"in r&&(e=r.chain),r=-1,u=je(n);for(o=a.length;++rC)return r +}else n=0;return cr(r,e)}}(),Du=mr(function(n,t,r){uu.call(n,r)?++n[r]:n[r]=1}),Mu=mr(function(n,t,r){uu.call(n,r)?n[r].push(t):n[r]=[t]}),zu=mr(function(n,t,r){n[r]=t}),qu=mr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Zu=ye(ce,2),Ku=_r($t);Nu.argsClass||(_e=function(n){var t=n&&typeof n=="object"?n.length:_;return typeof t=="number"&&-1--n?t.apply(this,arguments):void 0}},g.assign=Ku,g.at=function(t){var r=t?t.length:0;return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0; +return t=e-((null==t||r?1:t)||0),qr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Er(t,r,3);e--&&t(n[e],e,n););return qr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Er(t,r,3);++e(p?u(p,f):i(s,f))){for(t=e;--t;){var h=o[t];if(0>(h?u(h,f):i(n[t],f)))continue n}p&&p.push(f),s.push(f)}return s},g.invert=function(n,t){for(var r=-1,e=Xu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0; +return t=e-((null==t||r?1:t)||0),qr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Er(t,r,3);e--&&t(n[e],e,n););return qr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Er(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Xe(n),D.lastIndex=0,D.test(n)?n.replace(D,p):n +},g.escapeRegExp=ke,g.every=Hr,g.find=ne,g.findIndex=Br,g.findKey=function(n,t,r){return t=Er(t,r,3),Jt(n,t,nr,true)},g.findLast=function(n,t,r){return t=Er(t,r,3),Jt(n,t,Kt)},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=Er(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},g.findLastKey=function(n,t,r){return t=Er(t,r,3),Jt(n,t,tr,true)},g.findWhere=function(n,t){return ne(n,Ne(t))},g.first=Dr,g.has=function(n,t){return n?uu.call(n,t):false},g.identity=We,g.indexOf=Mr,g.isArguments=_e,g.isArray=Vu,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&iu.call(n)==at||false +},g.isDate=function(n){return n&&typeof n=="object"&&iu.call(n)==ft||false},g.isElement=be,g.isEmpty=function(n){if(null==n)return true;var t=n.length;return typeof t=="number"&&-1r?Iu(u+r,0):Cu(r||0,u-1))+1;else if(r)return u=Kr(n,t)-1,e&&n[u]===t?u:-1;for(r=t===t;u--;)if(e=n[u],r?e===t:e!==e)return u;return-1},g.max=ue,g.min=function(n,t,r){var e=1/0,u=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,a=!(i&&Vu(n))&&Ie(n);if(i&&!a)for(r=-1,n=Pr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=Ku({},r||t,e,Pt),n=Xe(null==n?"":n),r=Ku({},t.imports,e.imports,Pt); +var u,o,i=Xu(r),a=Se(r),f=0;r=t.interpolate||G;var l="__p+='";if(r=Je((t.escape||G).source+"|"+r.source+"|"+(r===q?Z:G).source+"|"+(t.evaluate||G).source+"|$","g"),n.replace(r,function(t,r,e,i,a,c){return e||(e=i),l+=n.slice(f,c).replace(nt,h),r&&(u=true,l+="'+__e("+r+")+'"),a&&(o=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),f=c+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(N,""):l).replace(P,"$1").replace($,"$1;"),l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Ue(function(){return Ze(i,"return "+l).apply(_,a) +}),t.source=l,we(t))throw t;return t},g.trim=Fe,g.trimLeft=function(n,t){return(n=null==n?"":Xe(n))?null==t?n.slice(v(n)):(t=Xe(t),n.slice(i(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Xe(n))?null==t?n.slice(0,y(n)+1):(t=Xe(t),n.slice(0,a(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(Ae(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Xe(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Xe(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; +if(r=n.slice(0,o),null==u)return r+e;if(Ee(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Je(u.source,(K.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},nr(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new X(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=Xr,g.prototype.toString=function(){return Xe(this.__wrapped__) +},g.prototype.value=Xr,g.prototype.valueOf=Xr,tt(["join","pop","shift"],function(n){var t=He[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new X(r,n):r}}),tt(["push","reverse","sort","unshift"],function(n){var t=He[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),tt(["concat","splice"],function(n){var t=He[n];g.prototype[n]=function(){return new X(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Nu.spliceObjects||tt(["pop","shift","splice"],function(n){var t=He[n],r="splice"==n; +g.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new X(u,n):u}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,O=16,E=32,I=64,C=150,S=16,k="__lodash_"+b.replace(/[-.]/g,"_")+"__",R="Expected a function",F=Math.pow(2,32)-1,U=Math.pow(2,53)-1,T="__lodash_placeholder__",L=0,W=/^[A-Z]+$/,N=/\b__p\+='';/g,P=/\b(__p\+=)''\+/g,$=/(__e\(.*?\)|\b__t\))\+'';/g,B=/&(?:amp|lt|gt|quot|#39|#96);/g,D=/[&<>"'`]/g,M=/<%-([\s\S]+?)%>/g,z=/<%([\s\S]+?)%>/g,q=/<%=([\s\S]+?)%>/g,Z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,Y=/^0[xX]/,J=/^\[object .+?Constructor\]$/,X=/[\xC0-\xFF]/g,G=/($^)/,H=/[.*+?^${}()|[\]\/\\]/g,Q=/\bthis\b/,nt=/['\n\r\u2028\u2029\\]/g,tt=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,rt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",et="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),ut="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ot="[object Arguments]",it="[object Array]",at="[object Boolean]",ft="[object Date]",lt="[object Error]",ct="[object Function]",st="[object Number]",pt="[object Object]",ht="[object RegExp]",gt="[object String]",vt="[object ArrayBuffer]",yt="[object Float32Array]",dt="[object Float64Array]",mt="[object Int8Array]",_t="[object Int16Array]",bt="[object Int32Array]",wt="[object Uint8Array]",jt="[object Uint8ClampedArray]",At="[object Uint16Array]",xt="[object Uint32Array]",Ot={}; +Ot[ot]=Ot[it]=Ot[yt]=Ot[dt]=Ot[mt]=Ot[_t]=Ot[bt]=Ot[wt]=Ot[jt]=Ot[At]=Ot[xt]=true,Ot[vt]=Ot[at]=Ot[ft]=Ot[lt]=Ot[ct]=Ot["[object Map]"]=Ot[st]=Ot[pt]=Ot[ht]=Ot["[object Set]"]=Ot[gt]=Ot["[object WeakMap]"]=false;var Et={};Et[ot]=Et[it]=Et[vt]=Et[at]=Et[ft]=Et[yt]=Et[dt]=Et[mt]=Et[_t]=Et[bt]=Et[st]=Et[pt]=Et[ht]=Et[gt]=Et[wt]=Et[jt]=Et[At]=Et[xt]=true,Et[lt]=Et[ct]=Et["[object Map]"]=Et["[object Set]"]=Et["[object WeakMap]"]=false;var It={leading:false,maxWait:0,trailing:false},Ct={configurable:false,enumerable:false,value:null,writable:false},St={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},kt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Rt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},Ft={"function":true,object:true},Ut={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Tt=Ft[typeof window]&&window||this,Lt=Ft[typeof exports]&&exports&&!exports.nodeType&&exports,Ft=Ft[typeof module]&&module&&!module.nodeType&&module,Wt=Lt&&Ft&&typeof global=="object"&&global; +!Wt||Wt.global!==Wt&&Wt.window!==Wt&&Wt.self!==Wt||(Tt=Wt);var Wt=Ft&&Ft.exports===Lt&&Lt,Nt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Tt._=Nt, define(function(){return Nt})):Lt&&Ft?Wt?(Ft.exports=Nt)._=Nt:Lt._=Nt:Tt._=Nt}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index c4f291d03b..97228c370e 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -24,6 +24,10 @@ PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64; + /** Used to detect when a function becomes hot */ + var HOT_COUNT = 150, + HOT_SPAN = 16; + /** Used as the property name for wrapper metadata */ var EXPANDO = '__lodash_' + VERSION.replace(/[-.]/g, '_') + '__'; @@ -122,7 +126,8 @@ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'window', 'WinRTError' + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + 'window', 'WinRTError' ]; /** Used to make template sourceURLs easier to identify */ @@ -202,7 +207,7 @@ /** * Used to convert characters to HTML entities. * - * Note: Though the ">" character is escaped for symmetry, characters like + * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) @@ -345,16 +350,37 @@ */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; + length = array ? array.length : 0, + isReflexive = value === value; while (++index < length) { - if (array[index] === value) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { return index; } } return -1; } + /** + * The base implementation of `_.slice` without support for `start` and `end` + * arguments. + * + * @private + * @param {Array} array The array to slice. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = array[index]; + } + return result; + } + /** * An implementation of `_.contains` for cache objects that mimics the return * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. @@ -393,7 +419,7 @@ var index = -1, length = string.length; - while (++index < length && chars.indexOf(string.charAt(index)) > -1) { } + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} return index; } @@ -409,7 +435,7 @@ function charsRightIndex(string, chars) { var index = string.length; - while (index-- && chars.indexOf(string.charAt(index)) > -1) { } + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} return index; } @@ -538,7 +564,7 @@ var index = -1, length = string.length; - while (++index < length && isWhitespace(string.charCodeAt(index))) { } + while (++index < length && isWhitespace(string.charCodeAt(index))) {} return index; } @@ -553,7 +579,7 @@ function trimmedRightIndex(string) { var index = string.length; - while (index-- && isWhitespace(string.charCodeAt(index))) { } + while (index-- && isWhitespace(string.charCodeAt(index))) {} return index; } @@ -618,8 +644,7 @@ /** Used for native method references */ var arrayProto = Array.prototype, - objectProto = Object.prototype, - stringProto = String.prototype; + objectProto = Object.prototype; /** Used to detect DOM support */ var document = (document = context.window) && document.document; @@ -627,6 +652,9 @@ /** 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 restore the original `_` reference in `_.noConflict` */ var oldDash = context._; @@ -646,13 +674,13 @@ clearTimeout = context.clearTimeout, floor = Math.floor, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, - hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, - Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array; + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, + WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers */ var Float64Array = (function() { @@ -662,7 +690,7 @@ try { var func = isNative(func = context.Float64Array) && func, result = new func(new ArrayBuffer(10), 0, 1) && func; - } catch(e) { } + } catch(e) {} return result; }()); @@ -673,13 +701,12 @@ var o = {}, func = isNative(func = Object.defineProperty) && func, result = func(o, o, o) && func; - } catch(e) { } + } catch(e) {} return result; }()); /* Native method references for those with the same name as other `lodash` methods */ - var nativeContains = isNative(nativeContains = stringProto.contains) && nativeContains, - nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, + var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = context.isFinite, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, @@ -693,6 +720,9 @@ /** Used as the size, in bytes, of each Float64Array element */ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; + /** Used to store function metadata */ + var metaMap = WeakMap && new WeakMap; + /*--------------------------------------------------------------------------*/ /** @@ -724,17 +754,17 @@ * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, - * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, - * `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, - * `isString`, `isUndefined`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, - * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, - * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, - * `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, - * `unescape`, `uniqueId`, and `value` + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, + * `lastIndexOf`, `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, + * `padRight`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, + * `result`, `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, + * `sortedLastIndex`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `unescape`, `uniqueId`, and `value` * * The wrapper function `sample` will return a wrapped value when `n` is * provided, otherwise it will return an unwrapped value. @@ -799,8 +829,6 @@ (function(x) { - for (var argsKey in arguments) { } - /** * Detect if functions can be decompiled by `Function#toString` * (all but Firefox OS certified apps, older Opera mobile browsers, and @@ -831,6 +859,18 @@ support.dom = false; } + /** + * Detect if the host objects are detectable (IE < 9). + * + * @memberOf _.support + * @type boolean + */ + try { + support.hostObject = !({ 'toString': 0 } + ''); + } catch(e) { + support.hostObject = false; + } + /** * Detect if `arguments` object indexes are non-enumerable. * @@ -844,7 +884,7 @@ * @type boolean */ try { - support.nonEnumArgs = !(hasOwnProperty.call(arguments, 1) && propertyIsEnumerable.call(arguments, 1)); + support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); } catch(e) { support.nonEnumArgs = true; } @@ -919,15 +959,15 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEach(array, iterator) { + function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { - if (iterator(array[index], index, array) === false) { + if (iteratee(array[index], index, array) === false) { break; } } @@ -940,14 +980,14 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEachRight(array, iterator) { + function arrayEachRight(array, iteratee) { var length = array.length; while (length--) { - if (iterator(array[length], length, array) === false) { + if (iteratee(array[length], length, array) === false) { break; } } @@ -982,16 +1022,16 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function arrayMap(array, iterator) { + function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { - result[index] = iterator(array[index], index, array); + result[index] = iteratee(array[index], index, array); } return result; } @@ -1008,12 +1048,13 @@ function arrayFilter(array, predicate) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { - result.push(value); + result[++resIndex] = value; } } return result; @@ -1025,13 +1066,13 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduce(array, iterator, accumulator, initFromArray) { + function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; @@ -1039,7 +1080,7 @@ accumulator = array[++index]; } while (++index < length) { - accumulator = iterator(accumulator, array[index], index, array); + accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } @@ -1050,20 +1091,20 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduceRight(array, iterator, accumulator, initFromArray) { + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { var length = array.length; if (initFromArray && length) { accumulator = array[--length]; } while (length--) { - accumulator = iterator(accumulator, array[length], length, array); + accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } @@ -1107,7 +1148,7 @@ /** * Used by `_.template` to customize its `_.assign` use. * - * Note: This method is like `assignDefaults` except that it ignores + * **Note:** This method is like `assignDefaults` except that it ignores * inherited property values when checking if a property is `undefined`. * * @private @@ -1162,7 +1203,7 @@ while (++index < length) { var key = methodNames[index]; - object[key] = createWrapper([object[key], BIND_FLAG, null, object]); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -1184,7 +1225,7 @@ if (typeof thisArg == 'undefined') { return func; } - var data = func[EXPANDO]; + var data = getData(func); if (typeof data == 'undefined') { if (support.funcNames) { data = !func.name; @@ -1198,7 +1239,7 @@ if (!data) { // checks if `func` references the `this` keyword and stores the result data = reThis.test(source) || isNative(func); - setData(func, data); + baseSetData(func, data); } } } @@ -1248,75 +1289,15 @@ if (typeof result != 'undefined') { return result; } - var isArr = isArray(value), - isShallow = !isDeep; - + var isArr = isArray(value); + result = value; if (isArr) { - result = isShallow ? slice(value) : value.constructor(value.length); - - // add array properties assigned by `RegExp#exec` - if (typeof value[0] == 'string' && hasOwnProperty.call(value, 'index')) { - result.index = value.index; - result.input = value.input; - } - if (isShallow) { - return result; - } + result = initArrayClone(value, isDeep); + } else if (isObject(value)) { + result = initObjectClone(value, isDeep); + value = (isDeep && toString.call(result) == objectClass) ? value : result; } - else { - if (!isObject(value)) { - return value; - } - var className = toString.call(value); - if (!cloneableClasses[className]) { - return value; - } - var isArgs = className == argsClass, - isObj = !isArgs && className == objectClass; - - if (isShallow && (isArgs || isObj)) { - result = baseAssign({}, value); - if (isObj) { - return result; - } - } - var Ctor = value.constructor; - if (className == objectClass && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { - Ctor = Object; - } - if (isDeep && (isArgs || isObj)) { - result = new Ctor; - } - else { - switch (className) { - case arrayBufferClass: - return cloneBuffer(value); - - case boolClass: - case dateClass: - return new Ctor(+value); - - case float32Class: case float64Class: - case int8Class: case int16Class: case int32Class: - case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: - var buffer = value.buffer; - return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, value.byteOffset, value.length); - - case numberClass: - case stringClass: - return new Ctor(value); - - case regexpClass: - result = Ctor(value.source, reFlags.exec(value)); - result.lastIndex = value.lastIndex; - return result; - } - } - } - if (isArgs) { - result.length = value.length; - } - if (isShallow) { + if (!isDeep || result === value) { return result; } // check for circular references and return corresponding clone @@ -1371,85 +1352,6 @@ }()); } - /** - * The base implementation of `createWrapper` which creates the wrapper and - * sets its metadata. - * - * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(data) { - var bitmask = data[1]; - if (bitmask == BIND_FLAG) { - return setData(createBindWrapper(data), data); - } - var partialHolders = data[5]; - if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { - return setData(createPartialWrapper(data), data); - } - var func = data[0], - arity = data[2], - thisArg = data[3], - partialArgs = data[4], - partialRightArgs = data[6], - partialRightHolders = data[7]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryRight = bitmask & CURRY_RIGHT_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG; - - var Ctor = !isBindKey && createCtorWrapper(func), - key = func; - - var wrapper = function() { - var length = arguments.length, - index = length, - args = Array(length); - - while (index--) { - args[index] = arguments[index]; - } - if (partialArgs) { - args = composeArgs(partialArgs, partialHolders, args); - } - if (partialRightArgs) { - args = composeArgsRight(partialRightArgs, partialRightHolders, args); - } - if (isCurry || isCurryRight) { - var placeholder = wrapper.placeholder, - newPartialHolders = replaceHolders(args, placeholder); - - length -= newPartialHolders.length; - - if (length < arity) { - bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); - bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); - - if (!isCurryBound) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); - } - var newData = [func, bitmask, nativeMax(arity - length, 0), thisArg, null, null]; - newData[isCurry ? 4 : 6] = args; - newData[isCurry ? 5 : 7] = newPartialHolders; - - var result = baseCreateWrapper(newData); - result.placeholder = placeholder; - return result; - } - } - var thisBinding = isBind ? thisArg : this; - if (isBindKey) { - func = thisBinding[key]; - } - return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); - }; - - return setData(wrapper, data); - } - /** * The base implementation of `_.curry` and `_.curryRight` which handles * resolving the default arity of `func`. @@ -1462,9 +1364,9 @@ */ function baseCurry(func, bitmask, arity) { if (typeof arity != 'number') { - arity = +arity || (func ? func.length : 0); + arity = arity == null ? (func ? func.length : 0) : nativeMax(+arity || 0, 0); } - return createWrapper([func, bitmask, arity]); + return createWrapper(func, bitmask, arity); } /** @@ -1497,7 +1399,7 @@ while (++index < length) { var value = array[index]; - if (isCommon) { + if (isCommon && value === value) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { @@ -1519,19 +1421,19 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEach(collection, iterator) { + function baseEach(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwn(collection, iterator); + return baseForOwn(collection, iteratee); } var index = -1, iterable = toIterable(collection); while (++index < length) { - if (iterator(iterable[index], index, iterable) === false) { + if (iteratee(iterable[index], index, iterable) === false) { break; } } @@ -1544,17 +1446,17 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEachRight(collection, iterator) { + function baseEachRight(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwnRight(collection, iterator); + return baseForOwnRight(collection, iteratee); } var iterable = toIterable(collection); while (length--) { - if (iterator(iterable[length], length, iterable) === false) { + if (iteratee(iterable[length], length, iterable) === false) { break; } } @@ -1668,24 +1570,24 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iterator` for + * over `object` properties returned by `keysFunc` executing `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseFor(object, iterator, keysFunc) { + function baseFor(object, iteratee, keysFunc) { var index = -1, props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; - if (iterator(object[key], key, object) === false) { + if (iteratee(object[key], key, object) === false) { break; } } @@ -1698,17 +1600,17 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForRight(object, iterator, keysFunc) { + function baseForRight(object, iteratee, keysFunc) { var props = keysFunc(object), length = props.length; while (length--) { var key = props[length]; - if (iterator(object[key], key, object) === false) { + if (iteratee(object[key], key, object) === false) { break; } } @@ -1721,11 +1623,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForIn(object, iterator) { - return baseFor(object, iterator, keysIn); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); } /** @@ -1734,11 +1636,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwn(object, iterator) { - return baseFor(object, iterator, keys); + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); } /** @@ -1747,32 +1649,32 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwnRight(object, iterator) { - return baseForRight(object, iterator, keys); + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); } /** - * The base implementation of `_.functions` which creates an array of function - * property names from those returned by `keysFunc`. + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. * * @private * @param {Object} object The object to inspect. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Array} Returns the new sorted array of property names. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. */ - function baseFunctions(object, keysFunc) { + function baseFunctions(object, props) { var index = -1, - props = keysFunc(object), length = props.length, + resIndex = -1, result = []; while (++index < length) { var key = props[index]; if (isFunction(object[key])) { - result.push(key); + result[++resIndex] = key; } } return result; @@ -1896,7 +1798,7 @@ return (value != +value) ? other != +other // but treat `-0` vs. `+0` as not equal - : (value == 0 ? (1 / value == 1 / other) : value == +other); + : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); case regexpClass: case stringClass: @@ -1999,14 +1901,14 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function baseMap(collection, iterator) { + function baseMap(collection, iteratee) { var result = []; baseEach(collection, function(value, key, collection) { - result.push(iterator(value, key, collection)); + result.push(iteratee(value, key, collection)); }); return result; } @@ -2089,51 +1991,14 @@ */ function basePartial(func, bitmask, args, holders, thisArg) { if (func) { - var data = func[EXPANDO], + var data = getData(func), arity = data ? data[2] : func.length; arity -= args.length; } - var isPartial = bitmask & PARTIAL_FLAG, - newData = [func, bitmask, arity, thisArg, null, null]; - - newData[isPartial ? 4 : 6] = args; - newData[isPartial ? 5 : 7] = holders; - return createWrapper(newData); - } - - /** - * The base implementation of `_.pick` without support for `this` binding - * and individual property name arguments. - * - * @private - * @param {Object} object The source object. - * @param {Function|string[]} predicate The function called per iteration or - * property names to pick. - * @returns {Object} Returns the new object. - */ - function basePick(object, predicate) { - var result = {}; - - if (typeof predicate == 'function') { - baseForIn(object, function(value, key, object) { - if (predicate(value, key, object)) { - result[key] = value; - } - }); - return result; - } - var index = -1, - props = predicate, - length = props.length; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - return result; + return (bitmask & PARTIAL_FLAG) + ? createWrapper(func, bitmask, arity, thisArg, args, holders) + : createWrapper(func, bitmask, arity, thisArg, null, null, args, holders); } /** @@ -2180,22 +2045,44 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ - function baseReduce(collection, iterator, accumulator, initFromCollection, eachFunc) { + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) - : iterator(accumulator, value, index, collection) + : iteratee(accumulator, value, index, collection) }); return accumulator; } + /** + * The base implementation of `setData` without support for hot loop detection. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + function baseSetData(func, data) { + metaMap.set(func, data); + return func; + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + baseSetData = !defineProperty ? identity : function(func, value) { + descriptor.value = value; + defineProperty(func, EXPANDO, descriptor); + descriptor.value = null; + return func; + }; + } + /** * The base implementation of `_.some` without support for callback shorthands * or `this` binding. @@ -2223,24 +2110,24 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ - function baseSortedIndex(array, value, iterator, retHighest) { + function baseSortedIndex(array, value, iteratee, retHighest) { var low = 0, high = array ? array.length : low; - value = iterator(value); + value = iteratee(value); var hintNum = typeof value == 'number' || (value != null && isFunction(value.valueOf) && typeof value.valueOf() == 'number'); while (low < high) { var mid = (low + high) >>> 1, - computed = iterator(array[mid]), - setLow = retHighest ? computed <= value : computed < value; + computed = iteratee(array[mid]), + setLow = retHighest ? (computed <= value) : (computed < value); if (hintNum && typeof computed != 'undefined') { computed = +computed; @@ -2261,10 +2148,10 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function baseUniq(array, iterator) { + function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), length = array.length, @@ -2277,27 +2164,27 @@ var seen = createCache(); indexOf = cacheIndexOf; } else { - seen = iterator ? [] : result; + seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; - if (isCommon) { + if (isCommon && value === value) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } - if (iterator) { + if (iteratee) { seen.push(computed); } result.push(value); } else if (indexOf(seen, computed) < 0) { - if (iterator || isLarge) { + if (iteratee || isLarge) { seen.push(computed); } result.push(value); @@ -2328,6 +2215,36 @@ return result; } + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function bufferClone(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` + bufferClone = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, + offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; + } + /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. @@ -2393,7 +2310,7 @@ /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection - * through `iterator`. The given setter function sets the keys and values of + * through `iteratee`. The given setter function sets the keys and values of * the accumulator object. If `initializer` is provided it is used to initialize * the accumulator object. * @@ -2403,9 +2320,9 @@ * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { - return function(collection, iterator, thisArg) { + return function(collection, iteratee, thisArg) { var result = initializer ? initializer() : {}; - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, @@ -2413,11 +2330,11 @@ while (++index < length) { var value = collection[index]; - setter(result, value, iterator(value, index, collection), collection); + setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { - setter(result, value, iterator(value, key, collection), collection); + setter(result, value, iteratee(value, key, collection), collection); }); } return result; @@ -2433,44 +2350,43 @@ * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { - return function(object) { - var args = arguments, - length = args.length; + return function() { + var length = arguments.length, + object = arguments[0]; if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` - var type = typeof args[2]; - if ((type == 'number' || type == 'string') && args[3] && args[3][args[2]] === args[1]) { + var type = typeof arguments[2]; + if ((type == 'number' || type == 'string') && arguments[3] && arguments[3][arguments[2]] === arguments[1]) { length = 2; } // juggle arguments - if (length > 3 && typeof args[length - 2] == 'function') { - var customizer = baseCallback(args[--length - 1], args[length--], 5); - } else if (length > 2 && typeof args[length - 1] == 'function') { - customizer = args[--length]; + if (length > 3 && typeof arguments[length - 2] == 'function') { + var customizer = baseCallback(arguments[--length - 1], arguments[length--], 5); + } else if (length > 2 && typeof arguments[length - 1] == 'function') { + customizer = arguments[--length]; } var index = 0; while (++index < length) { - assigner(object, args[index], customizer); + assigner(object, arguments[index], customizer); } return object; }; } /** - * Creates a function that invokes the function specified in the metadata - * with its associated `this` binding. + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new bound function. + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. */ - function createBindWrapper(data) { - var func = data[0], - thisArg = data[3], - Ctor = createCtorWrapper(func); + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); function wrapper() { return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); @@ -2515,6 +2431,77 @@ }; } + /** + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. + * @returns {Function} Returns the new function. + */ + function createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG; + + var Ctor = !isBindKey && createCtorWrapper(func), + key = func; + + function wrapper() { + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partialArgs) { + args = composeArgs(partialArgs, partialHolders, args); + } + if (partialRightArgs) { + args = composeArgsRight(partialRightArgs, partialRightHolders, args); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, + holders = replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + var newArity = nativeMax(arity - length, 0), + newPartialArgs = isCurry ? args : null, + newPartialHolders = isCurry ? holders : null, + newPartialRightArgs = isCurry ? null : args, + newPartialRightHolders = isCurry ? null : holders; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var result = createHybridWrapper(func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders); + result.placeholder = placeholder; + return setData(result, [func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders]); + } + } + var thisBinding = isBind ? thisArg : this; + if (isBindKey) { + func = thisBinding[key]; + } + return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); + } + return wrapper; + } + /** * Creates the pad required for `string` based on the given padding length. * The `chars` string may be truncated if the number of padding characters @@ -2539,25 +2526,25 @@ } /** - * Creates a function that invokes the function specified in the metadata - * with its associated partially applied arguments and optional `this` binding. + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partialArgs` prepended to those provided to + * the wrapper. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {Array} partialArgs An array of arguments to prepend to those provided to the new function. + * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new bound function. */ - function createPartialWrapper(data) { - var func = data[0], - thisArg = data[3], - partialArgs = data[4]; - - var isBind = data[1] & BIND_FLAG, + function createPartialWrapper(func, bitmask, partialArgs, thisArg) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` - var argsIndex = 0, + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partialArgs.length, @@ -2567,7 +2554,7 @@ args[leftIndex] = partialArgs[leftIndex]; } while (argsLength--) { - args[leftIndex++] = arguments[argsIndex++]; + args[leftIndex++] = arguments[++argsIndex]; } return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); } @@ -2579,9 +2566,8 @@ * `this` binding and partially applied arguments. * * @private - * @param {Array} data The metadata array. - * @param {Function|string} data[0] The function or method name to reference. - * @param {number} data[1] The bitmask of flags to compose. + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` @@ -2590,97 +2576,80 @@ * 16 - `_.curry` or `_.curryRight` of a bound function * 32 - `_.partial` * 64 - `_.partialRight` - * @param {number} data[2] The arity of `data[0]`. - * @param {*} [data[3]] The `this` binding of `data[0]`. - * @param {Array} [data[4]] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [data[5]] An array of `data[4]` placeholder indexes. - * @param {Array} [data[6]] An array of arguments to append to those - * provided to the new function. - * @param {Array} [data[7]] An array of `data[6]` placeholder indexes. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ - function createWrapper(data) { - var func = data[0], - bitmask = data[1]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isPartial = bitmask & PARTIAL_FLAG, - isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; - + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && !isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } - var arity = data[2], - partialArgs = data[4], - partialRightArgs = data[6]; - + var isPartial = bitmask & PARTIAL_FLAG; if (isPartial && !partialArgs.length) { + bitmask &= ~PARTIAL_FLAG; isPartial = false; - data[1] = (bitmask &= ~PARTIAL_FLAG); - data[4] = data[5] = partialArgs = null; + partialArgs = partialHolders = null; } + var isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (isPartialRight && !partialRightArgs.length) { + bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = false; - data[1] = (bitmask &= ~PARTIAL_RIGHT_FLAG); - data[6] = data[7] = partialRightArgs = null; - } - var funcData = !isBindKey && func[EXPANDO]; - if (funcData && funcData !== true) { - // shallow clone `funcData` - funcData = slice(funcData); - - // clone partial left arguments - if (funcData[4]) { - funcData[4] = slice(funcData[4]); - funcData[5] = slice(funcData[5]); - } - // clone partial right arguments - if (funcData[6]) { - funcData[6] = slice(funcData[6]); - funcData[7] = slice(funcData[7]); - } - // set arity if provided - if (typeof arity == 'number') { - funcData[2] = arity; + partialRightArgs = partialRightHolders = null; + } + var data = (data = !isBindKey && getData(func)) && data !== true && data; + if (data) { + var funcBitmask = data[1], + funcIsBind = funcBitmask & BIND_FLAG, + isBind = bitmask & BIND_FLAG; + + // use metadata `func` and merge bitmasks + func = data[0]; + bitmask |= funcBitmask; + + // use metadata `arity` if not provided + if (arity == null) { + arity = data[2]; } - // set `thisArg` if not previously bound - var bound = funcData[1] & BIND_FLAG; - if (isBind && !bound) { - funcData[3] = data[3]; + // use metadata `thisArg` if available + if (funcIsBind) { + thisArg = data[3]; } // set if currying a bound function - if (!isBind && bound) { + if (!isBind && funcIsBind) { bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments - if (isPartial) { - var funcPartialArgs = funcData[4]; - if (funcPartialArgs) { - funcPartialArgs = composeArgs(funcPartialArgs, funcData[5], partialArgs); - } - funcData[4] = funcPartialArgs || partialArgs; - funcData[5] = funcPartialArgs ? replaceHolders(funcPartialArgs, PLACEHOLDER) : data[5]; + var funcArgs = data[4]; + if (funcArgs) { + var funcHolders = data[5]; + partialArgs = isPartial ? composeArgs(funcArgs, funcHolders, partialArgs) : baseSlice(funcArgs); + partialHolders = isPartial ? replaceHolders(partialArgs, PLACEHOLDER) : baseSlice(funcHolders); } // prepend partial right arguments - if (isPartialRight) { - var funcPartialRightArgs = funcData[6]; - if (funcPartialRightArgs) { - funcPartialRightArgs = composeArgsRight(funcPartialRightArgs, funcData[7], partialRightArgs); - } - funcData[6] = funcPartialRightArgs || partialRightArgs; - funcData[7] = funcPartialRightArgs ? replaceHolders(funcPartialRightArgs, PLACEHOLDER) : data[7]; + funcArgs = data[6]; + if (funcArgs) { + funcHolders = data[7]; + partialRightArgs = isPartialRight ? composeArgsRight(funcArgs, funcHolders, partialRightArgs) : baseSlice(funcArgs); + partialRightHolders = isPartialRight ? replaceHolders(partialRightArgs, PLACEHOLDER) : baseSlice(funcHolders); } - // merge flags - funcData[1] |= bitmask; - return createWrapper(funcData); } if (arity == null) { arity = isBindKey ? 0 : func.length; } - data[2] = nativeMax(arity, 0); - return baseCreateWrapper(data); + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(func, thisArg); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { + result = createPartialWrapper(func, bitmask, partialArgs, thisArg); + } else { + result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); + } + var setter = data ? baseSetData : setData; + return setter(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); } /** @@ -2695,7 +2664,24 @@ function getCallback(func, thisArg, argCount) { var result = lodash.callback || callback; result = result === callback ? baseCallback : result; - return arguments.length ? result(func, thisArg, argCount) : result; + return argCount ? result(func, thisArg, argCount) : result; + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + function getData(func) { + return metaMap.get(func); + } + // fallback for environments without `WeakMap` + if (!WeakMap) { + getData = !defineProperty ? noop : function(func) { + return func[EXPANDO]; + }; } /** @@ -2714,29 +2700,93 @@ } /** - * Checks if `value` is an array-like object. + * Initializes an array clone. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @returns {*} Returns the initialized clone value. */ - function isArrayLike(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && - arrayLikeClasses[toString.call(value)]) || false; + function initArrayClone(array, isDeep) { + var index = -1, + length = array.length, + result = array.constructor(length); + + if (!isDeep) { + while (++index < length) { + result[index] = array[index]; + } + } + // add array properties assigned by `RegExp#exec` + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; } /** - * Checks if `value` is a native function. + * Initializes an object clone. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep=false] Specify a deep clone. + * @returns {*} Returns the initialized clone value. + */ + function initObjectClone(object, isDeep) { + var className = toString.call(object); + if (!cloneableClasses[className]) { + return object; + } + var Ctor = object.constructor, + isArgs = className == argsClass, + isObj = className == objectClass; + + if (isObj && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { + Ctor = Object; + } + if (isArgs || isObj) { + var result = isDeep ? new Ctor : baseAssign(new Ctor, object); + if (isArgs) { + result.length = object.length; + } + return result; + } + switch (className) { + case arrayBufferClass: + return bufferClone(object); + + case boolClass: + case dateClass: + return new Ctor(+object); + + case float32Class: case float64Class: + case int8Class: case int16Class: case int32Class: + case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberClass: + case stringClass: + return new Ctor(object); + + case regexpClass: + result = Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + + /** + * Checks if `value` is an array-like object. * * @private * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. */ - function isNative(value) { - var type = typeof value; - return type == 'function' - ? reNative.test(fnToString.call(value)) - : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; + function isArrayLike(value) { + return (value && typeof value == 'object' && typeof value.length == 'number' && + arrayLikeClasses[toString.call(value)]) || false; } /** @@ -2748,37 +2798,50 @@ * equality comparisons, else `false`. */ function isStrictComparable(value) { - return value === value && (value === 0 ? (1 / value > 0) : !isObject(value)); + return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value)); } /** - * Creates a clone of the given array buffer. + * A specialized version of `_.pick` that picks `object` properties + * specified by the `props` array. * * @private - * @param {ArrayBuffer} buffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. */ - function cloneBuffer(buffer) { - return bufferSlice.call(buffer, 0); - } - if (!bufferSlice) { - // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` - cloneBuffer = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + function pickByArray(object, props) { + var index = -1, + length = props.length, + result = {}; - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); + } + return result; + } + + /** + * A specialized version of `_.pick` that picks `object` properties + * the predicate returns truthy for. + * + * @private + * @param {Object} object The source object. + * @param {Function} predicate The function called per iteration. + * @returns {Object} Returns the new object. + */ + function pickByCallback(object, predicate) { + var result = {}; + + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; } - return result; - }; + }); + return result; } /** @@ -2793,31 +2856,49 @@ function replaceHolders(array, placeholder) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; - result.push(index); + result[++resIndex] = index; } } return result; } /** - * Sets wrapper metadata on a given function. + * Sets metadata for `func`. + * + * **Note**: If this function becomes hot, i.e. is called a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses. * * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = !defineProperty ? identity : function(func, value) { - descriptor.value = value; - defineProperty(func, EXPANDO, descriptor); - descriptor.value = null; - return func; - }; + var setData = (function() { + var count = 0, + lastCalled = 0; + + return function(key, value) { + var stamp = now ? now() : 0, + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count > HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }()); /** * A fallback implementation of `_.isPlainObject` which checks if `value` @@ -2883,22 +2964,23 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function sortedUniq(array, iterator) { + function sortedUniq(array, iteratee) { var seen, index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; if (!index || seen !== computed) { seen = computed; - result.push(value); + result[++resIndex] = value; } } return result; @@ -2937,7 +3019,7 @@ /*--------------------------------------------------------------------------*/ /** - * Creates an array of elements split into groups the length of `chunkSize`. + * Creates an array of elements split into groups the length of `size`. * If `collection` can't be split evenly, the final chunk will be the remaining * elements. * @@ -2945,7 +3027,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to process. - * @param {numer} [chunkSize=1] The size of each chunk. + * @param {numer} [size=1] The length of each chunk. * @returns {Array} Returns the new array containing chunks. * @example * @@ -2955,14 +3037,15 @@ * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ - function chunk(array, chunkSize) { + function chunk(array, size) { var index = 0, length = array ? array.length : 0, + resIndex = -1, result = []; - chunkSize = nativeMax(+chunkSize || 1, 1); + size = typeof size == 'undefined' ? 1 : nativeMax(+size || 1, 1); while (index < length) { - result.push(slice(array, index, (index += chunkSize))); + result[++resIndex] = slice(array, index, (index += size)); } return result; } @@ -2997,8 +3080,12 @@ } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates an array excluding all values of the provided arrays using + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3131,7 +3218,7 @@ index = length; predicate = getCallback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { } + while (index-- && predicate(array[index], index, array)) {} return slice(array, 0, index + 1); } @@ -3180,7 +3267,7 @@ length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { } + while (++index < length && predicate(array[index], index, array)) {} return slice(array, index); } @@ -3365,10 +3452,14 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, + * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, * it is used as the offset from the end of the collection. If `array` is * sorted providing `true` for `fromIndex` performs a faster binary search. * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @category Array @@ -3422,7 +3513,11 @@ /** * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3530,8 +3625,10 @@ index = sortedLastIndex(array, value) - 1; return (length && array[index] === value) ? index : -1; } + var isReflexive = value === value; while (index--) { - if (array[index] === value) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { return index; } } @@ -3539,10 +3636,14 @@ } /** - * Removes all provided values from `array` using strict equality for - * comparisons, i.e. `===`. + * Removes all provided values from `array` using `SameValueZero` for equality + * comparisons. * - * Note: Unlike `_.without`, this method mutates `array`. + * **Note:** Unlike `_.without`, this method mutates `array`. + * + * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches + * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3557,20 +3658,18 @@ * console.log(array); * // => [1, 1] */ - function pull(array) { - var argsIndex = 0, - argsLength = arguments.length, - length = array ? array.length : 0; + function pull() { + var array = arguments[0], + index = 0, + indexOf = getIndexOf(), + length = arguments.length; - while (++argsIndex < argsLength) { - var index = -1, - value = arguments[argsIndex]; + while (++index < length) { + var fromIndex = 0, + value = arguments[index]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); } } return array; @@ -3581,7 +3680,7 @@ * returns an array of the removed elements. Indexes may be specified as an * array of indexes or as individual arguments. * - * Note: Unlike `_.at`, this method mutates `array`. + * **Note:** Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ @@ -3617,7 +3716,7 @@ * returns `true` for elements that have the properties of the given object, * else `false`. * - * Note: Unlike `_.filter`, this method mutates `array`. + * **Note:** Unlike `_.filter`, this method mutates `array`. * * @static * @memberOf _ @@ -3677,7 +3776,7 @@ /** * Slices `array` from the `start` index up to, but not including, the `end` index. * - * Note: This function is used instead of `Array#slice` to support node lists + * **Note:** This function is used instead of `Array#slice` to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @static @@ -3700,6 +3799,9 @@ if (end < 0) { end += length; } + if (end && end == length && !start) { + return baseSlice(array); + } length = start > end ? 0 : (end - start); var result = Array(length); @@ -3712,14 +3814,14 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iterator function is provided it is executed for `value` - * and each element of `array` to compute their sort ranking. The iterator + * of the array. If an iteratee function is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -3728,10 +3830,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -3744,7 +3846,7 @@ * * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * - * // using an iterator function + * // using an iteratee function * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { * return this.data[word]; * }, dict); @@ -3754,9 +3856,9 @@ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ - function sortedIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : getCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator); + function sortedIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee); } /** @@ -3769,10 +3871,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -3780,9 +3882,9 @@ * _.sortedLastIndex([4, 4, 5, 5, 6, 6], 5); * // => 4 */ - function sortedLastIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : getCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator, true); + function sortedLastIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee, true); } /** @@ -3892,7 +3994,7 @@ index = length; predicate = getCallback(predicate, thisArg, 3); - while (index-- && predicate(array[index], index, array)) { } + while (index-- && predicate(array[index], index, array)) {} return slice(array, index + 1); } @@ -3941,13 +4043,17 @@ length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) { } + while (++index < length && predicate(array[index], index, array)) {} return slice(array, 0, index); } /** * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3964,30 +4070,34 @@ } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a - * faster search algorithm for sorted arrays. If an iterator function is - * provided it is executed for each value in the array to generate the criterion - * by which uniqueness is computed. The `iterator` is bound to `thisArg` and - * invoked with three arguments; (value, index, array). + * Creates a duplicate-value-free version of an array using `SameValueZero` + * for equality comparisons. Providing `true` for `isSorted` performs a faster + * search algorithm for sorted arrays. If an iteratee function is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @alias unique * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new duplicate-value-free array. * @example * @@ -3998,7 +4108,7 @@ * _.uniq([1, 1, 2], true); * // => [1, 2] * - * // using an iterator function + * // using an iteratee function * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); * // => [1, 2.5] * @@ -4006,7 +4116,7 @@ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ - function uniq(array, isSorted, iterator, thisArg) { + function uniq(array, isSorted, iteratee, thisArg) { var length = array ? array.length : 0; if (!length) { return []; @@ -4014,21 +4124,21 @@ // juggle arguments var type = typeof isSorted; if (type != 'boolean' && isSorted != null) { - thisArg = iterator; - iterator = isSorted; + thisArg = iteratee; + iteratee = isSorted; isSorted = false; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === array) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === array) { + iteratee = null; } } - if (iterator != null) { - iterator = getCallback(iterator, thisArg, 3); + if (iteratee != null) { + iteratee = getCallback(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) - ? sortedUniq(array, iterator) - : baseUniq(array, iterator); + ? sortedUniq(array, iteratee) + : baseUniq(array, iteratee); } /** @@ -4061,8 +4171,12 @@ } /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * Creates an array excluding all provided values using `SameValueZero` for + * equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4075,8 +4189,8 @@ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ - function without() { - return baseDifference(arguments[0], slice(arguments, 1)); + function without(array) { + return baseDifference(array, slice(arguments, 1)); } /** @@ -4128,7 +4242,13 @@ * // => [['fred', 30, true], ['barney', 40, false]] */ function zip() { - return unzip(arguments); + var length = arguments.length, + array = Array(length); + + while (length--) { + array[length] = arguments[length]; + } + return unzip(array); } /** @@ -4320,9 +4440,13 @@ } /** - * Checks if `value` is present in `collection` using strict equality for - * comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. + * Checks if `value` is present in `collection` using `SameValueZero` for + * equality comparisons. If `fromIndex` is negative, it is used as the offset + * from the end of the collection. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -4358,28 +4482,22 @@ } else { fromIndex = 0; } - if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { - if (fromIndex >= length) { - return false; - } - return nativeContains - ? nativeContains.call(collection, target, fromIndex) - : collection.indexOf(target, fromIndex) > -1; - } - return getIndexOf(collection, target, fromIndex) > -1; + return (typeof collection == 'string' || !isArray(collection) && isString(collection)) + ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) + : (getIndexOf(collection, target, fromIndex) > -1); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding value - * of each key is the number of times the key was returned by `iterator`. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the number of times the key was returned by `iteratee`. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4387,10 +4505,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4449,10 +4567,10 @@ * // => false */ function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arrayEvery : baseEvery; return func(collection, predicate); } @@ -4497,9 +4615,9 @@ * // => [{ 'name': 'barney', 'age': 36 }] */ function filter(collection, predicate, thisArg) { - predicate = getCallback(predicate, thisArg, 3); - var func = isArray(collection) ? arrayFilter : baseFilter; + + predicate = getCallback(predicate, thisArg, 3); return func(collection, predicate); } @@ -4607,12 +4725,12 @@ } /** - * Iterates over elements of `collection` executing `iterator` for each - * element. The `iterator` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` executing `iteratee` for each + * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * - * Note: As with other "Collections" methods, objects with a `length` property + * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * @@ -4621,8 +4739,8 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * @@ -4630,12 +4748,12 @@ * // => logs each value and returns the array * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); - * // => logs each value-key pair and returns the object (property order is not guaranteed across environments) + * // => logs each value-key pair and returns the object (property order is not guaranteed) */ - function forEach(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, iterator) - : baseEach(collection, baseCallback(iterator, thisArg, 3)); + function forEach(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, baseCallback(iteratee, thisArg, 3)); } /** @@ -4647,31 +4765,31 @@ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each value from right to left and returns the array */ - function forEachRight(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEachRight(collection, iterator) - : baseEachRight(collection, baseCallback(iterator, thisArg, 3)); + function forEachRight(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEachRight(collection, iteratee) + : baseEachRight(collection, baseCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding + * each element of `collection` through `iteratee`. The corresponding * value of each key is an array of the elements responsible for generating - * the key. The `iterator` is bound to `thisArg` and invoked with three + * the key. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4679,10 +4797,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4706,15 +4824,15 @@ /** * Creates an object composed of keys generated from the results of running - * each element of the collection through `iterator`. The corresponding value + * each element of the collection through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4722,10 +4840,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -4775,13 +4893,13 @@ /** * Creates an array of values by running each element in the collection through - * `iterator`. The `iterator` is bound to `thisArg` and invoked with three + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4790,10 +4908,10 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * @@ -4801,7 +4919,7 @@ * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) + * // => [3, 6, 9] (property order is not guaranteed) * * var characters = [ * { 'name': 'barney', 'age': 36 }, @@ -4812,24 +4930,24 @@ * _.map(characters, 'name'); * // => ['barney', 'fred'] */ - function map(collection, iterator, thisArg) { - iterator = getCallback(iterator, thisArg, 3); + function map(collection, iteratee, thisArg) { + iteratee = getCallback(iteratee, thisArg, 3); var func = isArray(collection) ? arrayMap : baseMap; - return func(collection, iterator); + return func(collection, iteratee); } /** * Retrieves the maximum value of `collection`. If the collection is empty - * or falsey `-Infinity` is returned. If an iterator function is provided it + * or falsey `-Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4837,10 +4955,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * @@ -4862,20 +4980,20 @@ * _.max(characters, 'age'); * // => { 'name': 'fred', 'age': 40 }; */ - function max(collection, iterator, thisArg) { + function max(collection, iteratee, thisArg) { var computed = -Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - var noIterator = iterator == null, - isArr = noIterator && isArray(collection), + var noIteratee = iteratee == null, + isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); - if (noIterator && !isStr) { + if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -4887,12 +5005,12 @@ } } } else { - iterator = (noIterator && isStr) + iteratee = (noIteratee && isStr) ? charAtCallback - : getCallback(iterator, thisArg, 3); + : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current > computed || (current === -Infinity && current === result)) { computed = current; result = value; @@ -4904,15 +5022,15 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty - * or falsey `Infinity` is returned. If an iterator function is provided it + * or falsey `Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -4920,10 +5038,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * @@ -4945,20 +5063,20 @@ * _.min(characters, 'age'); * // => { 'name': 'barney', 'age': 36 }; */ - function min(collection, iterator, thisArg) { + function min(collection, iteratee, thisArg) { var computed = Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - var noIterator = iterator == null, - isArr = noIterator && isArray(collection), + var noIteratee = iteratee == null, + isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); - if (noIterator && !isStr) { + if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -4970,12 +5088,12 @@ } } } else { - iterator = (noIterator && isStr) + iteratee = (noIteratee && isStr) ? charAtCallback - : getCallback(iterator, thisArg, 3); + : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current < computed || (current === Infinity && current === result)) { computed = current; result = value; @@ -5058,10 +5176,10 @@ /** * Reduces a collection to a value which is the accumulated result of running - * each element in the collection through `iterator`, where each successive + * each element in the collection through `iteratee`, where each successive * execution consumes the return value of the previous execution. If `accumulator` * is not provided the first element of the collection is used as the initial - * value. The `iterator` is bound to `thisArg`and invoked with four arguments; + * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * * @static @@ -5069,9 +5187,9 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -5082,11 +5200,11 @@ * result[key] = n * 3; * return result; * }, {}); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * // => { 'a': 3, 'b': 6, 'c': 9 } (property order is not guaranteed) */ - function reduce(collection, iterator, accumulator, thisArg) { + function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; - return func(collection, getCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEach); + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** @@ -5098,9 +5216,9 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -5108,9 +5226,9 @@ * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ - function reduceRight(collection, iterator, accumulator, thisArg) { + function reduceRight(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduceRight : baseReduce; - return func(collection, getCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** @@ -5152,8 +5270,12 @@ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); - return filter(collection, negate(predicate)); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); } /** @@ -5287,27 +5409,27 @@ * // => false */ function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arraySome : baseSome; return func(collection, predicate); } /** * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through `iterator`. This method performs + * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an array of property names is provided for `iterator` the collection + * If an array of property names is provided for `iteratee` the collection * is sorted by each property value. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -5315,10 +5437,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [iterator=identity] The function + * @param {Array|Function|Object|string} [iteratee=identity] The function * called per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. * @example * @@ -5343,28 +5465,28 @@ * _.map(_.sortBy(characters, ['name', 'age']), _.values); * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ - function sortBy(collection, iterator, thisArg) { + function sortBy(collection, iteratee, thisArg) { var index = -1, length = collection ? collection.length : 0, - multi = iterator && isArray(iterator), + multi = iteratee && isArray(iteratee), result = []; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { result.length = length; } if (!multi) { - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); } baseEach(collection, function(value, key, collection) { if (multi) { - var length = iterator.length, + var length = iteratee.length, criteria = Array(length); while (length--) { - criteria[length] = value[iterator[length]]; + criteria[length] = value == null ? undefined : value[iteratee[length]]; } } else { - criteria = iterator(value, key, collection); + criteria = iteratee(value, key, collection); } result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; }); @@ -5393,7 +5515,7 @@ function toArray(collection) { var length = collection ? collection.length : 0; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { - return slice(collection); + return baseSlice(collection); } return values(collection); } @@ -5501,7 +5623,7 @@ * and prepends any additional `bind` arguments to those provided to the bound * function. * - * Note: Unlike native `Function#bind` this method does not set the `length` + * **Note:** Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static @@ -5523,12 +5645,12 @@ */ function bind(func, thisArg) { if (arguments.length < 3) { - return createWrapper([func, BIND_FLAG, null, thisArg]); + return createWrapper(func, BIND_FLAG, null, thisArg); } var args = slice(arguments, 2), - partialHolders = replaceHolders(args, bind.placeholder); + holders = replaceHolders(args, bind.placeholder); - return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, partialHolders, thisArg); + return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, holders, thisArg); } /** @@ -5537,7 +5659,7 @@ * of method names. If no method names are provided all enumerable function * properties, own and inherited, of `object` are bound. * - * Note: This method does not set the `length` property of bound functions. + * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ @@ -5601,12 +5723,14 @@ * // => 'hiya fred!' */ function bindKey(object, key) { - var data = [key, BIND_FLAG | BIND_KEY_FLAG, null, object]; + var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (arguments.length > 2) { - var args = slice(arguments, 2); - data.push(args, replaceHolders(args, bindKey.placeholder)); + var args = slice(arguments, 2), + holders = replaceHolders(args, bindKey.placeholder); } - return createWrapper(data); + return args + ? createWrapper(key, bitmask, null, object, args, holders) + : createWrapper(key, bitmask, null, object); } /** @@ -5670,7 +5794,7 @@ * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. * - * Note: This method does not set the `length` property of curried functions. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ @@ -5703,7 +5827,7 @@ * This method is like `_.curry` except that arguments are applied to `func` * in the manner of `_.partialRight` instead of `_.partial`. * - * Note: This method does not set the `length` property of curried functions. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ @@ -5740,7 +5864,7 @@ * and/or trailing edge of the `wait` timeout. Subsequent calls to the * debounced function return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * @@ -6061,7 +6185,7 @@ * prepended to those provided to the new function. This method is similar to * `_.bind` except it does **not** alter the `this` binding. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -6079,16 +6203,16 @@ */ function partial(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partial.placeholder); + holders = replaceHolders(args, partial.placeholder); - return basePartial(func, PARTIAL_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_FLAG, args, holders); } /** * This method is like `_.partial` except that partially applied arguments * are appended to those provided to the new function. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -6117,9 +6241,9 @@ */ function partialRight(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partialRight.placeholder); + holders = replaceHolders(args, partialRight.placeholder); - return basePartial(func, PARTIAL_RIGHT_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_RIGHT_FLAG, args, holders); } /** @@ -6130,7 +6254,7 @@ * Subsequent calls to the throttled function return the result of the last * `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * @@ -6243,7 +6367,7 @@ * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -6306,7 +6430,7 @@ * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -6388,7 +6512,7 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property are ignored. * - * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * **Note:** See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. * * @static @@ -6406,7 +6530,7 @@ if (object == null) { return object; } - var args = slice(arguments); + var args = baseSlice(arguments); args.push(assignDefaults); return assign.apply(undefined, args); } @@ -6442,7 +6566,7 @@ * _.findKey(characters, function(chr) { * return chr.age < 40; * }); - * // => 'barney' (property order is not guaranteed across environments) + * // => 'barney' (property order is not guaranteed) * * // using "_.where" callback shorthand * _.findKey(characters, { 'age': 1 }); @@ -6505,7 +6629,7 @@ /** * Iterates over own and inherited enumerable properties of an object executing - * `iterator` for each property. The `iterator` is bound to `thisArg` and invoked + * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * @@ -6513,8 +6637,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6528,13 +6652,13 @@ * _.forIn(new Shape, function(value, key) { * console.log(key); * }); - * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments) + * // => logs 'x', 'y', and 'z' (property order is not guaranteed) */ - function forIn(object, iterator, thisArg) { - if (typeof iterator != 'function' || typeof thisArg != 'undefined') { - iterator = baseCallback(iterator, thisArg, 3); + function forIn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = baseCallback(iteratee, thisArg, 3); } - return baseFor(object, iterator, keysIn); + return baseFor(object, iteratee, keysIn); } /** @@ -6545,8 +6669,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6562,14 +6686,14 @@ * }); * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' */ - function forInRight(object, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); - return baseForRight(object, iterator, keysIn); + function forInRight(object, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keysIn); } /** - * Iterates over own enumerable properties of an object executing `iterator` - * for each property. The `iterator` is bound to `thisArg` and invoked with + * Iterates over own enumerable properties of an object executing `iteratee` + * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * @@ -6577,21 +6701,21 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) + * // => logs '0', '1', and 'length' (property order is not guaranteed) */ - function forOwn(object, iterator, thisArg) { - if (typeof iterator != 'function' || typeof thisArg != 'undefined') { - iterator = baseCallback(iterator, thisArg, 3); + function forOwn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = baseCallback(iteratee, thisArg, 3); } - return baseForOwn(object, iterator); + return baseForOwn(object, iteratee); } /** @@ -6602,8 +6726,8 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -6612,9 +6736,9 @@ * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ - function forOwnRight(object, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); - return baseForRight(object, iterator, keys); + function forOwnRight(object, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keys); } /** @@ -6626,14 +6750,14 @@ * @alias methods * @category Object * @param {Object} object The object to inspect. - * @returns {Array} Returns the new sorted array of property names. + * @returns {Array} Returns the new array of property names. * @example * * _.functions(_); * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - return baseFunctions(object, keysIn); + return baseFunctions(object, keysIn(object)); } /** @@ -6862,7 +6986,7 @@ * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). * - * Note: This method supports comparing arrays, booleans, `Date` objects, + * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. @@ -6925,7 +7049,7 @@ /** * Checks if `value` is a finite primitive number. * - * Note: This method is based on ES6 `Number.isFinite`. See the + * **Note:** This method is based on ES6 `Number.isFinite`. See the * [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) * for more details. * @@ -6981,7 +7105,7 @@ * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * Note: See the [ES5 spec](http://es5.github.io/#x8) for more details. + * **Note:** See the [ES5 spec](http://es5.github.io/#x8) for more details. * * @static * @memberOf _ @@ -7009,7 +7133,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which returns `true` + * **Note:** This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -7038,6 +7162,27 @@ return isNumber(value) && value != +value; } + /** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Object + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + */ + function isNative(value) { + if (isFunction(value)) { + return reNative.test(fnToString.call(value)); + } + if (value && typeof value == 'object') { + return !('constructor' in value) && isHostObject(value) + ? reNative.test(value) + : reHostCtor.test(toString.call(value)); + } + return false; + } + /** * Checks if `value` is `null`. * @@ -7061,7 +7206,7 @@ /** * Checks if `value` is classified as a `Number` primitive or object. * - * Note: To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static @@ -7090,7 +7235,7 @@ * Checks if `value` is an object created by the `Object` constructor or has * a `[[Prototype]]` of `null`. * - * Note: This method assumes objects created by the `Object` constructor + * **Note:** This method assumes objects created by the `Object` constructor * have no inherited enumerable properties. * * @static @@ -7208,7 +7353,7 @@ * Shape.prototype.z = 0; * * _.keys(new Shape); - * // => ['x', 'y'] (property order is not guaranteed across environments) + * // => ['x', 'y'] (property order is not guaranteed) */ var keys = !nativeKeys ? shimKeys : function(object) { object = toObject(object); @@ -7241,7 +7386,7 @@ * Shape.prototype.z = 0; * * _.keysIn(new Shape); - * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) + * // => ['x', 'y', 'z'] (property order is not guaranteed) */ function keysIn(object) { if (object == null) { @@ -7275,14 +7420,14 @@ /** * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through `iterator`. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * running each own enumerable property of `object` through `iteratee`. The + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, key, object). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -7290,10 +7435,10 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the new mapped object. * @example * @@ -7309,12 +7454,12 @@ * _.mapValues(characters, 'age'); * // => { 'fred': 40, 'pebbles': 1 } */ - function mapValues(object, iterator, thisArg) { + function mapValues(object, iteratee, thisArg) { var result = {}; - iterator = getCallback(iterator, thisArg, 3); + iteratee = getCallback(iteratee, thisArg, 3); baseForOwn(object, function(value, key, object) { - result[key] = iterator(value, key, object); + result[key] = iteratee(value, key, object); }); return result; } @@ -7403,11 +7548,15 @@ if (object == null) { return {}; } - if (typeof predicate == 'function') { - return basePick(object, negate(getCallback(predicate, thisArg, 3))); + var iterable = toObject(object); + if (typeof predicate != 'function') { + var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + return pickByArray(iterable, baseDifference(keysIn(iterable), props)); } - var omitProps = baseFlatten(arguments, false, false, 1); - return basePick(toObject(object), baseDifference(keysIn(object), arrayMap(omitProps, String))); + predicate = getCallback(predicate, thisArg, 3); + return pickByCallback(iterable, function(value, key, object) { + return !predicate(value, key, object); + }); } /** @@ -7422,7 +7571,7 @@ * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed) */ function pairs(object) { var index = -1, @@ -7468,18 +7617,17 @@ if (object == null) { return {}; } - return basePick(toObject(object), - typeof predicate == 'function' - ? getCallback(predicate, thisArg, 3) - : baseFlatten(arguments, false, false, 1) - ); + var iterable = toObject(object); + return typeof predicate == 'function' + ? pickByCallback(iterable, getCallback(predicate, thisArg, 3)) + : pickByArray(iterable, baseFlatten(arguments, false, false, 1)); } /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own - * enumerable properties through `iterator`, with each execution potentially - * mutating the `accumulator` object. The `iterator` is bound to `thisArg` + * enumerable properties through `iteratee`, with each execution potentially + * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. * @@ -7487,9 +7635,9 @@ * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -7506,7 +7654,7 @@ * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ - function transform(object, iterator, accumulator, thisArg) { + function transform(object, iteratee, accumulator, thisArg) { var isArr = isArrayLike(object); if (accumulator == null) { @@ -7520,10 +7668,10 @@ accumulator = baseCreate(proto); } } - if (iterator) { - iterator = getCallback(iterator, thisArg, 4); + if (iteratee) { + iteratee = getCallback(iteratee, thisArg, 4); (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { - return iterator(accumulator, value, index, object); + return iteratee(accumulator, value, index, object); }); } return accumulator; @@ -7547,7 +7695,7 @@ * Shape.prototype.z = 0; * * _.values(new Shape(2, 1)); - * // => [2, 1] (property order is not guaranteed across environments) + * // => [2, 1] (property order is not guaranteed) */ function values(object) { return baseValues(object, keys); @@ -7572,7 +7720,7 @@ * Shape.prototype.z = 0; * * _.valuesIn(new Shape(2, 1)); - * // => [2, 1, 0] (property order is not guaranteed across environments) + * // => [2, 1, 0] (property order is not guaranteed) */ function valuesIn(object) { return baseValues(object, keysIn); @@ -7663,7 +7811,7 @@ * Converts the characters "&", "<", ">", '"', and "'" in `string` to * their corresponding HTML entities. * - * Note: No other characters are escaped. To escape additional characters + * **Note:** No other characters are escaped. To escape additional characters * use a third-party library like [_he_](http://mths.be/he). * * When working with HTML you should always quote attribute values to reduce @@ -7930,7 +8078,7 @@ * properties may be accessed as free variables in the template. If a setting * object is provided it overrides `_.templateSettings` for the template. * - * Note: In the development build `_.template` utilizes sourceURLs for easier debugging. + * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * @@ -8292,7 +8440,7 @@ * `&`, `<`, `>`, `"`, and `'` in `string` to their * corresponding characters. * - * Note: No other HTML entities are unescaped. To unescape additional HTML + * **Note:** No other HTML entities are unescaped. To unescape additional HTML * entities use a third-party library like [_he_](http://mths.be/he). * * @static @@ -8350,6 +8498,7 @@ * * @static * @memberOf _ + * @alias iteratee * @category Utility * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. @@ -8466,7 +8615,7 @@ var isStrict = isStrictComparable(value); flags[index] = isStrict; - vals[index] = isStrict ? value : baseClone(value, false); + vals[index] = isStrict ? value : baseClone(value); } return function(object) { index = length; @@ -8523,16 +8672,20 @@ */ function mixin(object, source, options) { var chain = true, - methodNames = source && baseFunctions(source, keys); + isObj = isObject(source), + noOpts = options == null, + props = noOpts && isObj && keys(source), + methodNames = props && baseFunctions(source, props); - if (!source || (!options && !methodNames.length)) { - if (options == null) { + if ((props && props.length && !methodNames.length) || (noOpts && !isObj)) { + if (noOpts) { options = source; } + methodNames = false; source = object; object = this; - methodNames = baseFunctions(source, keys); } + methodNames || (methodNames = baseFunctions(source, keys(source))); if (options === false) { chain = false; } else if (isObject(options) && 'chain' in options) { @@ -8540,7 +8693,7 @@ } var index = -1, isFunc = isFunction(object), - length = methodNames ? methodNames.length : 0; + length = methodNames.length; while (++index < length) { var methodName = methodNames[index], @@ -8624,7 +8777,7 @@ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * Note: This method avoids differences in native ES3 and ES5 `parseInt` + * **Note:** This method avoids differences in native ES3 and ES5 `parseInt` * implementations. See the [ES5 spec](http://es5.github.io/#E) * for more details. * @@ -8852,16 +9005,16 @@ } /** - * Executes the iterator function `n` times, returning an array of the results - * of each execution. The `iterator` is bound to `thisArg` and invoked with + * Executes the iteratee function `n` times, returning an array of the results + * of each execution. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iterator`. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {number} n The number of times to execute `iteratee`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example * @@ -8874,18 +9027,18 @@ * _.times(3, function(n) { this.cast(n); }, mage); * // => also calls `mage.castSpell(n)` three times */ - function times(n, iterator, thisArg) { + function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; - iterator = baseCallback(iterator, thisArg, 1); + iteratee = baseCallback(iteratee, thisArg, 1); var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); while (++index < n) { if (index < MAX_ARRAY_LENGTH) { - result[index] = iterator(index); + result[index] = iteratee(index); } else { - iterator(index); + iteratee(index); } } return result; @@ -9016,6 +9169,7 @@ lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; + lodash.iteratee = callback; lodash.methods = functions; lodash.object = zipObject; lodash.select = filter; @@ -9060,6 +9214,7 @@ lodash.isFinite = isFinite; lodash.isFunction = isFunction; lodash.isNaN = isNaN; + lodash.isNative = isNative; lodash.isNull = isNull; lodash.isNumber = isNumber; lodash.isObject = isObject; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index c1771afb5c..93c5c3717c 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -3,69 +3,70 @@ * Lo-Dash 3.0.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash modern -o ./dist/lodash.js` */ -;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) -}function g(n){for(var t=-1,r=n.length;++ti(t,a)&&c.push(a);return c}function Mt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>S)return Xt(n,t);for(var e=-1,u=kr(n);++e=r||r>S)return Gt(n,t);for(var e=kr(n);r--&&false!==t(e[r],r,e););return n}function qt(n,t){var r=true;return Mt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Pt(n,t){var r=[];return Mt(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function Zt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0 -}),u}function Kt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++e>>1,a=r(n[f]),c=e?a<=t:ao(l,s)&&((t||a)&&l.push(s),c.push(p))}return c}function lr(n,t){for(var r=-1,e=t(n),u=e.length,o=Ce(u);++re)return t;var u=typeof r[2];if("number"!=u&&"string"!=u||!r[3]||r[3][r[2]]!==r[1]||(e=2),3e?vu(u+e,0):e||0;else if(e)return e=Nr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function Ur(n){return Wr(n,1)}function Wr(n,t,r){var e=-1,u=n?n.length:0;for(t=null==t?0:+t||0,0>t&&(t=-t>u?0:u+t),r=typeof r=="undefined"||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t,r=Ce(u);++er?vu(e+r,0):r||0:0,typeof n=="string"||!Cu(n)&&me(n)?ro&&(o=f);else t=i&&f?u:br(t,r,3),Mt(n,function(n,r,u){r=t(n,r,u),(r>e||-1/0===r&&r===o)&&(e=r,o=n)});return o}function Xr(n,t){return Yr(n,Se(t))}function Gr(n,t,r,e){return(Cu(n)?It:ir)(n,br(t,e,4),r,3>arguments.length,Mt)}function Hr(n,t,r,e){return(Cu(n)?Rt:ir)(n,br(t,e,4),r,3>arguments.length,zt)}function Qr(n){n=kr(n);for(var t=-1,r=n.length,e=Ce(r);++targuments.length)return _r([n,b,null,t]);var r=Wr(arguments,2),e=Or(r,re.placeholder);return er(n,b|E,r,e,t)}function ee(n,t){var r=[t,b|w,null,n];if(2=r||r>t?(f&&He(f),r=s,f=p=s=m,r&&(h=Bu(),a=n.apply(l,i),p||f||(i=l=null))):p=ou(e,r)}function u(){p&&He(p),f=p=s=m,(v||g!==t)&&(h=Bu(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=Bu(),l=this,s=v&&(p||!y),false===g)var r=y&&!p;else{f||y||(h=c);var o=g-(c-h),d=0>=o||o>g;d?(f&&(f=He(f)),h=c,a=n.apply(l,i)):f||(f=ou(u,o))}return d&&p?p=He(p):p||t===g||(p=ou(e,t)),r&&(d=true,a=n.apply(l,i)),!d||p||f||(i=l=null),a -}var i,f,a,c,l,p,s,h=0,g=false,v=true;if(!ge(n))throw new De(R);if(t=0>t?0:t,true===r)var y=true,v=false;else ve(r)&&(y=r.leading,g="maxWait"in r&&vu(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){p&&He(p),f&&He(f),f=p=s=m},o}function fe(n){if(!ge(n))throw new De(R);return function(){return!n.apply(this,arguments)}}function ae(n){var t=Wr(arguments,1),r=Or(t,ae.placeholder);return er(n,E,t,r)}function ce(n){var t=Wr(arguments,1),r=Or(t,ce.placeholder);return er(n,O,t,r)}function le(n){return Ht(n,_e) -}function pe(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ve.call(n)==tt||false}function se(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=Ce(r),f=0t||null==n||!hu(t))return r;n=Be(n);do t%2&&(r+=n),t=Qe(t/2),n+=n;while(t);return r}function Ae(n,t){return(n=null==n?"":Be(n))?null==t?n.slice(g(n),v(n)+1):(t=Be(t),n.slice(o(n,t),i(n,t)+1)):n}function xe(n){try{return n()}catch(t){return he(t)?t:Te(t)}}function Ee(n,t){return Wt(n,t)}function Oe(n){return n}function Ie(n){var t=Uu(n),r=t.length;if(1==r){var e=t[0],u=n[e];if(xr(u))return function(n){return null!=n&&u===n[e]&&tu.call(n,e)}}for(var o=r,i=Ce(r),f=Ce(r);o--;){var u=n[t[o]],a=xr(u); -i[o]=a,f[o]=a?u:Nt(u,false)}return function(n){if(o=r,null==n)return!o;for(;o--;)if(i[o]?f[o]!==n[t[o]]:!tu.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!tu.call(n,t[o]):!Qt(f[o],n[t[o]],null,true))return false;return true}}function Re(n,t,r){var e=true,u=t&&Ht(t,Uu);t&&(r||u.length)||(null==r&&(r=t),t=n,n=this,u=Ht(t,Uu)),false===r?e=false:ve(r)&&"chain"in r&&(e=r.chain),r=-1;for(var o=ge(n),i=u?u.length:0;++r--n?t.apply(this,arguments):void 0}},h.assign=Su,h.at=function(t){var r=t?t.length:0; -return typeof r=="number"&&-1t?0:t)},h.dropRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),Wr(n,0,0>t?0:t)},h.dropRightWhile=function(n,t,r){var e=n?n.length:0; -for(t=br(t,r,3);e--&&t(n[e],e,n););return Wr(n,0,e+1)},h.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=br(t,r,3);++e(s?e(s,a):i(p,a))){for(t=u;--t;){var h=o[t]; -if(0>(h?e(h,a):i(n[t],a)))continue n}s&&s.push(a),p.push(a)}return p},h.invert=function(n,t){for(var r=-1,e=Uu(n),u=e.length,o={};++rt?0:t)},h.takeRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),Wr(n,0>t?0:t)},h.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=br(t,r,3);e--&&t(n[e],e,n););return Wr(n,e+1)},h.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=br(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},h.escape=function(n){return n=null==n?"":Be(n),$.lastIndex=0,$.test(n)?n.replace($,p):n -},h.escapeRegExp=we,h.every=qr,h.find=Zr,h.findIndex=Cr,h.findKey=function(n,t,r){return t=br(t,r,3),Zt(n,t,Xt,true)},h.findLast=function(n,t,r){return t=br(t,r,3),Zt(n,t,zt)},h.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=br(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},h.findLastKey=function(n,t,r){return t=br(t,r,3),Zt(n,t,Gt,true)},h.findWhere=function(n,t){return Zr(n,Ie(t))},h.first=Fr,h.has=function(n,t){return n?tu.call(n,t):false},h.identity=Oe,h.indexOf=Tr,h.isArguments=pe,h.isArray=Cu,h.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&Ve.call(n)==et||false -},h.isDate=function(n){return n&&typeof n=="object"&&Ve.call(n)==ut||false},h.isElement=se,h.isEmpty=function(n){if(null==n)return true;var t=n.length;return typeof t=="number"&&-1r?vu(u+r,0):yu(r||0,u-1))+1;else if(r)return u=Lr(n,t)-1,e&&n[u]===t?u:-1;for(;u--;)if(n[u]===t)return u;return-1},h.max=Jr,h.min=function(n,t,r){var e=1/0,o=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,f=!(i&&Cu(n))&&me(n);if(i&&!f)for(r=-1,n=kr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},h.template=function(n,t,r){var e=h.templateSettings;t=Su({},r||t,e,Tt),n=Be(null==n?"":n),r=Su({},t.imports,e.imports,Tt); -var u,o,i=Uu(r),f=be(r),a=0;r=t.interpolate||Y;var c="__p+='";if(r=$e((t.escape||Y).source+"|"+r.source+"|"+(r===M?z:Y).source+"|"+(t.evaluate||Y).source+"|$","g"),n.replace(r,function(t,r,e,i,f,l){return e||(e=i),c+=n.slice(a,l).replace(G,s),r&&(u=true,c+="'+__e("+r+")+'"),f&&(o=true,c+="';"+f+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),a=l+t.length,t}),c+="';",(t=t.variable)||(c="with(obj){"+c+"}"),c=(o?c.replace(U,""):c).replace(W,"$1").replace(N,"$1;"),c="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}",t=xe(function(){return Ue(i,"return "+c).apply(m,f) -}),t.source=c,he(t))throw t;return t},h.trim=Ae,h.trimLeft=function(n,t){return(n=null==n?"":Be(n))?null==t?n.slice(g(n)):(t=Be(t),n.slice(o(n,t))):n},h.trimRight=function(n,t){return(n=null==n?"":Be(n))?null==t?n.slice(0,v(n)+1):(t=Be(t),n.slice(0,i(n,t)+1)):n},h.trunc=function(n,t){var r=30,e="...";if(ve(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Be(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Be(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; -if(r=n.slice(0,o),null==u)return r+e;if(de(u)){if(n.slice(o).search(u)){var i,f,a=n.slice(0,o);for(u.global||(u=$e(u.source,(q.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(a);)f=i.index;r=r.slice(0,null==f?o:f)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},Xt(h,function(n,t){var r="sample"!=t;h.prototype[t]||(h.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new V(o,u):o})}),h.VERSION=_,h.prototype.chain=function(){return this.__chain__=true,this},h.prototype.toJSON=Mr,h.prototype.toString=function(){return Be(this.__wrapped__) -},h.prototype.value=Mr,h.prototype.valueOf=Mr,H(["join","pop","shift"],function(n){var t=Me[n];h.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new V(r,n):r}}),H(["push","reverse","sort","unshift"],function(n){var t=Me[n];h.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),H(["concat","splice"],function(n){var t=Me[n];h.prototype[n]=function(){return new V(t.apply(this.__wrapped__,arguments),this.__chain__)}}),h}var m,_="3.0.0-pre",b=1,w=2,j=4,A=8,x=16,E=32,O=64,I="__lodash_"+_.replace(/[-.]/g,"_")+"__",R="Expected a function",k=Math.pow(2,32)-1,S=Math.pow(2,53)-1,C="__lodash_placeholder__",F=0,T=/^[A-Z]+$/,U=/\b__p\+='';/g,W=/\b(__p\+=)''\+/g,N=/(__e\(.*?\)|\b__t\))\+'';/g,L=/&(?:amp|lt|gt|quot|#39|#96);/g,$=/[&<>"'`]/g,B=/<%-([\s\S]+?)%>/g,D=/<%([\s\S]+?)%>/g,M=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,q=/\w*$/,P=/^\s*function[ \n\r\t]+\w/,Z=/^0[xX]/,K=/^\[object .+?Constructor\]$/,V=/[\xC0-\xFF]/g,Y=/($^)/,J=/[.*+?^${}()|[\]\/\\]/g,X=/\bthis\b/,G=/['\n\r\u2028\u2029\\]/g,H=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,Q=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",nt="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array window WinRTError".split(" "),tt="[object Arguments]",rt="[object Array]",et="[object Boolean]",ut="[object Date]",ot="[object Error]",it="[object Number]",ft="[object Object]",at="[object RegExp]",ct="[object String]",lt="[object ArrayBuffer]",pt="[object Float32Array]",st="[object Float64Array]",ht="[object Int8Array]",gt="[object Int16Array]",vt="[object Int32Array]",yt="[object Uint8Array]",dt="[object Uint8ClampedArray]",mt="[object Uint16Array]",_t="[object Uint32Array]",bt={}; -bt[tt]=bt[rt]=bt[pt]=bt[st]=bt[ht]=bt[gt]=bt[vt]=bt[yt]=bt[dt]=bt[mt]=bt[_t]=true,bt[lt]=bt[et]=bt[ut]=bt[ot]=bt["[object Function]"]=bt["[object Map]"]=bt[it]=bt[ft]=bt[at]=bt["[object Set]"]=bt[ct]=bt["[object WeakMap]"]=false;var wt={};wt[tt]=wt[rt]=wt[lt]=wt[et]=wt[ut]=wt[pt]=wt[st]=wt[ht]=wt[gt]=wt[vt]=wt[it]=wt[ft]=wt[at]=wt[ct]=wt[yt]=wt[dt]=wt[mt]=wt[_t]=true,wt[ot]=wt["[object Function]"]=wt["[object Map]"]=wt["[object Set]"]=wt["[object WeakMap]"]=false;var jt={leading:false,maxWait:0,trailing:false},At={configurable:false,enumerable:false,value:null,writable:false},xt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Et={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ot={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},It={"function":true,object:true},Rt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},kt=It[typeof window]&&window||this,St=It[typeof exports]&&exports&&!exports.nodeType&&exports,It=It[typeof module]&&module&&!module.nodeType&&module,Ct=St&&It&&typeof global=="object"&&global; -!Ct||Ct.global!==Ct&&Ct.window!==Ct&&Ct.self!==Ct||(kt=Ct);var Ct=It&&It.exports===St&&St,Ft=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(kt._=Ft, define(function(){return Ft})):St&&It?Ct?(It.exports=Ft)._=Ft:St._=Ft:kt._=Ft}).call(this); \ No newline at end of file +;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) +}function v(n){for(var t=-1,r=n.length;++ti(t,a)&&c.push(a);return c}function qt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>T)return Gt(n,t); +for(var e=-1,u=Nr(n);++e=r||r>T)return Qt(n,t);for(var e=Nr(n);r--&&false!==t(e[r],r,e););return n}function Zt(n,t){var r=true;return qt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Kt(n,t){var r=[];return qt(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function Vt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function Yt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++e>>1,a=r(n[f]),c=e?a<=t:ao(l,s)&&((t||a)&&l.push(s),c.push(p))}return c}function sr(n,t){for(var r=-1,e=t(n),u=e.length,o=Be(u);++rt)return r; +var e=typeof arguments[2];if("number"!=e&&"string"!=e||!arguments[3]||arguments[3][arguments[2]]!==arguments[1]||(t=2),3e?ju(u+e,0):e||0;else if(e)return e=qr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function Mr(n){return zr(n,1) +}function zr(n,t,r){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),r=typeof r=="undefined"||r>o?o:+r||0,0>r&&(r+=o),r&&r==o&&!t)return e(n);for(o=t>r?0:r-t,r=Be(o);++ur?ju(e+r,0):r||0:0,typeof n=="string"||!Bu(n)&&Oe(n)?ru&&(u=f);else t=i&&f?o:xr(t,r,3),qt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function ee(n,t){return te(n,$e(t))}function ue(n,t,r,e){return(Bu(n)?St:fr)(n,xr(t,e,4),r,3>arguments.length,qt)}function oe(n,t,r,e){return(Bu(n)?Ct:fr)(n,xr(t,e,4),r,3>arguments.length,Pt) +}function ie(n){n=Nr(n);for(var t=-1,r=n.length,e=Be(r);++targuments.length)return Ar(n,w,null,t);var r=zr(arguments,2),e=Tr(r,ce.placeholder);return or(n,w|E,r,e,t)}function le(n,t){var r=w|j;if(2=r||r>t?(f&&iu(f),r=s,f=p=s=_,r&&(h=Vu(),a=n.apply(l,i),p||f||(i=l=null))):p=su(e,r)}function u(){p&&iu(p),f=p=s=_,(v||g!==t)&&(h=Vu(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=Vu(),l=this,s=v&&(p||!y),false===g)var r=y&&!p;else{f||y||(h=c);var o=g-(c-h),d=0>=o||o>g; +d?(f&&(f=iu(f)),h=c,a=n.apply(l,i)):f||(f=su(u,o))}return d&&p?p=iu(p):p||t===g||(p=su(e,t)),r&&(d=true,a=n.apply(l,i)),!d||p||f||(i=l=null),a}var i,f,a,c,l,p,s,h=0,g=false,v=true;if(!be(n))throw new Ye(C);if(t=0>t?0:t,true===r)var y=true,v=false;else we(r)&&(y=r.leading,g="maxWait"in r&&ju(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){p&&iu(p),f&&iu(f),f=p=s=_},o}function ge(n){var t=zr(arguments,1),r=Tr(t,ge.placeholder);return or(n,E,t,r)}function ve(n){var t=zr(arguments,1),r=Tr(t,ve.placeholder); +return or(n,I,t,r)}function ye(n){return nr(n,Ee(n))}function de(n){return n&&typeof n=="object"&&typeof n.length=="number"&&tu.call(n)==ut||false}function me(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=Be(r),f=0t||null==n||!bu(t))return r;n=Ve(n);do t%2&&(r+=n),t=fu(t/2),n+=n;while(t);return r}function Se(n,t){return(n=null==n?"":Ve(n))?null==t?n.slice(v(n),y(n)+1):(t=Ve(t),n.slice(i(n,t),f(n,t)+1)):n}function Ce(n){try{return n()}catch(t){return _e(t)?t:Me(t)}}function Fe(n,t){return $t(n,t)}function Te(n){return n}function Ue(n){var t=zu(n),r=t.length; +if(1==r){var e=t[0],u=n[e];if(Sr(u))return function(n){return null!=n&&u===n[e]&&Qe.call(n,e)}}for(var o=r,i=Be(r),f=Be(r);o--;){var u=n[t[o]],a=Sr(u);i[o]=a,f[o]=a?u:Bt(u)}return function(n){if(o=r,null==n)return!o;for(;o--;)if(i[o]?f[o]!==n[t[o]]:!Qe.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!Qe.call(n,t[o]):!tr(f[o],n[t[o]],null,true))return false;return true}}function We(n,t,r){var e=true,u=we(t),o=null==r,i=o&&u&&zu(t),f=i&&nr(t,i);(i&&i.length&&!f.length||o&&!u)&&(o&&(r=t),f=false,t=n,n=this),f||(f=nr(t,zu(t))),false===r?e=false:we(r)&&"chain"in r&&(e=r.chain),r=-1,u=be(n); +for(o=f.length;++rk)return r}else n=0;return ar(r,e)}}(),Tu=yr(function(n,t,r){Qe.call(n,r)?++n[r]:n[r]=1}),Uu=yr(function(n,t,r){Qe.call(n,r)?n[r].push(t):n[r]=[t]}),Wu=yr(function(n,t,r){n[r]=t +}),Nu=yr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Lu=ge(ae,2),$u=dr(Lt),Bu=_u||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&tu.call(n)==ot||false};Su.dom||(me=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!Mu(n)||false});var Du=Ou||function(n){return typeof n=="number"&&bu(n)},Mu=au?function(n){if(!n||tu.call(n)!=lt)return false;var t=n.valueOf,r=je(t)&&(r=au(t))&&au(r);return r?n==r||au(n)==r:Ur(n)}:Ur,zu=wu?function(n){n=Lr(n);var t=n.constructor,r=n.length; +return t&&n===t.prototype||typeof r=="number"&&0--n?t.apply(this,arguments):void 0}},g.assign=$u,g.at=function(t){var r=t?t.length:0;return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),zr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--&&t(n[e],e,n););return zr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=xr(t,r,3);++e(s?u(s,a):i(p,a))){for(t=e;--t;){var h=o[t];if(0>(h?u(h,a):i(n[t],a)))continue n}s&&s.push(a),p.push(a)}return p},g.invert=function(n,t){for(var r=-1,e=zu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),zr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--&&t(n[e],e,n););return zr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=xr(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Ve(n),M.lastIndex=0,M.test(n)?n.replace(M,s):n},g.escapeRegExp=ke,g.every=Jr,g.find=Gr,g.findIndex=$r,g.findKey=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Gt,true)},g.findLast=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Pt)},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--;)if(t(n[e],e,n))return e; +return-1},g.findLastKey=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Qt,true)},g.findWhere=function(n,t){return Gr(n,Ue(t))},g.first=Br,g.has=function(n,t){return n?Qe.call(n,t):false},g.identity=Te,g.indexOf=Dr,g.isArguments=de,g.isArray=Bu,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&tu.call(n)==it||false},g.isDate=function(n){return n&&typeof n=="object"&&tu.call(n)==ft||false},g.isElement=me,g.isEmpty=function(n){if(null==n)return true;var t=n.length;return typeof t=="number"&&-1r?ju(u+r,0):Au(r||0,u-1))+1; +else if(r)return u=Pr(n,t)-1,e&&n[u]===t?u:-1;for(r=t===t;u--;)if(e=n[u],r?e===t:e!==e)return u;return-1},g.max=re,g.min=function(n,t,r){var e=1/0,u=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,f=!(i&&Bu(n))&&Oe(n);if(i&&!f)for(r=-1,n=Nr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=$u({},r||t,e,Nt),n=Ve(null==n?"":n),r=$u({},t.imports,e.imports,Nt); +var u,o,i=zu(r),f=Ie(r),a=0;r=t.interpolate||X;var c="__p+='";if(r=Ke((t.escape||X).source+"|"+r.source+"|"+(r===P?Z:X).source+"|"+(t.evaluate||X).source+"|$","g"),n.replace(r,function(t,r,e,i,f,l){return e||(e=i),c+=n.slice(a,l).replace(nt,h),r&&(u=true,c+="'+__e("+r+")+'"),f&&(o=true,c+="';"+f+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),a=l+t.length,t}),c+="';",(t=t.variable)||(c="with(obj){"+c+"}"),c=(o?c.replace(L,""):c).replace($,"$1").replace(B,"$1;"),c="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}",t=Ce(function(){return ze(i,"return "+c).apply(_,f) +}),t.source=c,_e(t))throw t;return t},g.trim=Se,g.trimLeft=function(n,t){return(n=null==n?"":Ve(n))?null==t?n.slice(v(n)):(t=Ve(t),n.slice(i(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Ve(n))?null==t?n.slice(0,y(n)+1):(t=Ve(t),n.slice(0,f(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(we(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Ve(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Ve(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; +if(r=n.slice(0,o),null==u)return r+e;if(xe(u)){if(n.slice(o).search(u)){var i,f,a=n.slice(0,o);for(u.global||(u=Ke(u.source,(K.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(a);)f=i.index;r=r.slice(0,null==f?o:f)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},Gt(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=Yr,g.prototype.toString=function(){return Ve(this.__wrapped__) +},g.prototype.value=Yr,g.prototype.valueOf=Yr,tt(["join","pop","shift"],function(n){var t=He[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),tt(["push","reverse","sort","unshift"],function(n){var t=He[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),tt(["concat","splice"],function(n){var t=He[n];g.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,O=16,E=32,I=64,k=150,R=16,S="__lodash_"+b.replace(/[-.]/g,"_")+"__",C="Expected a function",F=Math.pow(2,32)-1,T=Math.pow(2,53)-1,U="__lodash_placeholder__",W=0,N=/^[A-Z]+$/,L=/\b__p\+='';/g,$=/\b(__p\+=)''\+/g,B=/(__e\(.*?\)|\b__t\))\+'';/g,D=/&(?:amp|lt|gt|quot|#39|#96);/g,M=/[&<>"'`]/g,z=/<%-([\s\S]+?)%>/g,q=/<%([\s\S]+?)%>/g,P=/<%=([\s\S]+?)%>/g,Z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,Y=/^0[xX]/,H=/^\[object .+?Constructor\]$/,J=/[\xC0-\xFF]/g,X=/($^)/,G=/[.*+?^${}()|[\]\/\\]/g,Q=/\bthis\b/,nt=/['\n\r\u2028\u2029\\]/g,tt=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,rt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",et="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),ut="[object Arguments]",ot="[object Array]",it="[object Boolean]",ft="[object Date]",at="[object Error]",ct="[object Number]",lt="[object Object]",pt="[object RegExp]",st="[object String]",ht="[object ArrayBuffer]",gt="[object Float32Array]",vt="[object Float64Array]",yt="[object Int8Array]",dt="[object Int16Array]",mt="[object Int32Array]",_t="[object Uint8Array]",bt="[object Uint8ClampedArray]",wt="[object Uint16Array]",jt="[object Uint32Array]",At={}; +At[ut]=At[ot]=At[gt]=At[vt]=At[yt]=At[dt]=At[mt]=At[_t]=At[bt]=At[wt]=At[jt]=true,At[ht]=At[it]=At[ft]=At[at]=At["[object Function]"]=At["[object Map]"]=At[ct]=At[lt]=At[pt]=At["[object Set]"]=At[st]=At["[object WeakMap]"]=false;var xt={};xt[ut]=xt[ot]=xt[ht]=xt[it]=xt[ft]=xt[gt]=xt[vt]=xt[yt]=xt[dt]=xt[mt]=xt[ct]=xt[lt]=xt[pt]=xt[st]=xt[_t]=xt[bt]=xt[wt]=xt[jt]=true,xt[at]=xt["[object Function]"]=xt["[object Map]"]=xt["[object Set]"]=xt["[object WeakMap]"]=false;var Ot={leading:false,maxWait:0,trailing:false},Et={configurable:false,enumerable:false,value:null,writable:false},It={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},kt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Rt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},St={"function":true,object:true},Ct={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ft=St[typeof window]&&window||this,Tt=St[typeof exports]&&exports&&!exports.nodeType&&exports,St=St[typeof module]&&module&&!module.nodeType&&module,Ut=Tt&&St&&typeof global=="object"&&global; +!Ut||Ut.global!==Ut&&Ut.window!==Ut&&Ut.self!==Ut||(Ft=Ut);var Ut=St&&St.exports===Tt&&Tt,Wt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ft._=Wt, define(function(){return Wt})):Tt&&St?Ut?(St.exports=Wt)._=Wt:Tt._=Wt:Ft._=Wt}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index 13ced1ca4d..d1a8226434 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -21,8 +21,7 @@ CURRY_FLAG = 4, CURRY_RIGHT_FLAG = 8, CURRY_BOUND_FLAG = 16, - PARTIAL_FLAG = 32, - PARTIAL_RIGHT_FLAG = 64; + PARTIAL_FLAG = 32; /** Used as the property name for wrapper metadata */ var EXPANDO = '__lodash_' + VERSION.replace(/[-.]/g, '_') + '__'; @@ -118,7 +117,7 @@ /** * Used to convert characters to HTML entities. * - * Note: Though the ">" character is escaped for symmetry, characters like + * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) @@ -219,13 +218,33 @@ length = array ? array.length : 0; while (++index < length) { - if (array[index] === value) { + var other = array[index]; + if (other === value) { return index; } } return -1; } + /** + * The base implementation of `_.slice` without support for `start` and `end` + * arguments. + * + * @private + * @param {Array} array The array to slice. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = array[index]; + } + return result; + } + /** * Used by `_.sortBy` to compare transformed elements of `collection` and stable * sort them in ascending order. @@ -282,6 +301,9 @@ /** 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 restore the original `_` reference in `_.noConflict` */ var oldDash = root._; @@ -297,7 +319,6 @@ /** Native method references */ var ceil = Math.ceil, floor = Math.floor, - hasOwnProperty = objectProto.hasOwnProperty, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice; @@ -343,17 +364,17 @@ * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, - * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, - * `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, - * `isString`, `isUndefined`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, - * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, - * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, - * `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, - * `unescape`, `uniqueId`, and `value` + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, + * `lastIndexOf`, `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, + * `padRight`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, + * `result`, `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, + * `sortedLastIndex`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `unescape`, `uniqueId`, and `value` * * The wrapper function `sample` will return a wrapped value when `n` is * provided, otherwise it will return an unwrapped value. @@ -428,6 +449,18 @@ * @type boolean */ support.spliceObjects = (splice.call(object, 0, 1), !object[0]); + + /** + * Detect if the host objects are detectable (IE < 9). + * + * @memberOf _.support + * @type boolean + */ + try { + support.hostObject = !({ 'toString': 0 } + ''); + } catch(e) { + support.hostObject = false; + } }(0, 0)); /** @@ -482,15 +515,15 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns `array`. */ - function arrayEach(array, iterator) { + function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { - if (iterator(array[index], index, array) === breakIndicator) { + if (iteratee(array[index], index, array) === breakIndicator) { break; } } @@ -525,16 +558,16 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function arrayMap(array, iterator) { + function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { - result[index] = iterator(array[index], index, array); + result[index] = iteratee(array[index], index, array); } return result; } @@ -551,12 +584,13 @@ function arrayFilter(array, predicate) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { - result.push(value); + result[++resIndex] = value; } } return result; @@ -568,13 +602,13 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduce(array, iterator, accumulator, initFromArray) { + function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; @@ -582,7 +616,7 @@ accumulator = array[++index]; } while (++index < length) { - accumulator = iterator(accumulator, array[index], index, array); + accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } @@ -593,20 +627,20 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduceRight(array, iterator, accumulator, initFromArray) { + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { var length = array.length; if (initFromArray && length) { accumulator = array[--length]; } while (length--) { - accumulator = iterator(accumulator, array[length], length, array); + accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } @@ -648,7 +682,7 @@ while (++index < length) { var key = methodNames[index]; - object[key] = createWrapper([object[key], BIND_FLAG, null, object]); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -721,56 +755,6 @@ }()); } - /** - * The base implementation of `createWrapper` which creates the wrapper and - * sets its metadata. - * - * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(data) { - var bitmask = data[1]; - if (bitmask == BIND_FLAG) { - return createBindWrapper(data); - } - var partialHolders = data[5]; - if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { - return createPartialWrapper(data); - } - var func = data[0], - arity = data[2], - thisArg = data[3], - partialArgs = data[4], - partialRightArgs = data[6]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryRight = bitmask & CURRY_RIGHT_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG; - - var Ctor = !isBindKey && createCtorWrapper(func), - key = func; - - var wrapper = function() { - var length = arguments.length, - index = length, - args = Array(length); - - while (index--) { - args[index] = arguments[index]; - } - if (partialArgs) { - args = composeArgs(partialArgs, partialHolders, args); - } - var thisBinding = isBind ? thisArg : this; - return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); - }; - - return wrapper; - } - /** * The base implementation of `_.difference` which accepts a single array * of values to exclude. @@ -804,19 +788,19 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEach(collection, iterator) { + function baseEach(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwn(collection, iterator); + return baseForOwn(collection, iteratee); } var index = -1, iterable = toIterable(collection); while (++index < length) { - if (iterator(iterable[index], index, iterable) === breakIndicator) { + if (iteratee(iterable[index], index, iterable) === breakIndicator) { break; } } @@ -829,17 +813,17 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEachRight(collection, iterator) { + function baseEachRight(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { - return baseForOwnRight(collection, iterator); + return baseForOwnRight(collection, iteratee); } var iterable = toIterable(collection); while (length--) { - if (iterator(iterable[length], length, iterable) === breakIndicator) { + if (iteratee(iterable[length], length, iterable) === breakIndicator) { break; } } @@ -953,24 +937,24 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iterator` for + * over `object` properties returned by `keysFunc` executing `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseFor(object, iterator, keysFunc) { + function baseFor(object, iteratee, keysFunc) { var index = -1, props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; - if (iterator(object[key], key, object) === breakIndicator) { + if (iteratee(object[key], key, object) === breakIndicator) { break; } } @@ -983,17 +967,17 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForRight(object, iterator, keysFunc) { + function baseForRight(object, iteratee, keysFunc) { var props = keysFunc(object), length = props.length; while (length--) { var key = props[length]; - if (iterator(object[key], key, object) === breakIndicator) { + if (iteratee(object[key], key, object) === breakIndicator) { break; } } @@ -1006,11 +990,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForIn(object, iterator) { - return baseFor(object, iterator, keysIn); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); } /** @@ -1019,11 +1003,11 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwn(object, iterator) { - return baseFor(object, iterator, keys); + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); } /** @@ -1032,32 +1016,32 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Object} Returns `object`. */ - function baseForOwnRight(object, iterator) { - return baseForRight(object, iterator, keys); + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); } /** - * The base implementation of `_.functions` which creates an array of function - * property names from those returned by `keysFunc`. + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. * * @private * @param {Object} object The object to inspect. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Array} Returns the new sorted array of property names. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. */ - function baseFunctions(object, keysFunc) { + function baseFunctions(object, props) { var index = -1, - props = keysFunc(object), length = props.length, + resIndex = -1, result = []; while (++index < length) { var key = props[index]; if (isFunction(object[key])) { - result.push(key); + result[++resIndex] = key; } } return result; @@ -1215,14 +1199,14 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @returns {Array} Returns the new mapped array. */ - function baseMap(collection, iterator) { + function baseMap(collection, iteratee) { var result = []; baseEach(collection, function(value, key, collection) { - result.push(iterator(value, key, collection)); + result.push(iteratee(value, key, collection)); }); return result; } @@ -1241,51 +1225,13 @@ */ function basePartial(func, bitmask, args, holders, thisArg) { if (func) { - var data = func[EXPANDO], - arity = data ? data[2] : func.length; + var arity = func.length; arity -= args.length; } - var isPartial = bitmask & PARTIAL_FLAG, - newData = [func, bitmask, arity, thisArg, null, null]; - - newData[isPartial ? 4 : 6] = args; - newData[isPartial ? 5 : 7] = holders; - return createWrapper(newData); - } - - /** - * The base implementation of `_.pick` without support for `this` binding - * and individual property name arguments. - * - * @private - * @param {Object} object The source object. - * @param {Function|string[]} predicate The function called per iteration or - * property names to pick. - * @returns {Object} Returns the new object. - */ - function basePick(object, predicate) { - var result = {}; - - if (typeof predicate == 'function') { - baseForIn(object, function(value, key, object) { - if (predicate(value, key, object)) { - result[key] = value; - } - }); - return result; - } - var index = -1, - props = predicate, - length = props.length; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - return result; + return (bitmask & PARTIAL_FLAG) + ? createWrapper(func, bitmask, arity, thisArg, args, holders) + : createWrapper(func, bitmask, arity, thisArg, null, null, args, holders); } /** @@ -1308,18 +1254,18 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ - function baseReduce(collection, iterator, accumulator, initFromCollection, eachFunc) { + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) - : iterator(accumulator, value, index, collection) + : iteratee(accumulator, value, index, collection) }); return accumulator; } @@ -1351,24 +1297,24 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iterator The function called per iteration. + * @param {Function} iteratee The function called per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ - function baseSortedIndex(array, value, iterator, retHighest) { + function baseSortedIndex(array, value, iteratee, retHighest) { var low = 0, high = array ? array.length : low; - value = iterator(value); + value = iteratee(value); var hintNum = typeof value == 'number' || (value != null && isFunction(value.valueOf) && typeof value.valueOf() == 'number'); while (low < high) { var mid = (low + high) >>> 1, - computed = iterator(array[mid]), - setLow = retHighest ? computed <= value : computed < value; + computed = iteratee(array[mid]), + setLow = retHighest ? (computed <= value) : (computed < value); if (hintNum && typeof computed != 'undefined') { computed = +computed; @@ -1389,22 +1335,22 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function baseUniq(array, iterator) { + function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), length = array.length, result = [], - seen = iterator ? [] : result; + seen = iteratee ? [] : result; while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; if (indexOf(seen, computed) < 0) { - if (iterator) { + if (iteratee) { seen.push(computed); } result.push(value); @@ -1468,7 +1414,7 @@ /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection - * through `iterator`. The given setter function sets the keys and values of + * through `iteratee`. The given setter function sets the keys and values of * the accumulator object. If `initializer` is provided it is used to initialize * the accumulator object. * @@ -1478,9 +1424,9 @@ * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { - return function(collection, iterator, thisArg) { + return function(collection, iteratee, thisArg) { var result = initializer ? initializer() : {}; - iterator = baseCallback(iterator, thisArg, 3); + iteratee = baseCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, @@ -1488,11 +1434,11 @@ while (++index < length) { var value = collection[index]; - setter(result, value, iterator(value, index, collection), collection); + setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { - setter(result, value, iterator(value, key, collection), collection); + setter(result, value, iteratee(value, key, collection), collection); }); } return result; @@ -1500,17 +1446,16 @@ } /** - * Creates a function that invokes the function specified in the metadata - * with its associated `this` binding. + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new bound function. + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. */ - function createBindWrapper(data) { - var func = data[0], - thisArg = data[3], - Ctor = createCtorWrapper(func); + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); function wrapper() { return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); @@ -1538,25 +1483,67 @@ } /** - * Creates a function that invokes the function specified in the metadata - * with its associated partially applied arguments and optional `this` binding. + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. * * @private - * @param {Array} data The metadata array. See `createWrapper` for more details. - * @returns {Function} Returns the new bound function. + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. + * @returns {Function} Returns the new function. */ - function createPartialWrapper(data) { - var func = data[0], - thisArg = data[3], - partialArgs = data[4]; + function createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG; + + var Ctor = !isBindKey && createCtorWrapper(func), + key = func; + + function wrapper() { + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partialArgs) { + args = composeArgs(partialArgs, partialHolders, args); + } + var thisBinding = isBind ? thisArg : this; + return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); + } + return wrapper; + } - var isBind = data[1] & BIND_FLAG, + /** + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partialArgs` prepended to those provided to + * the wrapper. + * + * @private + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {Array} partialArgs An array of arguments to prepend to those provided to the new function. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new bound function. + */ + function createPartialWrapper(func, bitmask, partialArgs, thisArg) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` - var argsIndex = 0, + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partialArgs.length, @@ -1566,7 +1553,7 @@ args[leftIndex] = partialArgs[leftIndex]; } while (argsLength--) { - args[leftIndex++] = arguments[argsIndex++]; + args[leftIndex++] = arguments[++argsIndex]; } return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); } @@ -1578,9 +1565,8 @@ * `this` binding and partially applied arguments. * * @private - * @param {Array} data The metadata array. - * @param {Function|string} data[0] The function or method name to reference. - * @param {number} data[1] The bitmask of flags to compose. + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` @@ -1589,42 +1575,36 @@ * 16 - `_.curry` or `_.curryRight` of a bound function * 32 - `_.partial` * 64 - `_.partialRight` - * @param {number} data[2] The arity of `data[0]`. - * @param {*} [data[3]] The `this` binding of `data[0]`. - * @param {Array} [data[4]] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [data[5]] An array of `data[4]` placeholder indexes. - * @param {Array} [data[6]] An array of arguments to append to those - * provided to the new function. - * @param {Array} [data[7]] An array of `data[6]` placeholder indexes. + * @param {number} arity The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partialArgs] An array of arguments to prepend to those provided to the new function. + * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. + * @param {Array} [partialRightArgs] An array of arguments to append to those provided to the new function. + * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ - function createWrapper(data) { - var func = data[0], - bitmask = data[1]; - - var isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isPartial = bitmask & PARTIAL_FLAG, - isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; - + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { + var isBindKey = bitmask & BIND_KEY_FLAG; if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } - var arity = data[2], - partialArgs = data[4], - partialRightArgs = data[6]; - + var isPartial = bitmask & PARTIAL_FLAG; if (isPartial && !partialArgs.length) { + bitmask &= ~PARTIAL_FLAG; isPartial = false; - data[1] = (bitmask &= ~PARTIAL_FLAG); - data[4] = data[5] = partialArgs = null; + partialArgs = partialHolders = null; } if (arity == null) { - arity = isBindKey ? 0 : func.length; + arity = func.length; + } + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(func, thisArg); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { + result = createPartialWrapper(func, bitmask, partialArgs, thisArg); + } else { + result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); } - data[2] = nativeMax(arity, 0); - return baseCreateWrapper(data); + return result; } /** @@ -1643,17 +1623,46 @@ } /** - * Checks if `value` is a native function. + * A specialized version of `_.pick` that picks `object` properties + * specified by the `props` array. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. */ - function isNative(value) { - var type = typeof value; - return type == 'function' - ? reNative.test(fnToString.call(value)) - : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; + function pickByArray(object, props) { + var index = -1, + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + + /** + * A specialized version of `_.pick` that picks `object` properties + * the predicate returns truthy for. + * + * @private + * @param {Object} object The source object. + * @param {Function} predicate The function called per iteration. + * @returns {Object} Returns the new object. + */ + function pickByCallback(object, predicate) { + var result = {}; + + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; } /** @@ -1668,12 +1677,13 @@ function replaceHolders(array, placeholder) { var index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; - result.push(index); + result[++resIndex] = index; } } return result; @@ -1708,22 +1718,23 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iterator] The function called per iteration. + * @param {Function} [iteratee] The function called per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ - function sortedUniq(array, iterator) { + function sortedUniq(array, iteratee) { var seen, index = -1, length = array.length, + resIndex = -1, result = []; while (++index < length) { var value = array[index], - computed = iterator ? iterator(value, index, array) : value; + computed = iteratee ? iteratee(value, index, array) : value; if (!index || seen !== computed) { seen = computed; - result.push(value); + result[++resIndex] = value; } } return result; @@ -1791,8 +1802,12 @@ } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates an array excluding all values of the provided arrays using + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -1958,10 +1973,14 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, + * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, * it is used as the offset from the end of the collection. If `array` is * sorted providing `true` for `fromIndex` performs a faster binary search. * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @category Array @@ -2019,7 +2038,11 @@ /** * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -2120,7 +2143,8 @@ index = (fromIndex < 0 ? nativeMax(index + fromIndex, 0) : nativeMin(fromIndex || 0, index - 1)) + 1; } while (index--) { - if (array[index] === value) { + var other = array[index]; + if (other === value) { return index; } } @@ -2153,7 +2177,7 @@ /** * Slices `array` from the `start` index up to, but not including, the `end` index. * - * Note: This function is used instead of `Array#slice` to support node lists + * **Note:** This function is used instead of `Array#slice` to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @static @@ -2176,6 +2200,9 @@ if (end < 0) { end += length; } + if (end && end == length && !start) { + return baseSlice(array); + } length = start > end ? 0 : (end - start); var result = Array(length); @@ -2188,14 +2215,14 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iterator function is provided it is executed for `value` - * and each element of `array` to compute their sort ranking. The iterator + * of the array. If an iteratee function is provided it is executed for `value` + * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -2204,10 +2231,10 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example @@ -2220,7 +2247,7 @@ * * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * - * // using an iterator function + * // using an iteratee function * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { * return this.data[word]; * }, dict); @@ -2230,9 +2257,9 @@ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ - function sortedIndex(array, value, iterator, thisArg) { - iterator = iterator == null ? identity : baseCallback(iterator, thisArg, 1); - return baseSortedIndex(array, value, iterator); + function sortedIndex(array, value, iteratee, thisArg) { + iteratee = iteratee == null ? identity : baseCallback(iteratee, thisArg, 1); + return baseSortedIndex(array, value, iteratee); } /** @@ -2264,7 +2291,11 @@ /** * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -2281,30 +2312,34 @@ } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. Providing `true` for `isSorted` performs a - * faster search algorithm for sorted arrays. If an iterator function is - * provided it is executed for each value in the array to generate the criterion - * by which uniqueness is computed. The `iterator` is bound to `thisArg` and - * invoked with three arguments; (value, index, array). + * Creates a duplicate-value-free version of an array using `SameValueZero` + * for equality comparisons. Providing `true` for `isSorted` performs a faster + * search algorithm for sorted arrays. If an iteratee function is provided it + * is executed for each value in the array to generate the criterion by which + * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, index, array). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * * @static * @memberOf _ * @alias unique * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new duplicate-value-free array. * @example * @@ -2315,7 +2350,7 @@ * _.uniq([1, 1, 2], true); * // => [1, 2] * - * // using an iterator function + * // using an iteratee function * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); * // => [1, 2.5] * @@ -2323,7 +2358,7 @@ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ - function uniq(array, isSorted, iterator, thisArg) { + function uniq(array, isSorted, iteratee, thisArg) { var length = array ? array.length : 0; if (!length) { return []; @@ -2331,21 +2366,21 @@ // juggle arguments var type = typeof isSorted; if (type != 'boolean' && isSorted != null) { - thisArg = iterator; - iterator = isSorted; + thisArg = iteratee; + iteratee = isSorted; isSorted = false; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === array) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === array) { + iteratee = null; } } - if (iterator != null) { - iterator = baseCallback(iterator, thisArg, 3); + if (iteratee != null) { + iteratee = baseCallback(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) - ? sortedUniq(array, iterator) - : baseUniq(array, iterator); + ? sortedUniq(array, iteratee) + : baseUniq(array, iteratee); } /** @@ -2378,8 +2413,12 @@ } /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * Creates an array excluding all provided values using `SameValueZero` for + * equality comparisons. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -2392,8 +2431,8 @@ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ - function without() { - return baseDifference(arguments[0], slice(arguments, 1)); + function without(array) { + return baseDifference(array, slice(arguments, 1)); } /** @@ -2412,7 +2451,13 @@ * // => [['fred', 30, true], ['barney', 40, false]] */ function zip() { - return unzip(arguments); + var length = arguments.length, + array = Array(length); + + while (length--) { + array[length] = arguments[length]; + } + return unzip(array); } /** @@ -2559,9 +2604,13 @@ /*--------------------------------------------------------------------------*/ /** - * Checks if `value` is present in `collection` using strict equality for - * comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. + * Checks if `value` is present in `collection` using `SameValueZero` for + * equality comparisons. If `fromIndex` is negative, it is used as the offset + * from the end of the collection. + * + * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that + * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -2596,15 +2645,15 @@ /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding value - * of each key is the number of times the key was returned by `iterator`. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the number of times the key was returned by `iteratee`. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -2612,10 +2661,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -2674,10 +2723,10 @@ * // => false */ function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = baseCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arrayEvery : baseEvery; return func(collection, predicate); } @@ -2722,9 +2771,9 @@ * // => [{ 'name': 'barney', 'age': 36 }] */ function filter(collection, predicate, thisArg) { - predicate = baseCallback(predicate, thisArg, 3); - var func = isArray(collection) ? arrayFilter : baseFilter; + + predicate = baseCallback(predicate, thisArg, 3); return func(collection, predicate); } @@ -2809,12 +2858,12 @@ } /** - * Iterates over elements of `collection` executing `iterator` for each - * element. The `iterator` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` executing `iteratee` for each + * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * - * Note: As with other "Collections" methods, objects with a `length` property + * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * @@ -2823,8 +2872,8 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * @@ -2832,25 +2881,25 @@ * // => logs each value and returns the array * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); - * // => logs each value-key pair and returns the object (property order is not guaranteed across environments) + * // => logs each value-key pair and returns the object (property order is not guaranteed) */ - function forEach(collection, iterator, thisArg) { - return (typeof iterator == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, iterator) - : baseEach(collection, baseCallback(iterator, thisArg, 3)); + function forEach(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, baseCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iterator`. The corresponding + * each element of `collection` through `iteratee`. The corresponding * value of each key is an array of the elements responsible for generating - * the key. The `iterator` is bound to `thisArg` and invoked with three + * the key. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -2858,10 +2907,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -2885,15 +2934,15 @@ /** * Creates an object composed of keys generated from the results of running - * each element of the collection through `iterator`. The corresponding value + * each element of the collection through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The - * iterator function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -2901,10 +2950,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * @@ -2954,13 +3003,13 @@ /** * Creates an array of values by running each element in the collection through - * `iterator`. The `iterator` is bound to `thisArg` and invoked with three + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -2969,10 +3018,10 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function called * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * @@ -2980,7 +3029,7 @@ * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) + * // => [3, 6, 9] (property order is not guaranteed) * * var characters = [ * { 'name': 'barney', 'age': 36 }, @@ -2991,24 +3040,24 @@ * _.map(characters, 'name'); * // => ['barney', 'fred'] */ - function map(collection, iterator, thisArg) { - iterator = baseCallback(iterator, thisArg, 3); + function map(collection, iteratee, thisArg) { + iteratee = baseCallback(iteratee, thisArg, 3); var func = isArray(collection) ? arrayMap : baseMap; - return func(collection, iterator); + return func(collection, iteratee); } /** * Retrieves the maximum value of `collection`. If the collection is empty - * or falsey `-Infinity` is returned. If an iterator function is provided it + * or falsey `-Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -3016,10 +3065,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * @@ -3041,17 +3090,17 @@ * _.max(characters, 'age'); * // => { 'name': 'fred', 'age': 40 }; */ - function max(collection, iterator, thisArg) { + function max(collection, iteratee, thisArg) { var computed = -Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - if (iterator == null) { + if (iteratee == null) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -3063,10 +3112,10 @@ } } } else { - iterator = baseCallback(iterator, thisArg, 3); + iteratee = baseCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current > computed || (current === -Infinity && current === result)) { computed = current; result = value; @@ -3078,15 +3127,15 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty - * or falsey `Infinity` is returned. If an iterator function is provided it + * or falsey `Infinity` is returned. If an iteratee function is provided it * is executed for each value in the collection to generate the criterion by - * which the value is ranked. The `iterator` is bound to `thisArg` and invoked + * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -3094,10 +3143,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iterator] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function called per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * @@ -3119,17 +3168,17 @@ * _.min(characters, 'age'); * // => { 'name': 'barney', 'age': 36 }; */ - function min(collection, iterator, thisArg) { + function min(collection, iteratee, thisArg) { var computed = Infinity, result = computed, - type = typeof iterator; + type = typeof iteratee; // enables use as a callback for functions like `_.map` - if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === collection) { - iterator = null; + if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { + iteratee = null; } - if (iterator == null) { + if (iteratee == null) { var index = -1, iterable = toIterable(collection), length = iterable.length; @@ -3141,10 +3190,10 @@ } } } else { - iterator = baseCallback(iterator, thisArg, 3); + iteratee = baseCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { - var current = iterator(value, index, collection); + var current = iteratee(value, index, collection); if (current < computed || (current === Infinity && current === result)) { computed = current; result = value; @@ -3227,10 +3276,10 @@ /** * Reduces a collection to a value which is the accumulated result of running - * each element in the collection through `iterator`, where each successive + * each element in the collection through `iteratee`, where each successive * execution consumes the return value of the previous execution. If `accumulator` * is not provided the first element of the collection is used as the initial - * value. The `iterator` is bound to `thisArg`and invoked with four arguments; + * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * * @static @@ -3238,9 +3287,9 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -3251,11 +3300,11 @@ * result[key] = n * 3; * return result; * }, {}); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * // => { 'a': 3, 'b': 6, 'c': 9 } (property order is not guaranteed) */ - function reduce(collection, iterator, accumulator, thisArg) { + function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; - return func(collection, baseCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEach); + return func(collection, baseCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** @@ -3267,9 +3316,9 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iterator=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function called per iteration. * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -3277,9 +3326,9 @@ * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ - function reduceRight(collection, iterator, accumulator, thisArg) { + function reduceRight(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduceRight : baseReduce; - return func(collection, baseCallback(iterator, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); + return func(collection, baseCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** @@ -3321,8 +3370,12 @@ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = baseCallback(predicate, thisArg, 3); - return filter(collection, negate(predicate)); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); } /** @@ -3456,27 +3509,27 @@ * // => false */ function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = baseCallback(predicate, thisArg, 3); } - var func = isArray(collection) ? arraySome : baseSome; return func(collection, predicate); } /** * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through `iterator`. This method performs + * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. - * The `iterator` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * - * If a property name is provided for `iterator` the created "_.pluck" style + * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * - * If an array of property names is provided for `iterator` the collection + * If an array of property names is provided for `iteratee` the collection * is sorted by each property value. * - * If an object is provided for `iterator` the created "_.where" style callback + * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * @@ -3484,10 +3537,10 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [iterator=identity] The function + * @param {Array|Function|Object|string} [iteratee=identity] The function * called per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. * @example * @@ -3512,15 +3565,15 @@ * _.map(_.sortBy(characters, ['name', 'age']), _.values); * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ - function sortBy(collection, iterator, thisArg) { + function sortBy(collection, iteratee, thisArg) { var index = -1, length = collection && collection.length, result = Array(length < 0 ? 0 : length >>> 0); - iterator = baseCallback(iterator, thisArg, 3); + iteratee = baseCallback(iteratee, thisArg, 3); baseEach(collection, function(value, key, collection) { result[++index] = { - 'criteria': iterator(value, key, collection), + 'criteria': iteratee(value, key, collection), 'index': index, 'value': value }; @@ -3550,7 +3603,7 @@ function toArray(collection) { var length = collection ? collection.length : 0; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { - return slice(collection); + return baseSlice(collection); } return values(collection); } @@ -3658,7 +3711,7 @@ * and prepends any additional `bind` arguments to those provided to the bound * function. * - * Note: Unlike native `Function#bind` this method does not set the `length` + * **Note:** Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static @@ -3680,7 +3733,7 @@ */ function bind(func, thisArg) { return arguments.length < 3 - ? createWrapper([func, BIND_FLAG, null, thisArg]) + ? createWrapper(func, BIND_FLAG, null, thisArg) : basePartial(func, BIND_FLAG | PARTIAL_FLAG, slice(arguments, 2), [], thisArg); } @@ -3690,7 +3743,7 @@ * of method names. If no method names are provided all enumerable function * properties, own and inherited, of `object` are bound. * - * Note: This method does not set the `length` property of bound functions. + * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ @@ -3780,7 +3833,7 @@ * and/or trailing edge of the `wait` timeout. Subsequent calls to the * debounced function return the result of the last `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * @@ -4046,34 +4099,6 @@ }; } - /** - * Creates a function that negates the result of the predicate `func`. The - * `func` function is executed with the `this` binding and arguments of the - * created function. - * - * @static - * @memberOf _ - * @category Function - * @param {Function} predicate The predicate to negate. - * @returns {Function} Returns the new function. - * @example - * - * function isEven(n) { - * return n % 2 == 0; - * } - * - * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); - * // => [1, 3, 5] - */ - function negate(predicate) { - if (!isFunction(predicate)) { - throw new TypeError(FUNC_ERROR_TEXT); - } - return function() { - return !predicate.apply(this, arguments); - }; - } - /** * Creates a function that is restricted to execute `func` once. Repeat calls * to the function return the value of the first call. The `func` is executed @@ -4099,7 +4124,7 @@ * prepended to those provided to the new function. This method is similar to * `_.bind` except it does **not** alter the `this` binding. * - * Note: This method does not set the `length` property of partially applied + * **Note:** This method does not set the `length` property of partially applied * functions. * * @static @@ -4117,9 +4142,9 @@ */ function partial(func) { var args = slice(arguments, 1), - partialHolders = replaceHolders(args, partial.placeholder); + holders = replaceHolders(args, partial.placeholder); - return basePartial(func, PARTIAL_FLAG, args, partialHolders); + return basePartial(func, PARTIAL_FLAG, args, holders); } /** @@ -4130,7 +4155,7 @@ * Subsequent calls to the throttled function return the result of the last * `func` call. * - * Note: If `leading` and `trailing` options are `true`, `func` is called on + * **Note:** If `leading` and `trailing` options are `true`, `func` is called on * the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * @@ -4263,7 +4288,7 @@ * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * - * Note: This method is loosely based on the structured clone algorithm. Functions + * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) @@ -4304,7 +4329,7 @@ */ function clone(value) { return isObject(value) - ? (isArray(value) ? slice(value) : assign({}, value)) + ? (isArray(value) ? baseSlice(value) : assign({}, value)) : value; } @@ -4313,7 +4338,7 @@ * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property are ignored. * - * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) + * **Note:** See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. * * @static @@ -4359,14 +4384,14 @@ * @alias methods * @category Object * @param {Object} object The object to inspect. - * @returns {Array} Returns the new sorted array of property names. + * @returns {Array} Returns the new array of property names. * @example * * _.functions(_); * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { - return baseFunctions(object, keysIn); + return baseFunctions(object, keysIn(object)); } /** @@ -4583,7 +4608,7 @@ * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). * - * Note: This method supports comparing arrays, booleans, `Date` objects, + * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. @@ -4643,7 +4668,7 @@ /** * Checks if `value` is a finite primitive number. * - * Note: This method is based on ES6 `Number.isFinite`. See the + * **Note:** This method is based on ES6 `Number.isFinite`. See the * [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) * for more details. * @@ -4706,7 +4731,7 @@ * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * Note: See the [ES5 spec](http://es5.github.io/#x8) for more details. + * **Note:** See the [ES5 spec](http://es5.github.io/#x8) for more details. * * @static * @memberOf _ @@ -4734,7 +4759,7 @@ /** * Checks if `value` is `NaN`. * - * Note: This method is not the same as native `isNaN` which returns `true` + * **Note:** This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * @@ -4763,6 +4788,27 @@ return isNumber(value) && value != +value; } + /** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Object + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + */ + function isNative(value) { + if (isFunction(value)) { + return reNative.test(fnToString.call(value)); + } + if (value && typeof value == 'object') { + return !('constructor' in value) && isHostObject(value) + ? reNative.test(value) + : reHostCtor.test(toString.call(value)); + } + return false; + } + /** * Checks if `value` is `null`. * @@ -4786,7 +4832,7 @@ /** * Checks if `value` is classified as a `Number` primitive or object. * - * Note: To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static @@ -4890,7 +4936,7 @@ * Shape.prototype.z = 0; * * _.keys(new Shape); - * // => ['x', 'y'] (property order is not guaranteed across environments) + * // => ['x', 'y'] (property order is not guaranteed) */ var keys = !nativeKeys ? shimKeys : function(object) { return isObject(object) ? nativeKeys(object) : []; @@ -4914,7 +4960,7 @@ * Shape.prototype.z = 0; * * _.keysIn(new Shape); - * // => ['x', 'y', 'z'] (property order is not guaranteed across environments) + * // => ['x', 'y', 'z'] (property order is not guaranteed) */ function keysIn(object) { var result = []; @@ -4958,8 +5004,10 @@ if (object == null) { return {}; } - var omitProps = baseFlatten(arguments, false, false, 1); - return basePick(toObject(object), baseDifference(keysIn(object), arrayMap(omitProps, String))); + var iterable = toObject(object), + props = arrayMap(baseFlatten(arguments, false, false, 1), String); + + return pickByArray(iterable, baseDifference(keysIn(iterable), props)); } /** @@ -4974,7 +5022,7 @@ * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed) */ function pairs(object) { var index = -1, @@ -5019,7 +5067,7 @@ function pick(object) { return object == null ? {} - : basePick(toObject(object), baseFlatten(arguments, false, false, 1)); + : pickByArray(toObject(object), baseFlatten(arguments, false, false, 1)); } /** @@ -5040,7 +5088,7 @@ * Shape.prototype.z = 0; * * _.values(new Shape(2, 1)); - * // => [2, 1] (property order is not guaranteed across environments) + * // => [2, 1] (property order is not guaranteed) */ function values(object) { return baseValues(object, keys); @@ -5052,7 +5100,7 @@ * Converts the characters "&", "<", ">", '"', and "'" in `string` to * their corresponding HTML entities. * - * Note: No other characters are escaped. To escape additional characters + * **Note:** No other characters are escaped. To escape additional characters * use a third-party library like [_he_](http://mths.be/he). * * When working with HTML you should always quote attribute values to reduce @@ -5105,7 +5153,7 @@ * properties may be accessed as free variables in the template. If a setting * object is provided it overrides `_.templateSettings` for the template. * - * Note: In the development build `_.template` utilizes sourceURLs for easier debugging. + * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * @@ -5252,7 +5300,7 @@ * `&`, `<`, `>`, `"`, and `'` in `string` to their * corresponding characters. * - * Note: No other HTML entities are unescaped. To unescape additional HTML + * **Note:** No other HTML entities are unescaped. To unescape additional HTML * entities use a third-party library like [_he_](http://mths.be/he). * * @static @@ -5652,16 +5700,16 @@ } /** - * Executes the iterator function `n` times, returning an array of the results - * of each execution. The `iterator` is bound to `thisArg` and invoked with + * Executes the iteratee function `n` times, returning an array of the results + * of each execution. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iterator`. - * @param {Function} [iterator=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `iterator`. + * @param {number} n The number of times to execute `iteratee`. + * @param {Function} [iteratee=identity] The function called per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example * @@ -5674,18 +5722,18 @@ * _.times(3, function(n) { this.cast(n); }, mage); * // => also calls `mage.castSpell(n)` three times */ - function times(n, iterator, thisArg) { + function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; - iterator = baseCallback(iterator, thisArg, 1); + iteratee = baseCallback(iteratee, thisArg, 1); var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); while (++index < n) { if (index < MAX_ARRAY_LENGTH) { - result[index] = iterator(index); + result[index] = iteratee(index); } else { - iterator(index); + iteratee(index); } } return result; diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index e3771cecf0..f0c9b9e3d9 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -3,44 +3,43 @@ * Lo-Dash 3.0.0-pre (Custom Build) lodash.com/license | Underscore.js 1.6.0 underscorejs.org/LICENSE * Build: `lodash underscore -o ./dist/lodash.underscore.js` */ -;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(tu(r,i)&&o.push(i)}return o}function b(n,r){var t=n?n.length:0; -if(typeof t!="number"||-1>=t||t>Rr)return x(n,r,Wt);for(var e=-1,u=P(n);++e=t||t>Rr){for(var t=Wt(n),e=t.length;e--;){var u=t[e];if(r(n[u],u,n)===Br)break}return n}for(e=P(n);t--&&r(e[t],t,e)!==Br;);return n}function d(n,r){var t=true;return b(n,function(n,e,u){return(t=!!r(n,e,u))||Br}),t}function j(n,r){var t=[];return b(n,function(n,e,u){r(n,e,u)&&t.push(n)}),t}function w(n,r,t){var e;return t(n,function(n,t,u){return r(n,t,u)?(e=n,Br):void 0 -}),e}function A(n,r,t,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++ee(i,a)&&(r&&i.push(a),o.push(f))}return o}function $(n,r){return function(t,e,u){var o=r?r():{};if(e=g(e,u,3),Ut(t)){u=-1;for(var i=t.length;++ur?0:r)}function G(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?Et(u+e,0):e||0;else if(e)return e=K(r,t),u&&r[e]===t?e:-1;return n(r,t,e)}function H(n,r,t){return J(n,null==r||t?1:0>r?0:r)}function J(n,r,t){var e=-1,u=n?n.length:0; -for(r=null==r?0:+r||0,0>r&&(r=-r>u?0:u+r),t=typeof t=="undefined"||t>u?u:+t||0,0>t&&(t+=u),u=r>t?0:t-r,t=Array(u);++e>>1,f=t(n[i]),a=fu&&(u=i)}else r=g(r,t,3),b(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function er(n,r){return rr(n,kr(r))}function ur(n,r,t,e){return(Ut(n)?p:M)(n,g(r,e,4),t,3>arguments.length,b) -}function or(n,r,t,e){return(Ut(n)?s:M)(n,g(r,e,4),t,3>arguments.length,_)}function ir(n){n=P(n);for(var r=-1,t=n.length,e=Array(t);++rarguments.length?W([n,Ir,null,r]):S(n,Ir|Mr,J(arguments,2),[],r)}function cr(n,r,t){function e(){var t=r-(Dt()-c);0>=t||t>r?(f&&clearTimeout(f),t=s,f=p=s=Sr,t&&(h=Dt(),a=n.apply(l,i),p||f||(i=l=null))):p=setTimeout(e,t) -}function u(){p&&clearTimeout(p),f=p=s=Sr,(v||g!==r)&&(h=Dt(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=Dt(),l=this,s=v&&(p||!y),false===g)var t=y&&!p;else{f||y||(h=c);var o=g-(c-h),m=0>=o||o>g;m?(f&&(f=clearTimeout(f)),h=c,a=n.apply(l,i)):f||(f=setTimeout(u,o))}return m&&p?p=clearTimeout(p):p||r===g||(p=setTimeout(e,r)),t&&(m=true,a=n.apply(l,i)),!m||p||f||(i=l=null),a}var i,f,a,c,l,p,s,h=0,g=false,v=true;if(!mr(n))throw new TypeError($r);if(r=0>r?0:r,true===t)var y=true,v=false;else br(t)&&(y=t.leading,g="maxWait"in t&&Et(+t.maxWait||0,r),v="trailing"in t?t.trailing:v); -return o.cancel=function(){p&&clearTimeout(p),f&&clearTimeout(f),f=p=s=Sr},o}function lr(n){if(!mr(n))throw new TypeError($r);return function(){return!n.apply(this,arguments)}}function pr(n){for(var r=J(arguments,1),t=r,e=pr.placeholder,u=-1,o=t.length,i=[];++u"'`]/g,Cr=/^\[object .+?Constructor\]$/,Pr=/($^)/,Vr=/[.*+?^${}()|[\]\/\\]/g,Gr=/['\n\r\u2028\u2029\\]/g,Hr="[object Arguments]",Jr="[object Boolean]",Kr="[object Date]",Lr="[object Error]",Qr="[object Number]",Xr="[object Object]",Yr="[object RegExp]",Zr="[object String]",nt={}; -nt[Hr]=nt["[object Array]"]=nt["[object Float32Array]"]=nt["[object Float64Array]"]=nt["[object Int8Array]"]=nt["[object Int16Array]"]=nt["[object Int32Array]"]=nt["[object Uint8Array]"]=nt["[object Uint8ClampedArray]"]=nt["[object Uint16Array]"]=nt["[object Uint32Array]"]=true,nt["[object ArrayBuffer]"]=nt[Jr]=nt[Kr]=nt[Lr]=nt["[object Function]"]=nt["[object Map]"]=nt[Qr]=nt[Xr]=nt[Yr]=nt["[object Set]"]=nt[Zr]=nt["[object WeakMap]"]=false;var rt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},tt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},et={"function":true,object:true},ut={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ot=et[typeof window]&&window||this,it=et[typeof exports]&&exports&&!exports.nodeType&&exports,ft=et[typeof module]&&module&&!module.nodeType&&module,at=it&&ft&&typeof global=="object"&&global; -!at||at.global!==at&&at.window!==at&&at.self!==at||(ot=at);var ct=ft&&ft.exports===it&&it,lt=Array.prototype,pt=Object.prototype,st=Function.prototype.toString,ht=ot._,gt=pt.toString,vt=RegExp("^"+function(n){return n=null==n?"":n+"",Vr.lastIndex=0,Vr.test(n)?n.replace(Vr,"\\$&"):n}(gt).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),yt=Math.ceil,mt=Math.floor,bt=pt.hasOwnProperty,_t=lt.push,dt=pt.propertyIsEnumerable,jt=lt.splice,wt=z(wt=Object.create)&&wt,At=z(At=Array.isArray)&&At,xt=ot.isFinite,Tt=z(Tt=Object.keys)&&Tt,Et=Math.max,Ot=Math.min,kt=z(kt=Date.now)&&kt,St=Math.random,It={}; -!function(){var n={0:1,length:1};It.spliceObjects=(jt.call(n,0,1),!n[0])}(0,0),o.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},wt||(v=function(){function n(){}return function(r){if(br(r)){n.prototype=r;var t=new n;n.prototype=null}return t||ot.Object()}}());var Ft=H,Mt=V,qt=$(function(n,r,t){bt.call(n,t)?++n[t]:n[t]=1}),Bt=$(function(n,r,t){bt.call(n,t)?n[t].push(r):n[t]=[r]}),$t=$(function(n,r,t){n[t]=r}),Nt=$(function(n,r,t){n[t?0:1].push(r) -},function(){return[[],[]]}),Rt=pr(function(n,r){var t;if(!mr(r))throw new TypeError($r);return function(){return 0<--n?t=r.apply(this,arguments):r=null,t}},2);vr(arguments)||(vr=function(n){var r=n&&typeof n=="object"?n.length:Sr;return typeof r=="number"&&-1--n?r.apply(this,arguments):void 0}},o.bind=ar,o.bindAll=function(n){for(var r=n,t=1r?0:r) -},o.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},o.invert=function(n){for(var r=-1,t=Wt(n),e=t.length,u={};++ro?0:o>>>0);for(t=g(t,e,3),b(n,function(n,r,e){i[++u]={a:t(n,r,e),b:u,c:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].c;return i},o.take=Mt,o.tap=function(n,r){return r(n),n},o.throttle=function(n,r,t){var e=true,u=true;if(!mr(n))throw new TypeError(funcErrorText);return false===t?e=false:br(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),cr(n,r,{leading:e,maxWait:r,trailing:u}) -},o.times=function(n,r,t){n=xt(n=+n)&&-1r?0:r))},o.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?Et(e+t,0):Ot(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},o.max=tr,o.min=function(n,r,t){var e=1/0,u=e,o=typeof r; -if("number"!=o&&"string"!=o||!t||t[r]!==n||(r=null),null==r)for(t=-1,n=P(n),o=n.length;++tr?0:+r||0,n.length),n)},Or(sr({},o)),o.VERSION="3.0.0-pre",o.prototype.chain=function(){return this.__chain__=true,this},o.prototype.value=function(){return this.__wrapped__ -},f("pop push reverse shift sort splice unshift".split(" "),function(n){var r=lt[n];o.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),It.spliceObjects||0!==n.length||delete n[0],this}}),f(["concat","join","slice"],function(n){var r=lt[n];o.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new i(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ot._=o, define("underscore",function(){return o -})):it&&ft?ct?(ft.exports=o)._=o:it._=o:ot._=o}).call(this); \ No newline at end of file +;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++te||typeof t=="undefined"){t=1;break n}if(tu(r,i)&&o.push(i)}return o}function b(n,r){var t=n?n.length:0;if(typeof t!="number"||-1>=t||t>Br){for(var t=-1,e=Nt(n),u=e.length;++t=t||t>Br){for(var t=Nt(n),e=t.length;e--;){var u=t[e];if(r(n[u],u,n)===Fr)break}return n}for(e=z(n);t--&&r(e[t],t,e)!==Fr;);return n +}function d(n,r){var t=true;return b(n,function(n,e,u){return(t=!!r(n,e,u))||Fr}),t}function j(n,r){var t=[];return b(n,function(n,e,u){r(n,e,u)&&t.push(n)}),t}function w(n,r,t){var e;return t(n,function(n,t,u){return r(n,t,u)?(e=n,Fr):void 0}),e}function A(n,r,t,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++ee(i,f)&&(r&&i.push(f),o.push(a))}return o}function M(n,r){return function(t,e,u){var o=r?r():{};if(e=v(e,u,3),$t(t)){u=-1;for(var i=t.length;++ur?0:r)}function H(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?At(u+e,0):e||0;else if(e)return e=G(r,t),u&&r[e]===t?e:-1; +return n(r,t,e)}function P(n,r,t){return V(n,null==r||t?1:0>r?0:r)}function V(n,t,e){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),e=typeof e=="undefined"||e>o?o:+e||0,0>e&&(e+=o),e&&e==o&&!t)return r(n);for(o=t>e?0:e-t,e=Array(o);++u>>1,a=t(n[i]),f=au&&(u=i)}else r=v(r,t,3),b(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function rr(n,r){return Z(n,Er(r))}function tr(n,r,t,e){return($t(n)?s:S)(n,v(r,e,4),t,3>arguments.length,b)}function er(n,r,t,e){return($t(n)?g:S)(n,v(r,e,4),t,3>arguments.length,_)}function ur(n){n=z(n);for(var r=-1,t=n.length,e=Array(t);++rarguments.length?R(n,kr,r):O(n,kr|Ir,V(arguments,2),[],r)}function ar(n,r,t){function e(){var t=r-(Rt()-c);0>=t||t>r?(a&&clearTimeout(a),t=s,a=p=s=Or,t&&(g=Rt(),f=n.apply(l,i),p||a||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),a=p=s=Or,(v||h!==r)&&(g=Rt(),f=n.apply(l,i),p||a||(i=l=null))}function o(){if(i=arguments,c=Rt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p;else{a||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(a&&(a=clearTimeout(a)),g=c,f=n.apply(l,i)):a||(a=setTimeout(u,o)) +}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,f=n.apply(l,i)),!m||p||a||(i=l=null),f}var i,a,f,c,l,p,s,g=0,h=false,v=true;if(!hr(n))throw new TypeError(Mr);if(r=0>r?0:r,true===t)var y=true,v=false;else vr(t)&&(y=t.leading,h="maxWait"in t&&At(+t.maxWait||0,r),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),a&&clearTimeout(a),a=p=s=Or},o}function fr(n){for(var r=V(arguments,1),t=r,e=fr.placeholder,u=-1,o=t.length,i=-1,a=[];++u"'`]/g,Wr=/^\[object .+?Constructor\]$/,Dr=/($^)/,zr=/[.*+?^${}()|[\]\/\\]/g,Cr=/['\n\r\u2028\u2029\\]/g,Hr="[object Arguments]",Pr="[object Boolean]",Vr="[object Date]",Gr="[object Error]",Jr="[object Number]",Kr="[object Object]",Lr="[object RegExp]",Qr="[object String]",Xr={}; +Xr[Hr]=Xr["[object Array]"]=Xr["[object Float32Array]"]=Xr["[object Float64Array]"]=Xr["[object Int8Array]"]=Xr["[object Int16Array]"]=Xr["[object Int32Array]"]=Xr["[object Uint8Array]"]=Xr["[object Uint8ClampedArray]"]=Xr["[object Uint16Array]"]=Xr["[object Uint32Array]"]=true,Xr["[object ArrayBuffer]"]=Xr[Pr]=Xr[Vr]=Xr[Gr]=Xr["[object Function]"]=Xr["[object Map]"]=Xr[Jr]=Xr[Kr]=Xr[Lr]=Xr["[object Set]"]=Xr[Qr]=Xr["[object WeakMap]"]=false;var Yr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Zr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},nt={"function":true,object:true},rt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},tt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof module]&&module&&!module.nodeType&&module,ot=et&&ut&&typeof global=="object"&&global; +!ot||ot.global!==ot&&ot.window!==ot&&ot.self!==ot||(tt=ot);var it=ut&&ut.exports===et&&et,at=Array.prototype,ft=Object.prototype,ct=Function.prototype.toString,lt=ft.hasOwnProperty,pt=tt._,st=ft.toString,gt=RegExp("^"+function(n){return n=null==n?"":n+"",zr.lastIndex=0,zr.test(n)?n.replace(zr,"\\$&"):n}(st).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ht=Math.ceil,vt=Math.floor,yt=at.push,mt=ft.propertyIsEnumerable,bt=at.splice,_t=yr(_t=Object.create)&&_t,dt=yr(dt=Array.isArray)&&dt,jt=tt.isFinite,wt=yr(wt=Object.keys)&&wt,At=Math.max,xt=Math.min,Tt=yr(Tt=Date.now)&&Tt,Et=Math.random,Ot={}; +!function(){var n={0:1,length:1};Ot.spliceObjects=(bt.call(n,0,1),!n[0]);try{Ot.hostObject=!({toString:0}+"")}catch(r){Ot.hostObject=false}}(0,0),i.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},_t||(y=function(){function n(){}return function(r){if(vr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||tt.Object()}}());var kt=P,St=C,It=M(function(n,r,t){lt.call(n,t)?++n[t]:n[t]=1}),Ft=M(function(n,r,t){lt.call(n,t)?n[t].push(r):n[t]=[r] +}),Mt=M(function(n,r,t){n[t]=r}),qt=M(function(n,r,t){n[t?0:1].push(r)},function(){return[[],[]]}),Bt=fr(function(n,r){var t;if(!hr(r))throw new TypeError(Mr);return function(){return 0<--n?t=r.apply(this,arguments):r=null,t}},2);sr(arguments)||(sr=function(n){var r=n&&typeof n=="object"?n.length:Or;return typeof r=="number"&&-1--n?r.apply(this,arguments):void 0}},i.bind=ir,i.bindAll=function(n){for(var r=n,t=1r?0:r)},i.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(f,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;f.push(e)}return f},i.invert=function(n){for(var r=-1,t=Nt(n),e=t.length,u={};++ro?0:o>>>0);for(r=v(r,e,3),b(n,function(n,t,e){i[++u]={a:r(n,t,e),b:u,c:n}}),o=i.length,i.sort(t);o--;)i[o]=i[o].c;return i},i.take=St,i.tap=function(n,r){return r(n),n},i.throttle=function(n,r,t){var e=true,u=true;if(!hr(n))throw new TypeError(funcErrorText);return false===t?e=false:vr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),ar(n,r,{leading:e,maxWait:r,trailing:u}) +},i.times=function(n,r,t){n=jt(n=+n)&&-1r?0:r))},i.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?At(e+t,0):xt(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},i.max=nr,i.min=function(n,r,t){var e=1/0,u=e,o=typeof r; +if("number"!=o&&"string"!=o||!t||t[r]!==n||(r=null),null==r)for(t=-1,n=z(n),o=n.length;++tr?0:+r||0,n.length),n)},Tr(cr({},i)),i.VERSION="3.0.0-pre",i.prototype.chain=function(){return this.__chain__=true,this},i.prototype.value=function(){return this.__wrapped__ +},f("pop push reverse shift sort splice unshift".split(" "),function(n){var r=at[n];i.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Ot.spliceObjects||0!==n.length||delete n[0],this}}),f(["concat","join","slice"],function(n){var r=at[n];i.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new a(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=i, define("underscore",function(){return i +})):et&&ut?it?(ut.exports=i)._=i:et._=i:tt._=i}).call(this); \ No newline at end of file From 200a5d84c7d9e8c38f63ff58b9e7a9207f3fa073 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Thu, 21 Aug 2014 13:06:23 +0800 Subject: [PATCH 1042/1608] Update docs. [closes #674] [ci skip] --- lodash.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lodash.js b/lodash.js index 58d8e69456..829ca12c55 100644 --- a/lodash.js +++ b/lodash.js @@ -215,7 +215,7 @@ * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. - * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) + * See [Mathias Bynens's article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in Internet Explorer < 9, they can break out @@ -3031,7 +3031,7 @@ /** * Sets metadata for `func`. * - * **Note**: If this function becomes hot, i.e. is called a lot in a short + * **Note:** If this function becomes hot, i.e. is called a lot in a short * period of time, it will trip its breaker and transition to an identity * function to avoid garbage collection pauses. * @@ -3818,11 +3818,11 @@ * Removes all provided values from `array` using `SameValueZero` for equality * comparisons. * - * **Note:** Unlike `_.without`, this method mutates `array`. - * - * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches - * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Notes:** + * - Unlike `_.without`, this method mutates `array`. + * - `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches `NaN`. + * See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -8028,7 +8028,7 @@ } /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to + * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional characters @@ -8657,7 +8657,7 @@ /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, and `'` in `string` to their + * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their * corresponding characters. * * **Note:** No other HTML entities are unescaped. To unescape additional HTML From 9f4a7fc0da94e6acdeb83dcbc9f563940298b26e Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 21 Aug 2014 09:29:27 -0700 Subject: [PATCH 1043/1608] Ensure wrapped arrays are compared correctly in `_.isEqual`. [closes #676] --- lodash.js | 144 +++++++++++++++++++++++++++------------------------ test/test.js | 45 ++++++++++------ 2 files changed, 104 insertions(+), 85 deletions(-) diff --git a/lodash.js b/lodash.js index 829ca12c55..ee2b5ec541 100644 --- a/lodash.js +++ b/lodash.js @@ -1846,7 +1846,7 @@ othType = typeof other; // exit early for unlike primitive values - if (value === value && (value == null || other == null || + if (!(valType == 'number' && othType == 'number') && (value == null || other == null || (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { return false; } @@ -1861,13 +1861,13 @@ if (othIsArg) { othClass = objectClass; } - if (valClass != othClass) { - return false; - } - var isArr = arrayLikeClasses[valClass], - isErr = valClass == errorClass; + var valIsArr = arrayLikeClasses[valClass], + valIsErr = valClass == errorClass, + valIsObj = valClass == objectClass && !isHostObject(value), + othIsObj = othClass == objectClass && !isHostObject(other); - if (isArr) { + var isSameClass = valClass == othClass; + if (isSameClass && valIsArr) { var valLength = value.length, othLength = other.length; @@ -1875,82 +1875,88 @@ return false; } } - else if (isErr || (valClass == objectClass && (support.nodeClass || !(isHostObject(value) || isHostObject(other))))) { + else { // unwrap any `lodash` wrapped values - var valWrapped = hasOwnProperty.call(value, '__wrapped__'), - othWrapped = hasOwnProperty.call(other, '__wrapped__'); + var valWrapped = valIsObj && hasOwnProperty.call(value, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (valWrapped || othWrapped) { return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, customizer, isWhere, stackA, stackB); } - if (!support.argsClass) { - valIsArg = isArguments(value); - othIsArg = isArguments(other); + if (!isSameClass) { + return false; } - // in older versions of Opera, `arguments` objects have `Array` constructors - var valCtor = valIsArg ? Object : value.constructor, - othCtor = othIsArg ? Object : other.constructor; - - if (isErr) { - // error objects of different types are not equal - if (valCtor.prototype.name != othCtor.prototype.name) { - return false; + if (valIsErr || valIsObj) { + if (!support.argsClass) { + valIsArg = isArguments(value); + othIsArg = isArguments(other); } - } else { - var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), - othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); + // in older versions of Opera, `arguments` objects have `Array` constructors + var valCtor = valIsArg ? Object : value.constructor, + othCtor = othIsArg ? Object : other.constructor; - if (valHasCtor != othHasCtor) { - return false; + if (valIsErr) { + // error objects of different types are not equal + if (valCtor.prototype.name != othCtor.prototype.name) { + return false; + } } - if (!valHasCtor) { - // non `Object` object instances with different constructors are not equal - if (valCtor != othCtor && - !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && - ('constructor' in value && 'constructor' in other) - ) { + else { + var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), + othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); + + if (valHasCtor != othHasCtor) { return false; } + if (!valHasCtor) { + // non `Object` object instances with different constructors are not equal + if (valCtor != othCtor && + !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && + ('constructor' in value && 'constructor' in other) + ) { + return false; + } + } } - } - var valProps = isErr ? ['message', 'name'] : keys(value), - othProps = isErr ? valProps : keys(other); + var valProps = valIsErr ? ['message', 'name'] : keys(value), + othProps = valIsErr ? valProps : keys(other); - if (valIsArg) { - valProps.push('length'); - } - if (othIsArg) { - othProps.push('length'); + if (valIsArg) { + valProps.push('length'); + } + if (othIsArg) { + othProps.push('length'); + } + valLength = valProps.length; + othLength = othProps.length; + if (valLength != othLength && !isWhere) { + return false; + } } - valLength = valProps.length; - othLength = othProps.length; - if (valLength != othLength && !isWhere) { + else { + switch (valClass) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal + return +value == +other; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return (value != +value) + ? other != +other + // but treat `-0` vs. `+0` as not equal + : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and + // treat strings primitives and string objects as equal + return value == String(other); + } return false; } } - else { - switch (valClass) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +value == +other; - - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (value != +value) - ? other != +other - // but treat `-0` vs. `+0` as not equal - : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); - - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and - // treat strings primitives and string objects as equal - return value == String(other); - } - return false; - } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) @@ -1969,7 +1975,7 @@ // recursively compare objects and arrays (susceptible to call stack limits) result = true; - if (isArr) { + if (valIsArr) { // deep compare the contents, ignoring non-numeric properties while (result && ++index < valLength) { var valValue = value[index]; @@ -1993,7 +1999,7 @@ else { while (result && ++index < valLength) { var key = valProps[index]; - result = isErr || hasOwnProperty.call(other, key); + result = valIsErr || hasOwnProperty.call(other, key); if (result) { valValue = value[key]; @@ -2943,7 +2949,7 @@ * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ - var isHostObject = support.hostObject ? constant(false) : function(value) { + var isHostObject = !support.hostObject ? constant(false) : function(value) { // IE < 9 presents many host objects as `Object` objects that can coerce to // strings despite having improperly defined `toString` methods return typeof value.toString != 'function' && typeof (value + '') == 'string'; diff --git a/test/test.js b/test/test.js index 0856f291a1..c67b85776a 100644 --- a/test/test.js +++ b/test/test.js @@ -5805,25 +5805,38 @@ } }); - test('should perform comparisons between wrapped values', 4, function() { - if (!isNpm) { - var object1 = _({ 'a': 1, 'b': 2 }), - object2 = _({ 'a': 1, 'b': 2 }), - actual = object1.isEqual(object2); + test('should perform comparisons between wrapped values', 32, function() { + var values = [ + [[1, 2], [1, 2], [1, 2, 3]], + [true, true, false], + [new Date, new Date, new Date(new Date - 100)], + [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 1 }], + [1, 1, 2], + [NaN, NaN, Infinity], + [/x/, /x/, /x/i], + ['a', 'a', 'A'] + ]; - strictEqual(actual, true); - strictEqual(_.isEqual(_(actual), _(true)), true); + _.each(values, function(vals) { + if (!isNpm) { + var wrapper1 = _(vals[0]), + wrapper2 = _(vals[1]), + actual = wrapper1.isEqual(wrapper2); - object1 = _({ 'a': 1, 'b': 2 }); - object2 = _({ 'a': 1, 'b': 1 }); + strictEqual(actual, true); + strictEqual(_.isEqual(_(actual), _(true)), true); - actual = object1.isEqual(object2); - strictEqual(actual, false); - strictEqual(_.isEqual(_(actual), _(false)), true); - } - else { - skipTest(4); - } + wrapper1 = _(vals[0]); + wrapper2 = _(vals[2]); + + actual = wrapper1.isEqual(wrapper2); + strictEqual(actual, false); + strictEqual(_.isEqual(_(actual), _(false)), true); + } + else { + skipTest(4); + } + }); }); test('should perform comparisons between wrapped and non-wrapped values', 4, function() { From 61578f4dca0ec2438cbce3c2ddbbccdf3971342a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 21 Aug 2014 20:24:09 -0700 Subject: [PATCH 1044/1608] Add missing semicolon. [ci skip] --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index ee2b5ec541..db7626ce3e 100644 --- a/lodash.js +++ b/lodash.js @@ -6314,7 +6314,7 @@ return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); - } + }; memoized.cache = {}; return memoized; } From 691d566482172e3b69320fb035df9824fe81bd5d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 22 Aug 2014 22:27:13 -0700 Subject: [PATCH 1045/1608] Add test for string as object when passed as the third param to `_.forEach` callbacks. --- test/test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index c67b85776a..847fb00df3 100644 --- a/test/test.js +++ b/test/test.js @@ -3889,7 +3889,7 @@ 'object': Object('abc') }, function(collection, key) { - test('`_.' + methodName + '` should work with a string ' + key + ' for `collection` (test in IE < 9)', 2, function() { + test('`_.' + methodName + '` should work with a string ' + key + ' for `collection` (test in IE < 9)', 3, function() { var args, values = []; @@ -3905,6 +3905,7 @@ deepEqual(args, ['c', 2, collection]); deepEqual(values, ['c', 'b', 'a']); } + strictEqual(typeof args[2], 'object'); }); }); From fca5fda9da38c63fd2c9dc6b3268d1387441f3ef Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 23 Aug 2014 12:12:24 -0700 Subject: [PATCH 1046/1608] Avoid circular dep with `isHostObject`. --- lodash.js | 79 ++++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/lodash.js b/lodash.js index db7626ce3e..6b41b25488 100644 --- a/lodash.js +++ b/lodash.js @@ -544,6 +544,26 @@ return '\\' + stringEscapes[chr]; } + /** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ + var isHostObject = (function() { + try { + ({ 'toString': 0 } + ''); + } catch(e) { + return function() { return false; }; + } + return function(value) { + // IE < 9 presents many host objects as `Object` objects that can coerce to + // strings despite having improperly defined `toString` methods + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + }; + }()); + /** * Used by `_.trimmedLeftIndex` and `_.trimmedRightIndex` to determine if a * character code is whitespace. @@ -921,6 +941,14 @@ */ support.funcNames = typeof Function.name == 'string'; + /** + * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). + * + * @memberOf _.support + * @type boolean + */ + support.nodeClass = toString.call(document) != objectClass; + /** * Detect if string indexes are non-enumerable * (IE < 9, RingoJS, Rhino, Narwhal). @@ -990,26 +1018,6 @@ support.dom = false; } - /** - * Detect if the host objects are detectable (IE < 9). - * - * @memberOf _.support - * @type boolean - */ - try { - support.hostObject = !({ 'toString': 0 } + ''); - } catch(e) { - support.hostObject = false; - } - - /** - * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). - * - * @memberOf _.support - * @type boolean - */ - support.nodeClass = !(toString.call(document) == objectClass && support.hostObject); - /** * Detect if `arguments` object indexes are non-enumerable. * @@ -2884,7 +2892,7 @@ */ function initObjectClone(object, isDeep) { var className = toString.call(object); - if (!cloneableClasses[className] || (!support.nodeClass && isHostObject(object))) { + if (!cloneableClasses[className] || isHostObject(object)) { return object; } var Ctor = object.constructor, @@ -2942,19 +2950,6 @@ arrayLikeClasses[toString.call(value)]) || false; } - /** - * Checks if `value` is a host object in IE < 9. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a host object, else `false`. - */ - var isHostObject = !support.hostObject ? constant(false) : function(value) { - // IE < 9 presents many host objects as `Object` objects that can coerce to - // strings despite having improperly defined `toString` methods - return typeof value.toString != 'function' && typeof (value + '') == 'string'; - }; - /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * @@ -3079,12 +3074,12 @@ var Ctor, result; - // avoid non `Object` objects, `arguments` objects, and DOM elements - if (!(value && toString.call(value) == objectClass) || + // exit early for non `Object` objects + if (!(value && typeof value == 'object' && + toString.call(value) == objectClass && !isHostObject(value)) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor))) || - (!support.argsClass && isArguments(value)) || - (!support.nodeClass && isHostObject(value))) { + (!support.argsClass && isArguments(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first @@ -7376,12 +7371,8 @@ if (isFunction(value)) { return reNative.test(fnToString.call(value)); } - if (value && typeof value == 'object') { - return !('constructor' in value) && isHostObject(value) - ? reNative.test(value) - : reHostCtor.test(toString.call(value)); - } - return false; + return (value && typeof value == 'object' && + (isHostObject(value) ? reNative : reHostCtor).test(value)) || false; } /** From 87879a678410921281d53325a03ad1ff53dd15e6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 23 Aug 2014 12:13:10 -0700 Subject: [PATCH 1047/1608] Make `_.isArguments` length check consistent with its fallback. --- lodash.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 6b41b25488..54bd3ea470 100644 --- a/lodash.js +++ b/lodash.js @@ -7027,7 +7027,8 @@ * // => false */ function isArguments(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && + var length = (value && typeof value == 'object') ? value.length : undefined; + return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER && toString.call(value) == argsClass) || false; } // fallback for environments without a `[[Class]]` for `arguments` objects From 6b59a924e842cbcf26b289f3d92a59942e64a389 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 23 Aug 2014 12:53:12 -0700 Subject: [PATCH 1048/1608] Avoid false fails on Sauce mocked alert/prompt functions. --- test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 847fb00df3..014a2e0a6f 100644 --- a/test/test.js +++ b/test/test.js @@ -6102,8 +6102,8 @@ (function() { var args = arguments; - test('should return `true` for native methods', 8, function() { - _.each([root.alert, Array, create, freeze, root.prompt, slice, Uint8Array], function(func) { + test('should return `true` for native methods', 6, function() { + _.each([Array, create, root.encodeURI, slice, Uint8Array], function(func) { if (func) { strictEqual(_.isNative(func), true); } From b48b454909b07ab4c903148a25814eff074d0209 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 00:02:01 -0700 Subject: [PATCH 1049/1608] Track down inconsistent sauce fail. --- test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 014a2e0a6f..68b36e924b 100644 --- a/test/test.js +++ b/test/test.js @@ -5824,8 +5824,8 @@ wrapper2 = _(vals[1]), actual = wrapper1.isEqual(wrapper2); - strictEqual(actual, true); - strictEqual(_.isEqual(_(actual), _(true)), true); + strictEqual(actual, true, vals); + strictEqual(_.isEqual(_(actual), _(true)), true, vals); wrapper1 = _(vals[0]); wrapper2 = _(vals[2]); From c17e1f9e751fa9611a0aad0f0b9f08b8e485e99d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 12:08:46 -0700 Subject: [PATCH 1050/1608] Doc tweak standardizing on "invoke" and "call". [ci skip] --- lodash.js | 278 +++++++++++++++++++++++++++--------------------------- 1 file changed, 139 insertions(+), 139 deletions(-) diff --git a/lodash.js b/lodash.js index 54bd3ea470..7f800ecfd1 100644 --- a/lodash.js +++ b/lodash.js @@ -492,7 +492,7 @@ * given string. * * @private - * @param {Function} callback The function called to combine each word. + * @param {Function} callback The function invoked to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { @@ -1106,7 +1106,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { @@ -1127,7 +1127,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEachRight(array, iteratee) { @@ -1147,7 +1147,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -1169,7 +1169,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { @@ -1189,7 +1189,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { @@ -1213,7 +1213,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. @@ -1238,7 +1238,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. @@ -1262,7 +1262,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -1568,7 +1568,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, iteratee) { @@ -1593,7 +1593,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, iteratee) { @@ -1616,7 +1616,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -1636,7 +1636,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { @@ -1657,7 +1657,7 @@ * * @private * @param {Array|Object|string} collection The collection to search. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey=false] Specify returning the key of the found * element instead of the element itself. @@ -1717,13 +1717,13 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iteratee` for + * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -1747,7 +1747,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -1770,7 +1770,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { @@ -1783,7 +1783,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { @@ -1796,7 +1796,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { @@ -2058,7 +2058,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { @@ -2202,7 +2202,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. @@ -2246,7 +2246,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -2267,7 +2267,7 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted @@ -2305,7 +2305,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, iteratee) { @@ -2813,7 +2813,7 @@ * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns * the `baseCallback` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function} Returns the chosen function or its result. @@ -2845,7 +2845,7 @@ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. @@ -2991,7 +2991,7 @@ * * @private * @param {Object} object The source object. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { @@ -3032,7 +3032,7 @@ /** * Sets metadata for `func`. * - * **Note:** If this function becomes hot, i.e. is called a lot in a short + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity * function to avoid garbage collection pauses. * @@ -3138,7 +3138,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function sortedUniq(array, iteratee) { @@ -3370,7 +3370,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -3419,7 +3419,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -3466,7 +3466,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3520,7 +3520,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3902,7 +3902,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to modify. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3994,7 +3994,7 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iteratee function is provided it is executed for `value` + * of the array. If an iteratee function is provided it is invoked for `value` * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * @@ -4010,7 +4010,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4051,7 +4051,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4146,7 +4146,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -4195,7 +4195,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -4253,7 +4253,7 @@ * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster * search algorithm for sorted arrays. If an iteratee function is provided it - * is executed for each value in the array to generate the criterion by which + * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * @@ -4274,7 +4274,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4685,7 +4685,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4722,7 +4722,7 @@ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4771,7 +4771,7 @@ * @alias select * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4818,7 +4818,7 @@ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4861,7 +4861,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4905,8 +4905,8 @@ } /** - * Iterates over elements of `collection` executing `iteratee` for each - * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -4919,7 +4919,7 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -4945,7 +4945,7 @@ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -4977,7 +4977,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5020,7 +5020,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5047,9 +5047,9 @@ /** * Invokes the method named by `methodName` on each element in the collection, - * returning an array of the results of each invoked method. Additional arguments - * is provided to each invoked method. If `methodName` is a function it is - * invoked for, and `this` bound to, each element in the 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 the collection. * * @static * @memberOf _ @@ -5088,7 +5088,7 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5120,7 +5120,7 @@ /** * Retrieves the maximum value of `collection`. If the collection is empty * or falsey `-Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -5135,7 +5135,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5203,7 +5203,7 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty * or falsey `Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -5218,7 +5218,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5300,7 +5300,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5357,8 +5357,8 @@ /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through `iteratee`, where each successive - * execution consumes the return value of the previous execution. If `accumulator` - * is not provided the first element of the collection is used as the initial + * invocation consumes the return value of the previous. If `accumulator` is + * not provided the first element of the collection is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * @@ -5367,7 +5367,7 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -5396,7 +5396,7 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -5426,7 +5426,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5564,7 +5564,7 @@ * @alias any * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5618,7 +5618,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=identity] The function - * called per iteration. If property name(s) or an object is provided it + * invoked per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. @@ -5736,13 +5736,13 @@ /*--------------------------------------------------------------------------*/ /** - * The opposite of `_.before`; this method creates a function that executes + * The opposite of `_.before`; this method creates a function that invokes * `func` only after it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of calls before `func` is executed. + * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -5771,13 +5771,13 @@ } /** - * Creates a function that executes `func`, with the `this` binding and + * Creates a function that invokes `func`, with the `this` binding and * arguments of the created function, until it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of times `func` may be executed. + * @param {number} n The number of times `func` may be called. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -6039,14 +6039,14 @@ } /** - * Creates a function that delays the execution of `func` until after `wait` + * Creates a function that delays the invocation of `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 calls. Provide an + * function comes with a `cancel` method to cancel delayed invokes. 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` call. + * debounced function return the result of the last `func` invocation. * - * **Note:** If `leading` and `trailing` options are `true`, `func` is called on + * **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 * invoked more than once during the `wait` timeout. * @@ -6059,11 +6059,11 @@ * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading + * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be - * delayed before it is called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * delayed before it is invoked. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example @@ -6071,13 +6071,13 @@ * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls + * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * }); * - * // ensure `batchLog` is executed once after 1 second of debounced calls + * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 @@ -6215,8 +6215,8 @@ } /** - * Defers executing the `func` function until the current call stack has - * cleared. Additional arguments are provided to `func` when it is invoked. + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -6238,14 +6238,14 @@ } /** - * Executes the `func` function after `wait` milliseconds. Additional arguments - * are provided to `func` when it is invoked. + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay execution. + * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example @@ -6266,7 +6266,7 @@ * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the cache key. The `func` is - * executed with the `this` binding of the memoized function. The result cache + * invoked with the `this` binding of the memoized function. The result cache * is exposed as the `cache` property on the memoized function. * * @static @@ -6316,7 +6316,7 @@ /** * Creates a function that negates the result of the predicate `func`. The - * `func` function is executed with the `this` binding and arguments of the + * `func` predicate is invoked with the `this` binding and arguments of the * created function. * * @static @@ -6343,8 +6343,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls - * to the function return the value of the first call. The `func` is executed + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first call. The `func` is invoked * with the `this` binding of the created function. * * @static @@ -6358,17 +6358,17 @@ * var initialize = _.once(createApplication); * initialize(); * initialize(); - * // `initialize` executes `createApplication` once + * // `initialize` invokes `createApplication` once */ var once = partial(before, 2); /** - * Creates a function that invokes `func` with any additional `partial` arguments - * prepended to those provided to the new function. This method is similar to - * `_.bind` except it does **not** alter the `this` binding. + * Creates a function that invokes `func` with `partial` arguments prepended + * to those provided to the new function. This method is similar to `_.bind` + * except it does **not** alter the `this` binding. * - * **Note:** This method does not set the `length` property of partially applied - * functions. + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ @@ -6429,15 +6429,15 @@ } /** - * Creates a function that only calls the `func` function at most once per - * every `wait` milliseconds. The created function comes with a `cancel` method - * to cancel delayed calls. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * 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 invokes. 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 called on - * the trailing edge of the timeout only if the the throttled function is + * **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 * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) @@ -6447,11 +6447,11 @@ * @memberOf _ * @category Function * @param {Function} func The function to throttle. - * @param {number} wait The number of milliseconds to throttle executions to. + * @param {number} wait The number of milliseconds to throttle invocations to. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading + * @param {boolean} [options.leading=true] Specify invoking on the leading * edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example @@ -6459,7 +6459,7 @@ * // avoid excessively updating the position while scrolling * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * - * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes + * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) * jQuery('.interactive').on('click', throttled); * @@ -6487,9 +6487,9 @@ /** * Creates a function that provides `value` to the wrapper function as its - * first argument. Additional arguments provided to the function are appended - * to those provided to the wrapper function. The wrapper is executed with - * the `this` binding of the created function. + * first argument. Any additional arguments provided to the function are + * appended to those provided to the wrapper function. The wrapper is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ @@ -6515,7 +6515,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. - * If `customizer` is provided it is executed to produce the assigned values. + * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments; * (objectValue, sourceValue, key, object, source). * @@ -6545,7 +6545,7 @@ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is - * executed to produce the cloned values. If `customizer` returns `undefined` + * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * @@ -6607,7 +6607,7 @@ } /** - * Creates a deep clone of `value`. If `customizer` is provided it is executed + * Creates a deep clone of `value`. If `customizer` is provided it is invoked * to produce the cloned values. If `customizer` returns `undefined` cloning * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). @@ -6732,7 +6732,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6778,7 +6778,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6810,7 +6810,7 @@ } /** - * Iterates over own and inherited enumerable properties of an object executing + * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. @@ -6819,7 +6819,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6851,7 +6851,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6874,7 +6874,7 @@ } /** - * Iterates over own enumerable properties of an object executing `iteratee` + * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. @@ -6883,7 +6883,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6908,7 +6908,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -7172,7 +7172,7 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If `customizer` is provided it is executed to compare values. + * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). @@ -7653,7 +7653,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -7686,8 +7686,8 @@ * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * overwrite property assignments of previous sources. If `customizer` is - * provided it is executed to produce the merged values of the destination - * and source properties. If `customizer` returns `undefined` merging is handled + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked * with five arguments; (objectValue, sourceValue, key, object, source). * @@ -7738,7 +7738,7 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` omitting the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -7747,7 +7747,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -7807,7 +7807,7 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` picking the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -7816,7 +7816,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -7844,7 +7844,7 @@ /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own - * enumerable properties through `iteratee`, with each execution potentially + * enumerable properties through `iteratee`, with each invocation potentially * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. @@ -7853,7 +7853,7 @@ * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -8681,7 +8681,7 @@ /*--------------------------------------------------------------------------*/ /** - * Attempts to execute `func`, returning either the result or the caught + * Attempts to invoke `func`, returning either the result or the caught * error object. * * @static @@ -8984,7 +8984,7 @@ * @example * * _.defer(function(stamp) { console.log(_.now() - stamp); }, _.now()); - * // => logs the number of milliseconds it took for the deferred function to be called + * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function() { return new Date().getTime(); @@ -9223,15 +9223,15 @@ } /** - * Executes the iteratee function `n` times, returning an array of the results - * of each execution. The `iteratee` is bound to `thisArg` and invoked with + * Invokes the iteratee function `n` times, returning an array of the results + * of each invocation. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iteratee`. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example @@ -9240,10 +9240,10 @@ * // => [3, 6, 4] * * _.times(3, function(n) { mage.castSpell(n); }); - * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively + * // => invokes `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively * * _.times(3, function(n) { this.cast(n); }, mage); - * // => also calls `mage.castSpell(n)` three times + * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; From c5112cb24e54c0436bbda5061b24d5102f34fdeb Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 12:17:50 -0700 Subject: [PATCH 1051/1608] Add `_.consume` and `_.consumeRight` and make `_.compose` an alias of `_.consumeRight`. [closes #667] --- lodash.js | 104 +++++++++++++++++++++++++++++++++++---------------- test/test.js | 64 ++++++++++++++++++------------- 2 files changed, 110 insertions(+), 58 deletions(-) diff --git a/lodash.js b/lodash.js index 7f800ecfd1..2bbe6cf846 100644 --- a/lodash.js +++ b/lodash.js @@ -5916,62 +5916,98 @@ } /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. + * Creates a function that invokes the provided functions with the `this` + * binding of the create function, where each successive invocation consumes + * the return value of the previous. * * @static * @memberOf _ * @category Function - * @param {...Function} [funcs] Functions to compose. - * @returns {Function} Returns the new composed function. + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. * @example * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; - * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; + * function add(x, y) { + * return x + y; + * } * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; + * function square(n) { + * return n * n; + * } * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' + * var addSquare = _.consume(add, square); + * addSquare(1, 2); + * // => 9 */ - function compose() { + function consume() { var funcs = arguments, - length = funcs.length, - index = length - 1; + length = funcs.length; if (!length) { return function() {}; } - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError(FUNC_ERROR_TEXT); + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = 0, + result = funcs[index].apply(this, arguments); + + while (++index < length) { + result = funcs[index].call(this, result); } + return result; + }; + } + + /** + * This method is like `_.consume` except that it creates a function that + * invokes the provided functions from right to left. + * + * @static + * @memberOf _ + * @alias compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.consumeRight(square, add); + * addSquare(1, 2); + * // => 9 + */ + function consumeRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; + + if (fromIndex < 0) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); } return function() { - length = index; - var result = funcs[length].apply(this, arguments); + var index = fromIndex, + result = funcs[index].apply(this, arguments); - while (length--) { - result = funcs[length].call(this, result); + while (index--) { + result = funcs[index].call(this, result); } return result; }; } /** - * Creates a function which accepts one or more arguments of `func` that when - * invoked either executes `func` returning its result, if all `func` arguments + * Creates a function that accepts one or more arguments of `func` that when + * called either invokes `func` returning its result if all `func` arguments * have been provided, or returns a function that accepts one or more of the * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. @@ -9303,7 +9339,8 @@ lodash.chain = chain; lodash.chunk = chunk; lodash.compact = compact; - lodash.compose = compose; + lodash.consume = consume; + lodash.consumeRight = consumeRight; lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; @@ -9384,6 +9421,7 @@ // add aliases lodash.collect = map; + lodash.compose = consumeRight; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; diff --git a/test/test.js b/test/test.js index 68b36e924b..db6ea35c63 100644 --- a/test/test.js +++ b/test/test.js @@ -1722,52 +1722,64 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.compose'); + QUnit.module('lodash.consumeRight'); (function() { - test('should create a function that is the composition of the provided functions', 1, function() { - var realNameMap = { - 'pebbles': 'penelope' - }; + test('should be aliased', 1, function() { + strictEqual(_.compose, _.consumeRight); + }); + }()); - var format = function(name) { - name = realNameMap[name.toLowerCase()] || name; - return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - }; + /*--------------------------------------------------------------------------*/ - var greet = function(formatted) { - return 'Hiya ' + formatted + '!'; - }; + QUnit.module('consume methods'); + + _.each(['consume', 'consumeRight'], function(methodName) { + var func = _[methodName], + isConsume = methodName == 'consume'; - var welcome = _.compose(greet, format); - strictEqual(welcome('pebbles'), 'Hiya Penelope!'); + test('`_.' + methodName + '` should create a function that consumes the output of the provided functions', 1, function() { + function add(x, y) { + return x + y; + } + + function square(n) { + return n * n; + } + + function fixed(n) { + return n.toFixed(1); + } + + var consumer = isConsume ? func(add, square, fixed) : func(fixed, square, add); + strictEqual(consumer(1, 2), '9.0'); }); - test('should return a new function', 1, function() { - notStrictEqual(_.compose(_.noop), _.noop); + test('`_.' + methodName + '` should return a new function', 1, function() { + notStrictEqual(func(_.noop), _.noop); }); - test('should return a noop function when no arguments are provided', 2, function() { - var composed = _.compose(); + test('`_.' + methodName + '` should return a noop function when no arguments are provided', 2, function() { + var consumer = func(); try { - strictEqual(composed(), undefined); + strictEqual(consumer(), undefined); } catch(e) { ok(false); } - notStrictEqual(composed, _.noop); + notStrictEqual(consumer, _.noop); }); - test('should return a wrapped value when chaining', 1, function() { + test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() { if (!isNpm) { - var actual = _(_.noop).compose(); + var actual = _(_.noop)[methodName](); ok(actual instanceof _); } else { skipTest(); } }); - }()); + }); /*--------------------------------------------------------------------------*/ @@ -12060,6 +12072,8 @@ 'before', 'bind', 'compose', + 'consume', + 'consumeRight', 'curry', 'curryRight', 'debounce', @@ -12143,13 +12157,13 @@ }); }); - test('should throw a TypeError for falsey arguments', 17, function() { + test('should throw a TypeError for falsey arguments', 19, function() { _.each(rejectFalsey, function(methodName) { var expected = _.map(falsey, _.constant(true)), func = _[methodName]; var actual = _.map(falsey, function(value, index) { - var pass = !index && methodName == 'compose'; + var pass = !index && /^(?:compose|consume(Right)?)$/.test(methodName); try { index ? func(value) : func(); } catch(e) { From 9ad26f943f098928deb4bbde4725463527c8ffea Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 12:22:19 -0700 Subject: [PATCH 1052/1608] Minor doc nit and update `lodash` chaining doc to include `_.consume` and `_.consumeRight`. [ci skip] --- lodash.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lodash.js b/lodash.js index 2bbe6cf846..17fb90e0fb 100644 --- a/lodash.js +++ b/lodash.js @@ -794,25 +794,25 @@ * * The chainable wrapper functions are: * `after`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, - * `chain`, `chunk`, `compact`, `compose`, `concat`, `constant`, `countBy`, - * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, - * `flattenDeep`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, - * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, `matches`, `memoize`, - * `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, - * `partialRight`, `partition`, `pick`, `pluck`, `property`, `pull`, `pullAt`, - * `push`, `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, - * `sort`, `sortBy`, `splice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, - * `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, - * and `zipObject` + * `chain`, `chunk`, `compact`, `concat`, `constant`, `consume`, `consumeRight`, + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, + * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, + * `flatten`, `flattenDeep`, `forEach`, `forEachRight`, `forIn`, `forInRight`, + * `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, + * `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, + * `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, + * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `pluck`, `property`, + * `pull`, `pullAt`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `times`, `toArray`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, + * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, - * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, + * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, @@ -5917,7 +5917,7 @@ /** * Creates a function that invokes the provided functions with the `this` - * binding of the create function, where each successive invocation consumes + * binding of the created function, where each successive invocation consumes * the return value of the previous. * * @static From 3bfb9d65f47157ce2a8c6bd0c641e510036f49d0 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 12:38:32 -0700 Subject: [PATCH 1053/1608] Prevent fails in older browsers due to timer drift. --- test/test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index db6ea35c63..dfff3f3cbc 100644 --- a/test/test.js +++ b/test/test.js @@ -5819,10 +5819,12 @@ }); test('should perform comparisons between wrapped values', 32, function() { + var stamp = +new Date; + var values = [ [[1, 2], [1, 2], [1, 2, 3]], [true, true, false], - [new Date, new Date, new Date(new Date - 100)], + [new Date(stamp), new Date(stamp), new Date(stamp - 100)], [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 1 }], [1, 1, 2], [NaN, NaN, Infinity], @@ -5836,8 +5838,8 @@ wrapper2 = _(vals[1]), actual = wrapper1.isEqual(wrapper2); - strictEqual(actual, true, vals); - strictEqual(_.isEqual(_(actual), _(true)), true, vals); + strictEqual(actual, true); + strictEqual(_.isEqual(_(actual), _(true)), true); wrapper1 = _(vals[0]); wrapper2 = _(vals[2]); @@ -7510,10 +7512,10 @@ isMax = methodName == 'max'; test('`_.' + methodName + '` should work with Date objects', 1, function() { - var now = new Date, + var curr = new Date, past = new Date(0); - strictEqual(func([now, past]), isMax ? now : past); + strictEqual(func([curr, past]), isMax ? curr : past); }); test('`_.' + methodName + '` should work with a callback argument', 1, function() { From d9be6f8a9a42f0a6f56409d9a5e6356538f20708 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 13:54:09 -0700 Subject: [PATCH 1054/1608] Add `_.consume` and `_.isNative` to the features section of readme. [ci skip] --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ef0dedfe0b..82366a1f93 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# * [_.chunk](http://lodash.com/docs#chunk) for splitting an array into chunks of a given size * [_.clone](http://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects + * [_.consume](http://lodash.com/docs#consume) to complement [_.consumeRight](http://lodash.com/docs#consumeRight) (a.k.a `_.compose`) * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` * [_.create](http://lodash.com/docs#create) for easier object inheritance * [_.curry](http://lodash.com/docs#curry) & [_.curryRight](http://lodash.com/docs#curryRight) for creating [curried](http://hughfdjackson.com/javascript/why-curry-helps/) functions @@ -83,6 +84,7 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# * [_.forIn](http://lodash.com/docs#forIn) for iterating all enumerable properties * [_.forOwn](http://lodash.com/docs#forOwn) for iterating own properties * [_.isError](http://lodash.com/docs#isError) to check for error objects + * [_.isNative](http://lodash.com/docs#isNative) to check for native functions * [_.isPlainObject](http://lodash.com/docs#isPlainObject) to check for objects created by `Object` * [_.keysIn](http://lodash.com/docs#keysIn) & [_.valuesIn](http://lodash.com/docs#valuesIn) for getting keys and values of all enumerable properties * [_.mapValues](http://lodash.com/docs#mapValues) for [mapping](http://lodash.com/docs#map) values to an object From c3e717a3ef3a9f16d9bebfe58c41c7815ba41c62 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 17:29:00 -0700 Subject: [PATCH 1055/1608] Rename `_.consume` to `_.flow`. --- README.md | 2 +- lodash.js | 201 ++++++++++++++++++++++++++------------------------- test/test.js | 34 +++++---- 3 files changed, 120 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 82366a1f93..28f13e7cba 100644 --- a/README.md +++ b/README.md @@ -74,12 +74,12 @@ Don’t assign values to the [special variable](http://nodejs.org/api/repl.html# * [_.chunk](http://lodash.com/docs#chunk) for splitting an array into chunks of a given size * [_.clone](http://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects - * [_.consume](http://lodash.com/docs#consume) to complement [_.consumeRight](http://lodash.com/docs#consumeRight) (a.k.a `_.compose`) * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` * [_.create](http://lodash.com/docs#create) for easier object inheritance * [_.curry](http://lodash.com/docs#curry) & [_.curryRight](http://lodash.com/docs#curryRight) for creating [curried](http://hughfdjackson.com/javascript/why-curry-helps/) functions * [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) are cancelable & accept options for more control * [_.findIndex](http://lodash.com/docs#findIndex) & [_.findKey](http://lodash.com/docs#findKey) for finding indexes & keys + * [_.flow](http://lodash.com/docs#flow) to complement [_.flowRight](http://lodash.com/docs#vlowRight) (a.k.a `_.compose`) * [_.forEach](http://lodash.com/docs#forEach) supports exiting early * [_.forIn](http://lodash.com/docs#forIn) for iterating all enumerable properties * [_.forOwn](http://lodash.com/docs#forOwn) for iterating own properties diff --git a/lodash.js b/lodash.js index 17fb90e0fb..7491e78185 100644 --- a/lodash.js +++ b/lodash.js @@ -794,10 +794,10 @@ * * The chainable wrapper functions are: * `after`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, - * `chain`, `chunk`, `compact`, `concat`, `constant`, `consume`, `consumeRight`, - * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, - * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, - * `flatten`, `flattenDeep`, `forEach`, `forEachRight`, `forIn`, `forInRight`, + * `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `drop`, + * `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, `flattenDeep`, + * `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, * `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, * `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, * `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, @@ -5357,8 +5357,8 @@ /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through `iteratee`, where each successive - * invocation consumes the return value of the previous. If `accumulator` is - * not provided the first element of the collection is used as the initial + * invocation is supplied the return value of the previous. If `accumulator` + * is not provided the first element of the collection is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * @@ -5915,96 +5915,6 @@ : createWrapper(key, bitmask, null, object); } - /** - * Creates a function that invokes the provided functions with the `this` - * binding of the created function, where each successive invocation consumes - * the return value of the previous. - * - * @static - * @memberOf _ - * @category Function - * @param {...Function} [funcs] Functions to invoke. - * @returns {Function} Returns the new function. - * @example - * - * function add(x, y) { - * return x + y; - * } - * - * function square(n) { - * return n * n; - * } - * - * var addSquare = _.consume(add, square); - * addSquare(1, 2); - * // => 9 - */ - function consume() { - var funcs = arguments, - length = funcs.length; - - if (!length) { - return function() {}; - } - if (!arrayEvery(funcs, isFunction)) { - throw new TypeError(FUNC_ERROR_TEXT); - } - return function() { - var index = 0, - result = funcs[index].apply(this, arguments); - - while (++index < length) { - result = funcs[index].call(this, result); - } - return result; - }; - } - - /** - * This method is like `_.consume` except that it creates a function that - * invokes the provided functions from right to left. - * - * @static - * @memberOf _ - * @alias compose - * @category Function - * @param {...Function} [funcs] Functions to invoke. - * @returns {Function} Returns the new function. - * @example - * - * function add(x, y) { - * return x + y; - * } - * - * function square(n) { - * return n * n; - * } - * - * var addSquare = _.consumeRight(square, add); - * addSquare(1, 2); - * // => 9 - */ - function consumeRight() { - var funcs = arguments, - fromIndex = funcs.length - 1; - - if (fromIndex < 0) { - return function() {}; - } - if (!arrayEvery(funcs, isFunction)) { - throw new TypeError(FUNC_ERROR_TEXT); - } - return function() { - var index = fromIndex, - result = funcs[index].apply(this, arguments); - - while (index--) { - result = funcs[index].call(this, result); - } - return result; - }; - } - /** * Creates a function that accepts one or more arguments of `func` that when * called either invokes `func` returning its result if all `func` arguments @@ -6297,6 +6207,96 @@ return setTimeout(function() { func.apply(undefined, args); }, wait); } + /** + * Creates a function that invokes the provided functions with the `this` + * binding of the created function, where each successive invocation is + * supplied the return value of the previous. + * + * @static + * @memberOf _ + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flow(add, square); + * addSquare(1, 2); + * // => 9 + */ + function flow() { + var funcs = arguments, + length = funcs.length; + + if (!length) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = 0, + result = funcs[index].apply(this, arguments); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + } + + /** + * This method is like `_.flow` except that it creates a function that + * invokes the provided functions from right to left. + * + * @static + * @memberOf _ + * @alias backflow, compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight(square, add); + * addSquare(1, 2); + * // => 9 + */ + function flowRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; + + if (fromIndex < 0) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = fromIndex, + result = funcs[index].apply(this, arguments); + + while (index--) { + result = funcs[index].call(this, result); + } + return result; + }; + } + /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the @@ -6972,7 +6972,7 @@ * @example * * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + * // => ['all', 'any', 'bind', ...] */ function functions(object) { return baseFunctions(object, keysIn(object)); @@ -9339,8 +9339,6 @@ lodash.chain = chain; lodash.chunk = chunk; lodash.compact = compact; - lodash.consume = consume; - lodash.consumeRight = consumeRight; lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; @@ -9358,6 +9356,8 @@ lodash.filter = filter; lodash.flatten = flatten; lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; lodash.forEach = forEach; lodash.forEachRight = forEachRight; lodash.forIn = forIn; @@ -9420,8 +9420,9 @@ lodash.zipObject = zipObject; // add aliases + lodash.backflow = flowRight; lodash.collect = map; - lodash.compose = consumeRight; + lodash.compose = flowRight; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; diff --git a/test/test.js b/test/test.js index dfff3f3cbc..455c2b40f8 100644 --- a/test/test.js +++ b/test/test.js @@ -1722,23 +1722,24 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.consumeRight'); + QUnit.module('lodash.flowRight'); (function() { - test('should be aliased', 1, function() { - strictEqual(_.compose, _.consumeRight); + test('should be aliased', 2, function() { + strictEqual(_.backflow, _.flowRight); + strictEqual(_.compose, _.flowRight); }); }()); /*--------------------------------------------------------------------------*/ - QUnit.module('consume methods'); + QUnit.module('flow methods'); - _.each(['consume', 'consumeRight'], function(methodName) { + _.each(['flow', 'flowRight'], function(methodName) { var func = _[methodName], - isConsume = methodName == 'consume'; + isFlow = methodName == 'flow'; - test('`_.' + methodName + '` should create a function that consumes the output of the provided functions', 1, function() { + test('`_.' + methodName + '` should supply each function with the return value of the previous', 1, function() { function add(x, y) { return x + y; } @@ -1751,8 +1752,8 @@ return n.toFixed(1); } - var consumer = isConsume ? func(add, square, fixed) : func(fixed, square, add); - strictEqual(consumer(1, 2), '9.0'); + var combined = isFlow ? func(add, square, fixed) : func(fixed, square, add); + strictEqual(combined(1, 2), '9.0'); }); test('`_.' + methodName + '` should return a new function', 1, function() { @@ -1760,14 +1761,14 @@ }); test('`_.' + methodName + '` should return a noop function when no arguments are provided', 2, function() { - var consumer = func(); + var combined = func(); try { - strictEqual(consumer(), undefined); + strictEqual(combined(), undefined); } catch(e) { ok(false); } - notStrictEqual(consumer, _.noop); + notStrictEqual(combined, _.noop); }); test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() { @@ -12071,16 +12072,17 @@ var rejectFalsey = [ 'after', + 'backflow', 'before', 'bind', 'compose', - 'consume', - 'consumeRight', 'curry', 'curryRight', 'debounce', 'defer', 'delay', + 'flow', + 'flowRight', 'memoize', 'negate', 'once', @@ -12159,13 +12161,13 @@ }); }); - test('should throw a TypeError for falsey arguments', 19, function() { + test('should throw a TypeError for falsey arguments', 20, function() { _.each(rejectFalsey, function(methodName) { var expected = _.map(falsey, _.constant(true)), func = _[methodName]; var actual = _.map(falsey, function(value, index) { - var pass = !index && /^(?:compose|consume(Right)?)$/.test(methodName); + var pass = !index && /^(?:backflow|compose|flow(Right)?)$/.test(methodName); try { index ? func(value) : func(); } catch(e) { From 68bd881ca8a1cf5455cdb54cc39d5a8023a400e6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 17:29:44 -0700 Subject: [PATCH 1056/1608] Cleanup test names. [ci skip] --- test/test.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/test.js b/test/test.js index 455c2b40f8..25799a1242 100644 --- a/test/test.js +++ b/test/test.js @@ -763,11 +763,11 @@ _.times(times, _.after(n, function() { count++; })); return count; } - test('should create a function that executes `func` after `n` calls', 4, function() { - strictEqual(after(5, 5), 1, 'after(n) should execute `func` after being called `n` times'); - strictEqual(after(5, 4), 0, 'after(n) should not execute `func` before being called `n` times'); - strictEqual(after(0, 0), 0, 'after(0) should not execute `func` immediately'); - strictEqual(after(0, 1), 1, 'after(0) should execute `func` when called once'); + test('should create a function that invokes `func` after `n` calls', 4, function() { + strictEqual(after(5, 5), 1, 'after(n) should invoke `func` after being called `n` times'); + strictEqual(after(5, 4), 0, 'after(n) should not invoke `func` before being called `n` times'); + strictEqual(after(0, 0), 0, 'after(0) should not invoke `func` immediately'); + strictEqual(after(0, 1), 1, 'after(0) should invoke `func` when called once'); }); test('should coerce non-finite `n` values to `0`', 1, function() { @@ -939,11 +939,11 @@ _.times(times, _.before(n, function() { count++; })); return count; } - test('should create a function that executes `func` after `n` calls', 4, function() { - strictEqual(before(5, 4), 4, 'before(n) should execute `func` before being called `n` times'); - strictEqual(before(5, 6), 4, 'before(n) should not execute `func` after being called `n - 1` times'); - strictEqual(before(0, 0), 0, 'before(0) should not execute `func` immediately'); - strictEqual(before(0, 1), 0, 'before(0) should not execute `func` when called'); + test('should create a function that invokes `func` after `n` calls', 4, function() { + strictEqual(before(5, 4), 4, 'before(n) should invoke `func` before being called `n` times'); + strictEqual(before(5, 6), 4, 'before(n) should not invoke `func` after being called `n - 1` times'); + strictEqual(before(0, 0), 0, 'before(0) should not invoke `func` immediately'); + strictEqual(before(0, 1), 0, 'before(0) should not invoke `func` when called'); }); test('should coerce non-finite `n` values to `0`', 1, function() { @@ -2646,7 +2646,7 @@ } }); - asyncTest('should cancel `maxDelayed` when `delayed` is executed', 1, function() { + asyncTest('should cancel `maxDelayed` when `delayed` is invoked', 1, function() { if (!(isRhino && isModularize)) { var count = 0; @@ -2667,7 +2667,7 @@ } }); - asyncTest('should execute the `trailing` call with the correct arguments and `this` binding', 2, function() { + asyncTest('should invoke the `trailing` call with the correct arguments and `this` binding', 2, function() { if (!(isRhino && isModularize)) { var args, count = 0, @@ -3793,7 +3793,7 @@ deepEqual(_.flattenDeep(array), expected); }); - test('should execute without options when used as a callback for `_.map`', 2, function() { + test('should work when used as a callback for `_.map`', 2, function() { var array = [[[['a']]], [[['b']]]]; deepEqual(_.map(array, _.flatten), [[['a']], [['b']]]); @@ -7943,7 +7943,7 @@ QUnit.module('lodash.once'); (function() { - test('should execute `func` once', 2, function() { + test('should invoke `func` once', 2, function() { var count = 0, once = _.once(function() { return ++count; }); From 8b873b6b1be77be7c2bc0bb281f5ca45536ca749 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 21:29:17 -0700 Subject: [PATCH 1057/1608] Make breaker trip when greater than or equal to HOT_COUNT. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 7491e78185..4fcbc71f7e 100644 --- a/lodash.js +++ b/lodash.js @@ -3051,7 +3051,7 @@ lastCalled = stamp; if (remaining > 0) { - if (++count > HOT_COUNT) { + if (++count >= HOT_COUNT) { return key; } } else { From 36f5ddc543c6dfa26898a52c96661aa45bc7263f Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 21:31:07 -0700 Subject: [PATCH 1058/1608] Add test for hot methods. --- test/test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/test.js b/test/test.js index 25799a1242..b348da1cc2 100644 --- a/test/test.js +++ b/test/test.js @@ -3,6 +3,9 @@ /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; + /** Used to detect when a function becomes hot */ + var HOT_COUNT = 150; + /** Used as the size to cover large array optimizations */ var LARGE_ARRAY_SIZE = 200; @@ -2452,6 +2455,28 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('curry methods'); + + _.each(['curry', 'curryRight'], function(methodName) { + var func = _[methodName]; + + function fn(a, b, c, d) { + return slice.call(arguments); + } + + test('`_.' + methodName + '` should work when hot', 1, function() { + var curried = func(fn); + + var actual = _.last(_.times(HOT_COUNT, function() { + return curried(1)(2)(3)(4); + })); + + deepEqual(actual, [1, 2, 3, 4]); + }); + }); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.debounce'); (function() { From 38c57a662cc5ff191e966bad52430b1747143e47 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 24 Aug 2014 21:34:59 -0700 Subject: [PATCH 1059/1608] Rebuild dist. --- dist/lodash.compat.js | 707 ++++++++++++++++++---------------- dist/lodash.compat.min.js | 140 +++---- dist/lodash.js | 648 ++++++++++++++++--------------- dist/lodash.min.js | 128 +++--- dist/lodash.underscore.js | 383 +++++++++--------- dist/lodash.underscore.min.js | 54 +-- 6 files changed, 1051 insertions(+), 1009 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index 73d98faad3..1b52aa2068 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -216,7 +216,7 @@ * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. - * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) + * See [Mathias Bynens's article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in Internet Explorer < 9, they can break out @@ -493,7 +493,7 @@ * given string. * * @private - * @param {Function} callback The function called to combine each word. + * @param {Function} callback The function invoked to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { @@ -545,6 +545,26 @@ return '\\' + stringEscapes[chr]; } + /** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ + var isHostObject = (function() { + try { + ({ 'toString': 0 } + ''); + } catch(e) { + return function() { return false; }; + } + return function(value) { + // IE < 9 presents many host objects as `Object` objects that can coerce to + // strings despite having improperly defined `toString` methods + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + }; + }()); + /** * Used by `_.trimmedLeftIndex` and `_.trimmedRightIndex` to determine if a * character code is whitespace. @@ -774,25 +794,25 @@ * * The chainable wrapper functions are: * `after`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, - * `chain`, `chunk`, `compact`, `compose`, `concat`, `constant`, `countBy`, - * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, - * `flattenDeep`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, - * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, `matches`, `memoize`, - * `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, - * `partialRight`, `partition`, `pick`, `pluck`, `property`, `pull`, `pullAt`, - * `push`, `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, - * `sort`, `sortBy`, `splice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, - * `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, - * and `zipObject` + * `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `drop`, + * `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, `flattenDeep`, + * `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, + * `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, + * `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, + * `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, + * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `pluck`, `property`, + * `pull`, `pullAt`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `times`, `toArray`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, + * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, - * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, + * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, @@ -921,6 +941,14 @@ */ support.funcNames = typeof Function.name == 'string'; + /** + * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). + * + * @memberOf _.support + * @type boolean + */ + support.nodeClass = toString.call(document) != objectClass; + /** * Detect if string indexes are non-enumerable * (IE < 9, RingoJS, Rhino, Narwhal). @@ -990,26 +1018,6 @@ support.dom = false; } - /** - * Detect if the host objects are detectable (IE < 9). - * - * @memberOf _.support - * @type boolean - */ - try { - support.hostObject = !({ 'toString': 0 } + ''); - } catch(e) { - support.hostObject = false; - } - - /** - * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). - * - * @memberOf _.support - * @type boolean - */ - support.nodeClass = !(toString.call(document) == objectClass && support.hostObject); - /** * Detect if `arguments` object indexes are non-enumerable. * @@ -1098,7 +1106,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { @@ -1119,7 +1127,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEachRight(array, iteratee) { @@ -1139,7 +1147,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -1161,7 +1169,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { @@ -1181,7 +1189,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { @@ -1205,7 +1213,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. @@ -1230,7 +1238,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. @@ -1254,7 +1262,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -1560,7 +1568,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, iteratee) { @@ -1585,7 +1593,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, iteratee) { @@ -1608,7 +1616,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -1628,7 +1636,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { @@ -1649,7 +1657,7 @@ * * @private * @param {Array|Object|string} collection The collection to search. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey=false] Specify returning the key of the found * element instead of the element itself. @@ -1709,13 +1717,13 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iteratee` for + * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -1739,7 +1747,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -1762,7 +1770,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { @@ -1775,7 +1783,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { @@ -1788,7 +1796,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { @@ -1846,7 +1854,7 @@ othType = typeof other; // exit early for unlike primitive values - if (value === value && (value == null || other == null || + if (!(valType == 'number' && othType == 'number') && (value == null || other == null || (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { return false; } @@ -1861,13 +1869,13 @@ if (othIsArg) { othClass = objectClass; } - if (valClass != othClass) { - return false; - } - var isArr = arrayLikeClasses[valClass], - isErr = valClass == errorClass; + var valIsArr = arrayLikeClasses[valClass], + valIsErr = valClass == errorClass, + valIsObj = valClass == objectClass && !isHostObject(value), + othIsObj = othClass == objectClass && !isHostObject(other); - if (isArr) { + var isSameClass = valClass == othClass; + if (isSameClass && valIsArr) { var valLength = value.length, othLength = other.length; @@ -1875,82 +1883,88 @@ return false; } } - else if (isErr || (valClass == objectClass && (support.nodeClass || !(isHostObject(value) || isHostObject(other))))) { + else { // unwrap any `lodash` wrapped values - var valWrapped = hasOwnProperty.call(value, '__wrapped__'), - othWrapped = hasOwnProperty.call(other, '__wrapped__'); + var valWrapped = valIsObj && hasOwnProperty.call(value, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (valWrapped || othWrapped) { return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, customizer, isWhere, stackA, stackB); } - if (!support.argsClass) { - valIsArg = isArguments(value); - othIsArg = isArguments(other); + if (!isSameClass) { + return false; } - // in older versions of Opera, `arguments` objects have `Array` constructors - var valCtor = valIsArg ? Object : value.constructor, - othCtor = othIsArg ? Object : other.constructor; - - if (isErr) { - // error objects of different types are not equal - if (valCtor.prototype.name != othCtor.prototype.name) { - return false; + if (valIsErr || valIsObj) { + if (!support.argsClass) { + valIsArg = isArguments(value); + othIsArg = isArguments(other); } - } else { - var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), - othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); + // in older versions of Opera, `arguments` objects have `Array` constructors + var valCtor = valIsArg ? Object : value.constructor, + othCtor = othIsArg ? Object : other.constructor; - if (valHasCtor != othHasCtor) { - return false; + if (valIsErr) { + // error objects of different types are not equal + if (valCtor.prototype.name != othCtor.prototype.name) { + return false; + } } - if (!valHasCtor) { - // non `Object` object instances with different constructors are not equal - if (valCtor != othCtor && - !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && - ('constructor' in value && 'constructor' in other) - ) { + else { + var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), + othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); + + if (valHasCtor != othHasCtor) { return false; } + if (!valHasCtor) { + // non `Object` object instances with different constructors are not equal + if (valCtor != othCtor && + !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && + ('constructor' in value && 'constructor' in other) + ) { + return false; + } + } } - } - var valProps = isErr ? ['message', 'name'] : keys(value), - othProps = isErr ? valProps : keys(other); + var valProps = valIsErr ? ['message', 'name'] : keys(value), + othProps = valIsErr ? valProps : keys(other); - if (valIsArg) { - valProps.push('length'); - } - if (othIsArg) { - othProps.push('length'); + if (valIsArg) { + valProps.push('length'); + } + if (othIsArg) { + othProps.push('length'); + } + valLength = valProps.length; + othLength = othProps.length; + if (valLength != othLength && !isWhere) { + return false; + } } - valLength = valProps.length; - othLength = othProps.length; - if (valLength != othLength && !isWhere) { + else { + switch (valClass) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal + return +value == +other; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return (value != +value) + ? other != +other + // but treat `-0` vs. `+0` as not equal + : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and + // treat strings primitives and string objects as equal + return value == String(other); + } return false; } } - else { - switch (valClass) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +value == +other; - - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (value != +value) - ? other != +other - // but treat `-0` vs. `+0` as not equal - : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); - - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and - // treat strings primitives and string objects as equal - return value == String(other); - } - return false; - } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) @@ -1969,7 +1983,7 @@ // recursively compare objects and arrays (susceptible to call stack limits) result = true; - if (isArr) { + if (valIsArr) { // deep compare the contents, ignoring non-numeric properties while (result && ++index < valLength) { var valValue = value[index]; @@ -1993,7 +2007,7 @@ else { while (result && ++index < valLength) { var key = valProps[index]; - result = isErr || hasOwnProperty.call(other, key); + result = valIsErr || hasOwnProperty.call(other, key); if (result) { valValue = value[key]; @@ -2044,7 +2058,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { @@ -2188,7 +2202,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. @@ -2232,7 +2246,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -2253,7 +2267,7 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted @@ -2291,7 +2305,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, iteratee) { @@ -2799,7 +2813,7 @@ * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns * the `baseCallback` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function} Returns the chosen function or its result. @@ -2831,7 +2845,7 @@ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. @@ -2878,7 +2892,7 @@ */ function initObjectClone(object, isDeep) { var className = toString.call(object); - if (!cloneableClasses[className] || (!support.nodeClass && isHostObject(object))) { + if (!cloneableClasses[className] || isHostObject(object)) { return object; } var Ctor = object.constructor, @@ -2936,19 +2950,6 @@ arrayLikeClasses[toString.call(value)]) || false; } - /** - * Checks if `value` is a host object in IE < 9. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a host object, else `false`. - */ - var isHostObject = support.hostObject ? constant(false) : function(value) { - // IE < 9 presents many host objects as `Object` objects that can coerce to - // strings despite having improperly defined `toString` methods - return typeof value.toString != 'function' && typeof (value + '') == 'string'; - }; - /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * @@ -2990,7 +2991,7 @@ * * @private * @param {Object} object The source object. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { @@ -3031,7 +3032,7 @@ /** * Sets metadata for `func`. * - * **Note**: If this function becomes hot, i.e. is called a lot in a short + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity * function to avoid garbage collection pauses. * @@ -3050,7 +3051,7 @@ lastCalled = stamp; if (remaining > 0) { - if (++count > HOT_COUNT) { + if (++count >= HOT_COUNT) { return key; } } else { @@ -3073,12 +3074,12 @@ var Ctor, result; - // avoid non `Object` objects, `arguments` objects, and DOM elements - if (!(value && toString.call(value) == objectClass) || + // exit early for non `Object` objects + if (!(value && typeof value == 'object' && + toString.call(value) == objectClass && !isHostObject(value)) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor))) || - (!support.argsClass && isArguments(value)) || - (!support.nodeClass && isHostObject(value))) { + (!support.argsClass && isArguments(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first @@ -3137,7 +3138,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function sortedUniq(array, iteratee) { @@ -3369,7 +3370,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -3418,7 +3419,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -3465,7 +3466,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3519,7 +3520,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3818,11 +3819,11 @@ * Removes all provided values from `array` using `SameValueZero` for equality * comparisons. * - * **Note:** Unlike `_.without`, this method mutates `array`. - * - * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches - * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Notes:** + * - Unlike `_.without`, this method mutates `array`. + * - `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches `NaN`. + * See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3901,7 +3902,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to modify. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3993,7 +3994,7 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iteratee function is provided it is executed for `value` + * of the array. If an iteratee function is provided it is invoked for `value` * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * @@ -4009,7 +4010,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4050,7 +4051,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4145,7 +4146,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -4194,7 +4195,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -4252,7 +4253,7 @@ * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster * search algorithm for sorted arrays. If an iteratee function is provided it - * is executed for each value in the array to generate the criterion by which + * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * @@ -4273,7 +4274,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4684,7 +4685,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4721,7 +4722,7 @@ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4770,7 +4771,7 @@ * @alias select * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4817,7 +4818,7 @@ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4860,7 +4861,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4904,8 +4905,8 @@ } /** - * Iterates over elements of `collection` executing `iteratee` for each - * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -4918,7 +4919,7 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -4944,7 +4945,7 @@ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -4976,7 +4977,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5019,7 +5020,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5046,9 +5047,9 @@ /** * Invokes the method named by `methodName` on each element in the collection, - * returning an array of the results of each invoked method. Additional arguments - * is provided to each invoked method. If `methodName` is a function it is - * invoked for, and `this` bound to, each element in the 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 the collection. * * @static * @memberOf _ @@ -5087,7 +5088,7 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5119,7 +5120,7 @@ /** * Retrieves the maximum value of `collection`. If the collection is empty * or falsey `-Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -5134,7 +5135,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5202,7 +5203,7 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty * or falsey `Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -5217,7 +5218,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5299,7 +5300,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5356,7 +5357,7 @@ /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through `iteratee`, where each successive - * execution consumes the return value of the previous execution. If `accumulator` + * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of the collection is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). @@ -5366,7 +5367,7 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -5395,7 +5396,7 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -5425,7 +5426,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5563,7 +5564,7 @@ * @alias any * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5617,7 +5618,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=identity] The function - * called per iteration. If property name(s) or an object is provided it + * invoked per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. @@ -5735,13 +5736,13 @@ /*--------------------------------------------------------------------------*/ /** - * The opposite of `_.before`; this method creates a function that executes + * The opposite of `_.before`; this method creates a function that invokes * `func` only after it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of calls before `func` is executed. + * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -5770,13 +5771,13 @@ } /** - * Creates a function that executes `func`, with the `this` binding and + * Creates a function that invokes `func`, with the `this` binding and * arguments of the created function, until it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of times `func` may be executed. + * @param {number} n The number of times `func` may be called. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -5915,62 +5916,8 @@ } /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. - * - * @static - * @memberOf _ - * @category Function - * @param {...Function} [funcs] Functions to compose. - * @returns {Function} Returns the new composed function. - * @example - * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; - * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; - * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; - * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' - */ - function compose() { - var funcs = arguments, - length = funcs.length, - index = length - 1; - - if (!length) { - return function() {}; - } - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError(FUNC_ERROR_TEXT); - } - } - return function() { - length = index; - var result = funcs[length].apply(this, arguments); - - while (length--) { - result = funcs[length].call(this, result); - } - return result; - }; - } - - /** - * Creates a function which accepts one or more arguments of `func` that when - * invoked either executes `func` returning its result, if all `func` arguments + * Creates a function that accepts one or more arguments of `func` that when + * called either invokes `func` returning its result if all `func` arguments * have been provided, or returns a function that accepts one or more of the * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. @@ -6038,14 +5985,14 @@ } /** - * Creates a function that delays the execution of `func` until after `wait` + * Creates a function that delays the invocation of `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 calls. Provide an + * function comes with a `cancel` method to cancel delayed invokes. 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` call. + * debounced function return the result of the last `func` invocation. * - * **Note:** If `leading` and `trailing` options are `true`, `func` is called on + * **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 * invoked more than once during the `wait` timeout. * @@ -6058,11 +6005,11 @@ * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading + * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be - * delayed before it is called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * delayed before it is invoked. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example @@ -6070,13 +6017,13 @@ * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls + * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * }); * - * // ensure `batchLog` is executed once after 1 second of debounced calls + * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 @@ -6214,8 +6161,8 @@ } /** - * Defers executing the `func` function until the current call stack has - * cleared. Additional arguments are provided to `func` when it is invoked. + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -6237,14 +6184,14 @@ } /** - * Executes the `func` function after `wait` milliseconds. Additional arguments - * are provided to `func` when it is invoked. + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay execution. + * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example @@ -6260,12 +6207,102 @@ return setTimeout(function() { func.apply(undefined, args); }, wait); } + /** + * Creates a function that invokes the provided functions with the `this` + * binding of the created function, where each successive invocation is + * supplied the return value of the previous. + * + * @static + * @memberOf _ + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flow(add, square); + * addSquare(1, 2); + * // => 9 + */ + function flow() { + var funcs = arguments, + length = funcs.length; + + if (!length) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = 0, + result = funcs[index].apply(this, arguments); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + } + + /** + * This method is like `_.flow` except that it creates a function that + * invokes the provided functions from right to left. + * + * @static + * @memberOf _ + * @alias backflow, compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight(square, add); + * addSquare(1, 2); + * // => 9 + */ + function flowRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; + + if (fromIndex < 0) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = fromIndex, + result = funcs[index].apply(this, arguments); + + while (index--) { + result = funcs[index].call(this, result); + } + return result; + }; + } + /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the cache key. The `func` is - * executed with the `this` binding of the memoized function. The result cache + * invoked with the `this` binding of the memoized function. The result cache * is exposed as the `cache` property on the memoized function. * * @static @@ -6308,14 +6345,14 @@ return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); - } + }; memoized.cache = {}; return memoized; } /** * Creates a function that negates the result of the predicate `func`. The - * `func` function is executed with the `this` binding and arguments of the + * `func` predicate is invoked with the `this` binding and arguments of the * created function. * * @static @@ -6342,8 +6379,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls - * to the function return the value of the first call. The `func` is executed + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first call. The `func` is invoked * with the `this` binding of the created function. * * @static @@ -6357,17 +6394,17 @@ * var initialize = _.once(createApplication); * initialize(); * initialize(); - * // `initialize` executes `createApplication` once + * // `initialize` invokes `createApplication` once */ var once = partial(before, 2); /** - * Creates a function that invokes `func` with any additional `partial` arguments - * prepended to those provided to the new function. This method is similar to - * `_.bind` except it does **not** alter the `this` binding. + * Creates a function that invokes `func` with `partial` arguments prepended + * to those provided to the new function. This method is similar to `_.bind` + * except it does **not** alter the `this` binding. * - * **Note:** This method does not set the `length` property of partially applied - * functions. + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ @@ -6428,15 +6465,15 @@ } /** - * Creates a function that only calls the `func` function at most once per - * every `wait` milliseconds. The created function comes with a `cancel` method - * to cancel delayed calls. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * 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 invokes. 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 called on - * the trailing edge of the timeout only if the the throttled function is + * **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 * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) @@ -6446,11 +6483,11 @@ * @memberOf _ * @category Function * @param {Function} func The function to throttle. - * @param {number} wait The number of milliseconds to throttle executions to. + * @param {number} wait The number of milliseconds to throttle invocations to. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading + * @param {boolean} [options.leading=true] Specify invoking on the leading * edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example @@ -6458,7 +6495,7 @@ * // avoid excessively updating the position while scrolling * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * - * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes + * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) * jQuery('.interactive').on('click', throttled); * @@ -6486,9 +6523,9 @@ /** * Creates a function that provides `value` to the wrapper function as its - * first argument. Additional arguments provided to the function are appended - * to those provided to the wrapper function. The wrapper is executed with - * the `this` binding of the created function. + * first argument. Any additional arguments provided to the function are + * appended to those provided to the wrapper function. The wrapper is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ @@ -6514,7 +6551,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. - * If `customizer` is provided it is executed to produce the assigned values. + * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments; * (objectValue, sourceValue, key, object, source). * @@ -6544,7 +6581,7 @@ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is - * executed to produce the cloned values. If `customizer` returns `undefined` + * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * @@ -6606,7 +6643,7 @@ } /** - * Creates a deep clone of `value`. If `customizer` is provided it is executed + * Creates a deep clone of `value`. If `customizer` is provided it is invoked * to produce the cloned values. If `customizer` returns `undefined` cloning * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). @@ -6731,7 +6768,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6777,7 +6814,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6809,7 +6846,7 @@ } /** - * Iterates over own and inherited enumerable properties of an object executing + * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. @@ -6818,7 +6855,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6850,7 +6887,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6873,7 +6910,7 @@ } /** - * Iterates over own enumerable properties of an object executing `iteratee` + * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. @@ -6882,7 +6919,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6907,7 +6944,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6935,7 +6972,7 @@ * @example * * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + * // => ['all', 'any', 'bind', ...] */ function functions(object) { return baseFunctions(object, keysIn(object)); @@ -7026,7 +7063,8 @@ * // => false */ function isArguments(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && + var length = (value && typeof value == 'object') ? value.length : undefined; + return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER && toString.call(value) == argsClass) || false; } // fallback for environments without a `[[Class]]` for `arguments` objects @@ -7170,7 +7208,7 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If `customizer` is provided it is executed to compare values. + * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). @@ -7370,12 +7408,8 @@ if (isFunction(value)) { return reNative.test(fnToString.call(value)); } - if (value && typeof value == 'object') { - return !('constructor' in value) && isHostObject(value) - ? reNative.test(value) - : reHostCtor.test(toString.call(value)); - } - return false; + return (value && typeof value == 'object' && + (isHostObject(value) ? reNative : reHostCtor).test(value)) || false; } /** @@ -7655,7 +7689,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -7688,8 +7722,8 @@ * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * overwrite property assignments of previous sources. If `customizer` is - * provided it is executed to produce the merged values of the destination - * and source properties. If `customizer` returns `undefined` merging is handled + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked * with five arguments; (objectValue, sourceValue, key, object, source). * @@ -7740,7 +7774,7 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` omitting the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -7749,7 +7783,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -7809,7 +7843,7 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` picking the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -7818,7 +7852,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -7846,7 +7880,7 @@ /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own - * enumerable properties through `iteratee`, with each execution potentially + * enumerable properties through `iteratee`, with each invocation potentially * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. @@ -7855,7 +7889,7 @@ * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -8028,7 +8062,7 @@ } /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to + * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional characters @@ -8657,7 +8691,7 @@ /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, and `'` in `string` to their + * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their * corresponding characters. * * **Note:** No other HTML entities are unescaped. To unescape additional HTML @@ -8683,7 +8717,7 @@ /*--------------------------------------------------------------------------*/ /** - * Attempts to execute `func`, returning either the result or the caught + * Attempts to invoke `func`, returning either the result or the caught * error object. * * @static @@ -8986,7 +9020,7 @@ * @example * * _.defer(function(stamp) { console.log(_.now() - stamp); }, _.now()); - * // => logs the number of milliseconds it took for the deferred function to be called + * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function() { return new Date().getTime(); @@ -9225,15 +9259,15 @@ } /** - * Executes the iteratee function `n` times, returning an array of the results - * of each execution. The `iteratee` is bound to `thisArg` and invoked with + * Invokes the iteratee function `n` times, returning an array of the results + * of each invocation. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iteratee`. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example @@ -9242,10 +9276,10 @@ * // => [3, 6, 4] * * _.times(3, function(n) { mage.castSpell(n); }); - * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively + * // => invokes `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively * * _.times(3, function(n) { this.cast(n); }, mage); - * // => also calls `mage.castSpell(n)` three times + * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; @@ -9305,7 +9339,6 @@ lodash.chain = chain; lodash.chunk = chunk; lodash.compact = compact; - lodash.compose = compose; lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; @@ -9323,6 +9356,8 @@ lodash.filter = filter; lodash.flatten = flatten; lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; lodash.forEach = forEach; lodash.forEachRight = forEachRight; lodash.forIn = forIn; @@ -9385,7 +9420,9 @@ lodash.zipObject = zipObject; // add aliases + lodash.backflow = flowRight; lodash.collect = map; + lodash.compose = flowRight; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 1f6ea7fcda..bf061c4113 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -4,73 +4,73 @@ * Build: `lodash -o ./dist/lodash.compat.js` */ ;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) -}function v(n){for(var t=-1,r=n.length;++ti(t,f)&&l.push(f);return l}function Zt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>U)return nr(n,t); -for(var e=-1,u=Pr(n);++e=r||r>U)return tr(n,t);for(var e=Pr(n);r--&&false!==t(e[r],r,e););return n}function Vt(n,t){var r=true;return Zt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Yt(n,t){var r=[];return Zt(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function Jt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function Xt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++e>>1,f=r(n[a]),l=e?f<=t:fo(c,p)&&((t||f)&&c.push(p),l.push(s))}return l}function gr(n,t){for(var r=-1,e=t(n),u=e.length,o=Me(u);++rt)return r;var e=typeof arguments[2];if("number"!=e&&"string"!=e||!arguments[3]||arguments[3][arguments[2]]!==arguments[1]||(t=2),3=t||t>U)return Se(n);if(n=$r(n),Nu.unindexedChars&&Ie(n))for(var r=-1;++re?Iu(u+e,0):e||0;else if(e)return e=Zr(n,t),u&&n[e]===t?e:-1; -return r(n,t,e)}function zr(n){return qr(n,1)}function qr(n,t,r){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),r=typeof r=="undefined"||r>o?o:+r||0,0>r&&(r+=o),r&&r==o&&!t)return e(n);for(o=t>r?0:r-t,r=Me(o);++ur?Iu(e+r,0):r||0:0,typeof n=="string"||!Vu(n)&&Ie(n)?ru&&(u=a);else t=i&&a?o:Er(t,r,3),Zt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function oe(n,t){return ee(n,De(t))}function ie(n,t,r,e){return(Vu(n)?Ft:lr)(n,Er(t,e,4),r,3>arguments.length,Zt)}function ae(n,t,r,e){return(Vu(n)?Ut:lr)(n,Er(t,e,4),r,3>arguments.length,Kt) -}function fe(n){n=Pr(n);for(var t=-1,r=n.length,e=Me(r);++targuments.length)return Or(n,w,null,t);var r=qr(arguments,2),e=Lr(r,se.placeholder);return ar(n,w|E,r,e,t)}function pe(n,t){var r=w|j;if(2=r||r>t?(a&&su(a),r=p,a=s=p=_,r&&(h=to(),f=n.apply(c,i),s||a||(i=c=null))):s=du(e,r)}function u(){s&&su(s),a=s=p=_,(v||g!==t)&&(h=to(),f=n.apply(c,i),s||a||(i=c=null))}function o(){if(i=arguments,l=to(),c=this,p=v&&(s||!y),false===g)var r=y&&!s;else{a||y||(h=l);var o=g-(l-h),d=0>=o||o>g; -d?(a&&(a=su(a)),h=l,f=n.apply(c,i)):a||(a=du(u,o))}return d&&s?s=su(s):s||t===g||(s=du(e,t)),r&&(d=true,f=n.apply(c,i)),!d||s||a||(i=c=null),f}var i,a,f,l,c,s,p,h=0,g=false,v=true;if(!je(n))throw new Ge(R);if(t=0>t?0:t,true===r)var y=true,v=false;else Ae(r)&&(y=r.leading,g="maxWait"in r&&Iu(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&su(s),a&&su(a),a=s=p=_},o}function ye(n){var t=qr(arguments,1),r=Lr(t,ye.placeholder);return ar(n,E,t,r)}function de(n){var t=qr(arguments,1),r=Lr(t,de.placeholder); -return ar(n,I,t,r)}function me(n){return rr(n,Ce(n))}function _e(n){return n&&typeof n=="object"&&typeof n.length=="number"&&iu.call(n)==ot||false}function be(n){return n&&typeof n=="object"&&1===n.nodeType&&(Nu.nodeClass?-1t||null==n||!Ou(t))return r;n=Xe(n);do t%2&&(r+=n),t=pu(t/2),n+=n; -while(t);return r}function Fe(n,t){return(n=null==n?"":Xe(n))?null==t?n.slice(v(n),y(n)+1):(t=Xe(t),n.slice(i(n,t),a(n,t)+1)):n}function Ue(n){try{return n()}catch(t){return we(t)?t:qe(t)}}function Te(n,t){return Bt(n,t)}function Le(n){return function(){return n}}function We(n){return n}function Ne(n){var t=Xu(n),r=t.length;if(1==r){var e=t[0],u=n[e];if(Fr(u))return function(n){return null!=n&&u===n[e]&&uu.call(n,e)}}for(var o=r,i=Me(r),a=Me(r);o--;){var u=n[t[o]],f=Fr(u);i[o]=f,a[o]=f?u:Dt(u)}return function(n){if(o=r,null==n)return!o; -for(;o--;)if(i[o]?a[o]!==n[t[o]]:!uu.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!uu.call(n,t[o]):!er(a[o],n[t[o]],null,true))return false;return true}}function Pe(n,t,r){var e=true,u=Ae(t),o=null==r,i=o&&u&&Xu(t),a=i&&rr(t,i);(i&&i.length&&!a.length||o&&!u)&&(o&&(r=t),a=false,t=n,n=this),a||(a=rr(t,Xu(t))),false===r?e=false:Ae(r)&&"chain"in r&&(e=r.chain),r=-1,u=je(n);for(o=a.length;++rC)return r -}else n=0;return cr(r,e)}}(),Du=mr(function(n,t,r){uu.call(n,r)?++n[r]:n[r]=1}),Mu=mr(function(n,t,r){uu.call(n,r)?n[r].push(t):n[r]=[t]}),zu=mr(function(n,t,r){n[r]=t}),qu=mr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Zu=ye(ce,2),Ku=_r($t);Nu.argsClass||(_e=function(n){var t=n&&typeof n=="object"?n.length:_;return typeof t=="number"&&-1--n?t.apply(this,arguments):void 0}},g.assign=Ku,g.at=function(t){var r=t?t.length:0;return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0; -return t=e-((null==t||r?1:t)||0),qr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Er(t,r,3);e--&&t(n[e],e,n););return qr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Er(t,r,3);++e(p?u(p,f):i(s,f))){for(t=e;--t;){var h=o[t];if(0>(h?u(h,f):i(n[t],f)))continue n}p&&p.push(f),s.push(f)}return s},g.invert=function(n,t){for(var r=-1,e=Xu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0; -return t=e-((null==t||r?1:t)||0),qr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Er(t,r,3);e--&&t(n[e],e,n););return qr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Er(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Xe(n),D.lastIndex=0,D.test(n)?n.replace(D,p):n -},g.escapeRegExp=ke,g.every=Hr,g.find=ne,g.findIndex=Br,g.findKey=function(n,t,r){return t=Er(t,r,3),Jt(n,t,nr,true)},g.findLast=function(n,t,r){return t=Er(t,r,3),Jt(n,t,Kt)},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=Er(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},g.findLastKey=function(n,t,r){return t=Er(t,r,3),Jt(n,t,tr,true)},g.findWhere=function(n,t){return ne(n,Ne(t))},g.first=Dr,g.has=function(n,t){return n?uu.call(n,t):false},g.identity=We,g.indexOf=Mr,g.isArguments=_e,g.isArray=Vu,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&iu.call(n)==at||false -},g.isDate=function(n){return n&&typeof n=="object"&&iu.call(n)==ft||false},g.isElement=be,g.isEmpty=function(n){if(null==n)return true;var t=n.length;return typeof t=="number"&&-1r?Iu(u+r,0):Cu(r||0,u-1))+1;else if(r)return u=Kr(n,t)-1,e&&n[u]===t?u:-1;for(r=t===t;u--;)if(e=n[u],r?e===t:e!==e)return u;return-1},g.max=ue,g.min=function(n,t,r){var e=1/0,u=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,a=!(i&&Vu(n))&&Ie(n);if(i&&!a)for(r=-1,n=Pr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=Ku({},r||t,e,Pt),n=Xe(null==n?"":n),r=Ku({},t.imports,e.imports,Pt); -var u,o,i=Xu(r),a=Se(r),f=0;r=t.interpolate||G;var l="__p+='";if(r=Je((t.escape||G).source+"|"+r.source+"|"+(r===q?Z:G).source+"|"+(t.evaluate||G).source+"|$","g"),n.replace(r,function(t,r,e,i,a,c){return e||(e=i),l+=n.slice(f,c).replace(nt,h),r&&(u=true,l+="'+__e("+r+")+'"),a&&(o=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),f=c+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(N,""):l).replace(P,"$1").replace($,"$1;"),l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Ue(function(){return Ze(i,"return "+l).apply(_,a) -}),t.source=l,we(t))throw t;return t},g.trim=Fe,g.trimLeft=function(n,t){return(n=null==n?"":Xe(n))?null==t?n.slice(v(n)):(t=Xe(t),n.slice(i(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Xe(n))?null==t?n.slice(0,y(n)+1):(t=Xe(t),n.slice(0,a(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(Ae(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Xe(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Xe(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; -if(r=n.slice(0,o),null==u)return r+e;if(Ee(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Je(u.source,(K.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},nr(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new X(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=Xr,g.prototype.toString=function(){return Xe(this.__wrapped__) -},g.prototype.value=Xr,g.prototype.valueOf=Xr,tt(["join","pop","shift"],function(n){var t=He[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new X(r,n):r}}),tt(["push","reverse","sort","unshift"],function(n){var t=He[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),tt(["concat","splice"],function(n){var t=He[n];g.prototype[n]=function(){return new X(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Nu.spliceObjects||tt(["pop","shift","splice"],function(n){var t=He[n],r="splice"==n; -g.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new X(u,n):u}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,O=16,E=32,I=64,C=150,S=16,k="__lodash_"+b.replace(/[-.]/g,"_")+"__",R="Expected a function",F=Math.pow(2,32)-1,U=Math.pow(2,53)-1,T="__lodash_placeholder__",L=0,W=/^[A-Z]+$/,N=/\b__p\+='';/g,P=/\b(__p\+=)''\+/g,$=/(__e\(.*?\)|\b__t\))\+'';/g,B=/&(?:amp|lt|gt|quot|#39|#96);/g,D=/[&<>"'`]/g,M=/<%-([\s\S]+?)%>/g,z=/<%([\s\S]+?)%>/g,q=/<%=([\s\S]+?)%>/g,Z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,Y=/^0[xX]/,J=/^\[object .+?Constructor\]$/,X=/[\xC0-\xFF]/g,G=/($^)/,H=/[.*+?^${}()|[\]\/\\]/g,Q=/\bthis\b/,nt=/['\n\r\u2028\u2029\\]/g,tt=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,rt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",et="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),ut="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ot="[object Arguments]",it="[object Array]",at="[object Boolean]",ft="[object Date]",lt="[object Error]",ct="[object Function]",st="[object Number]",pt="[object Object]",ht="[object RegExp]",gt="[object String]",vt="[object ArrayBuffer]",yt="[object Float32Array]",dt="[object Float64Array]",mt="[object Int8Array]",_t="[object Int16Array]",bt="[object Int32Array]",wt="[object Uint8Array]",jt="[object Uint8ClampedArray]",At="[object Uint16Array]",xt="[object Uint32Array]",Ot={}; -Ot[ot]=Ot[it]=Ot[yt]=Ot[dt]=Ot[mt]=Ot[_t]=Ot[bt]=Ot[wt]=Ot[jt]=Ot[At]=Ot[xt]=true,Ot[vt]=Ot[at]=Ot[ft]=Ot[lt]=Ot[ct]=Ot["[object Map]"]=Ot[st]=Ot[pt]=Ot[ht]=Ot["[object Set]"]=Ot[gt]=Ot["[object WeakMap]"]=false;var Et={};Et[ot]=Et[it]=Et[vt]=Et[at]=Et[ft]=Et[yt]=Et[dt]=Et[mt]=Et[_t]=Et[bt]=Et[st]=Et[pt]=Et[ht]=Et[gt]=Et[wt]=Et[jt]=Et[At]=Et[xt]=true,Et[lt]=Et[ct]=Et["[object Map]"]=Et["[object Set]"]=Et["[object WeakMap]"]=false;var It={leading:false,maxWait:0,trailing:false},Ct={configurable:false,enumerable:false,value:null,writable:false},St={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},kt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Rt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},Ft={"function":true,object:true},Ut={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Tt=Ft[typeof window]&&window||this,Lt=Ft[typeof exports]&&exports&&!exports.nodeType&&exports,Ft=Ft[typeof module]&&module&&!module.nodeType&&module,Wt=Lt&&Ft&&typeof global=="object"&&global; -!Wt||Wt.global!==Wt&&Wt.window!==Wt&&Wt.self!==Wt||(Tt=Wt);var Wt=Ft&&Ft.exports===Lt&&Lt,Nt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Tt._=Nt, define(function(){return Nt})):Lt&&Ft?Wt?(Ft.exports=Nt)._=Nt:Lt._=Nt:Tt._=Nt}).call(this); \ No newline at end of file +}function a(n,t){for(var r=n.length;r--&&-1=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) +}function v(n){for(var t=-1,r=n.length;++ti(t,f)&&l.push(f);return l}function Kt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>U)return tr(n,t); +for(var e=-1,u=$r(n);++e=r||r>U)return rr(n,t);for(var e=$r(n);r--&&false!==t(e[r],r,e););return n}function Yt(n,t){var r=true;return Kt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Jt(n,t){var r=[];return Kt(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function Xt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function Gt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++ec))return false}else{var g=p&&ou.call(n,"__wrapped__"),h=h&&ou.call(t,"__wrapped__"); +if(g||h)return ur(g?n.__wrapped__:n,h?t.__wrapped__:t,r,e,u,o);if(!s)return false;if(!a&&!p){switch(l){case at:case ft:return+n==+t;case st:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case ht:case gt:return n==Ge(t)}return false}if(Pu.argsClass||(c=we(n),i=we(t)),g=c?Je:n.constructor,l=i?Je:t.constructor,a){if(g.prototype.name!=l.prototype.name)return false}else if(p=!c&&ou.call(n,"constructor"),h=!i&&ou.call(t,"constructor"),p!=h||!(p||g==l||xe(g)&&g instanceof g&&xe(l)&&l instanceof l)&&"constructor"in n&&"constructor"in t)return false; +if(g=a?["message","name"]:Xu(n),l=a?g:Xu(t),c&&g.push("length"),i&&l.push("length"),c=g.length,p=l.length,c!=p&&!e)return false}for(u||(u=[]),o||(o=[]),l=u.length;l--;)if(u[l]==n)return o[l]==t;if(u.push(n),o.push(t),i=true,f)for(;i&&++l>>1,f=r(n[a]),l=e?f<=t:fo(c,p)&&((t||f)&&c.push(p),l.push(s))}return l}function vr(n,t){for(var r=-1,e=t(n),u=e.length,o=ze(u);++rt)return r;var e=typeof arguments[2];if("number"!=e&&"string"!=e||!arguments[3]||arguments[3][arguments[2]]!==arguments[1]||(t=2),3=t||t>U)return Re(n);if(n=Br(n),Pu.unindexedChars&&Ce(n))for(var r=-1;++re?Su(u+e,0):e||0;else if(e)return e=Kr(n,t),u&&n[e]===t?e:-1; +return r(n,t,e)}function qr(n){return Zr(n,1)}function Zr(n,t,r){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),r=typeof r=="undefined"||r>o?o:+r||0,0>r&&(r+=o),r&&r==o&&!t)return e(n);for(o=t>r?0:r-t,r=ze(o);++ur?Su(e+r,0):r||0:0,typeof n=="string"||!Vu(n)&&Ce(n)?ru&&(u=a);else t=i&&a?o:Ir(t,r,3),Kt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function ie(n,t){return ue(n,Me(t))}function ae(n,t,r,e){return(Vu(n)?Ft:cr)(n,Ir(t,e,4),r,3>arguments.length,Kt)}function fe(n,t,r,e){return(Vu(n)?Ut:cr)(n,Ir(t,e,4),r,3>arguments.length,Vt) +}function le(n){n=$r(n);for(var t=-1,r=n.length,e=ze(r);++targuments.length)return Er(n,w,null,t);var r=Zr(arguments,2),e=Wr(r,pe.placeholder);return fr(n,w|E,r,e,t)}function he(n,t){var r=w|j;if(2=r||r>t?(a&&pu(a),r=p,a=s=p=_,r&&(h=to(),f=n.apply(c,i),s||a||(i=c=null))):s=du(e,r)}function u(){s&&pu(s),a=s=p=_,(v||g!==t)&&(h=to(),f=n.apply(c,i),s||a||(i=c=null))}function o(){if(i=arguments,l=to(),c=this,p=v&&(s||!y),false===g)var r=y&&!s;else{a||y||(h=l);var o=g-(l-h),m=0>=o||o>g; +m?(a&&(a=pu(a)),h=l,f=n.apply(c,i)):a||(a=du(u,o))}return m&&s?s=pu(s):s||t===g||(s=du(e,t)),r&&(m=true,f=n.apply(c,i)),!m||s||a||(i=c=null),f}var i,a,f,l,c,s,p,h=0,g=false,v=true;if(!xe(n))throw new He(R);if(t=0>t?0:t,true===r)var y=true,v=false;else Oe(r)&&(y=r.leading,g="maxWait"in r&&Su(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&pu(s),a&&pu(a),a=s=p=_},o}function me(){var n=arguments,t=n.length-1;if(0>t)return function(){};if(!Ct(n,xe))throw new He(R);return function(){for(var r=t,e=n[r].apply(this,arguments);r--;)e=n[r].call(this,e); +return e}}function de(n){var t=Zr(arguments,1),r=Wr(t,de.placeholder);return fr(n,E,t,r)}function _e(n){var t=Zr(arguments,1),r=Wr(t,_e.placeholder);return fr(n,I,t,r)}function be(n){return er(n,ke(n))}function we(n){var t=n&&typeof n=="object"?n.length:_;return typeof t=="number"&&-1t||null==n||!Eu(t))return r;n=Ge(n);do t%2&&(r+=n),t=hu(t/2),n+=n; +while(t);return r}function Te(n,t){return(n=null==n?"":Ge(n))?null==t?n.slice(v(n),y(n)+1):(t=Ge(t),n.slice(i(n,t),a(n,t)+1)):n}function Le(n){try{return n()}catch(t){return Ae(t)?t:Ze(t)}}function We(n,t){return Dt(n,t)}function Ne(n){return n}function Pe(n){var t=Xu(n),r=t.length;if(1==r){var e=t[0],u=n[e];if(Ur(u))return function(n){return null!=n&&u===n[e]&&ou.call(n,e)}}for(var o=r,i=ze(r),a=ze(r);o--;){var u=n[t[o]],f=Ur(u);i[o]=f,a[o]=f?u:Mt(u)}return function(n){if(o=r,null==n)return!o;for(;o--;)if(i[o]?a[o]!==n[t[o]]:!ou.call(n,t[o]))return false; +for(o=r;o--;)if(i[o]?!ou.call(n,t[o]):!ur(a[o],n[t[o]],null,true))return false;return true}}function $e(n,t,r){var e=true,u=Oe(t),o=null==r,i=o&&u&&Xu(t),a=i&&er(t,i);(i&&i.length&&!a.length||o&&!u)&&(o&&(r=t),a=false,t=n,n=this),a||(a=er(t,Xu(t))),false===r?e=false:Oe(r)&&"chain"in r&&(e=r.chain),r=-1,u=xe(n);for(o=a.length;++r=S)return r}else n=0;return sr(r,e)}}(),Du=_r(function(n,t,r){ou.call(n,r)?++n[r]:n[r]=1}),Mu=_r(function(n,t,r){ou.call(n,r)?n[r].push(t):n[r]=[t]}),zu=_r(function(n,t,r){n[r]=t +}),qu=_r(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Zu=de(se,2),Ku=br(Bt);Pu.argsClass||(we=function(n){var t=n&&typeof n=="object"?n.length:_;return typeof t=="number"&&-1--n?t.apply(this,arguments):void 0}},g.assign=Ku,g.at=function(t){var r=t?t.length:0;return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),Zr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Ir(t,r,3);e--&&t(n[e],e,n););return Zr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=Ir(t,r,3);++e(p?u(p,f):i(s,f))){for(t=e;--t;){var h=o[t]; +if(0>(h?u(h,f):i(n[t],f)))continue n}p&&p.push(f),s.push(f)}return s},g.invert=function(n,t){for(var r=-1,e=Xu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),Zr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=Ir(t,r,3);e--&&t(n[e],e,n););return Zr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0; +for(t=Ir(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Ge(n),D.lastIndex=0,D.test(n)?n.replace(D,p):n},g.escapeRegExp=Fe,g.every=Qr,g.find=te,g.findIndex=Dr,g.findKey=function(n,t,r){return t=Ir(t,r,3),Xt(n,t,tr,true)},g.findLast=function(n,t,r){return t=Ir(t,r,3),Xt(n,t,Vt) +},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=Ir(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},g.findLastKey=function(n,t,r){return t=Ir(t,r,3),Xt(n,t,rr,true)},g.findWhere=function(n,t){return te(n,Pe(t))},g.first=Mr,g.has=function(n,t){return n?ou.call(n,t):false},g.identity=Ne,g.indexOf=zr,g.isArguments=we,g.isArray=Vu,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&au.call(n)==at||false},g.isDate=function(n){return n&&typeof n=="object"&&au.call(n)==ft||false},g.isElement=je,g.isEmpty=function(n){if(null==n)return true; +var t=n.length;return typeof t=="number"&&-1r?Su(u+r,0):Cu(r||0,u-1))+1;else if(r)return u=Vr(n,t)-1,e&&n[u]===t?u:-1;for(r=t===t;u--;)if(e=n[u],r?e===t:e!==e)return u;return-1},g.max=oe,g.min=function(n,t,r){var e=1/0,u=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,a=!(i&&Vu(n))&&Ce(n);if(i&&!a)for(r=-1,n=$r(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=Ku({},r||t,e,$t),n=Ge(null==n?"":n),r=Ku({},t.imports,e.imports,$t); +var u,o,i=Xu(r),a=Re(r),f=0;r=t.interpolate||G;var l="__p+='";if(r=Xe((t.escape||G).source+"|"+r.source+"|"+(r===q?Z:G).source+"|"+(t.evaluate||G).source+"|$","g"),n.replace(r,function(t,r,e,i,a,c){return e||(e=i),l+=n.slice(f,c).replace(nt,h),r&&(u=true,l+="'+__e("+r+")+'"),a&&(o=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),f=c+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(o?l.replace(N,""):l).replace(P,"$1").replace($,"$1;"),l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Le(function(){return Ke(i,"return "+l).apply(_,a) +}),t.source=l,Ae(t))throw t;return t},g.trim=Te,g.trimLeft=function(n,t){return(n=null==n?"":Ge(n))?null==t?n.slice(v(n)):(t=Ge(t),n.slice(i(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Ge(n))?null==t?n.slice(0,y(n)+1):(t=Ge(t),n.slice(0,a(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(Oe(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Ge(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Ge(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; +if(r=n.slice(0,o),null==u)return r+e;if(Se(u)){if(n.slice(o).search(u)){var i,a,f=n.slice(0,o);for(u.global||(u=Xe(u.source,(K.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(f);)a=i.index;r=r.slice(0,null==a?o:a)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},tr(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new X(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=Gr,g.prototype.toString=function(){return Ge(this.__wrapped__) +},g.prototype.value=Gr,g.prototype.valueOf=Gr,tt(["join","pop","shift"],function(n){var t=Qe[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new X(r,n):r}}),tt(["push","reverse","sort","unshift"],function(n){var t=Qe[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),tt(["concat","splice"],function(n){var t=Qe[n];g.prototype[n]=function(){return new X(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Pu.spliceObjects||tt(["pop","shift","splice"],function(n){var t=Qe[n],r="splice"==n; +g.prototype[n]=function(){var n=this.__chain__,e=this.__wrapped__,u=t.apply(e,arguments);return 0===e.length&&delete e[0],n||r?new X(u,n):u}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,O=16,E=32,I=64,S=150,C=16,k="__lodash_"+b.replace(/[-.]/g,"_")+"__",R="Expected a function",F=Math.pow(2,32)-1,U=Math.pow(2,53)-1,T="__lodash_placeholder__",L=0,W=/^[A-Z]+$/,N=/\b__p\+='';/g,P=/\b(__p\+=)''\+/g,$=/(__e\(.*?\)|\b__t\))\+'';/g,B=/&(?:amp|lt|gt|quot|#39|#96);/g,D=/[&<>"'`]/g,M=/<%-([\s\S]+?)%>/g,z=/<%([\s\S]+?)%>/g,q=/<%=([\s\S]+?)%>/g,Z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,Y=/^0[xX]/,J=/^\[object .+?Constructor\]$/,X=/[\xC0-\xFF]/g,G=/($^)/,H=/[.*+?^${}()|[\]\/\\]/g,Q=/\bthis\b/,nt=/['\n\r\u2028\u2029\\]/g,tt=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,rt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",et="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),ut="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ot="[object Arguments]",it="[object Array]",at="[object Boolean]",ft="[object Date]",lt="[object Error]",ct="[object Function]",st="[object Number]",pt="[object Object]",ht="[object RegExp]",gt="[object String]",vt="[object ArrayBuffer]",yt="[object Float32Array]",mt="[object Float64Array]",dt="[object Int8Array]",_t="[object Int16Array]",bt="[object Int32Array]",wt="[object Uint8Array]",jt="[object Uint8ClampedArray]",At="[object Uint16Array]",xt="[object Uint32Array]",Ot={}; +Ot[ot]=Ot[it]=Ot[yt]=Ot[mt]=Ot[dt]=Ot[_t]=Ot[bt]=Ot[wt]=Ot[jt]=Ot[At]=Ot[xt]=true,Ot[vt]=Ot[at]=Ot[ft]=Ot[lt]=Ot[ct]=Ot["[object Map]"]=Ot[st]=Ot[pt]=Ot[ht]=Ot["[object Set]"]=Ot[gt]=Ot["[object WeakMap]"]=false;var Et={};Et[ot]=Et[it]=Et[vt]=Et[at]=Et[ft]=Et[yt]=Et[mt]=Et[dt]=Et[_t]=Et[bt]=Et[st]=Et[pt]=Et[ht]=Et[gt]=Et[wt]=Et[jt]=Et[At]=Et[xt]=true,Et[lt]=Et[ct]=Et["[object Map]"]=Et["[object Set]"]=Et["[object WeakMap]"]=false;var It={leading:false,maxWait:0,trailing:false},St={configurable:false,enumerable:false,value:null,writable:false},Ct={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},kt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Rt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},Ft={"function":true,object:true},Ut={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Tt=Ft[typeof window]&&window||this,Lt=Ft[typeof exports]&&exports&&!exports.nodeType&&exports,Ft=Ft[typeof module]&&module&&!module.nodeType&&module,Wt=Lt&&Ft&&typeof global=="object"&&global; +!Wt||Wt.global!==Wt&&Wt.window!==Wt&&Wt.self!==Wt||(Tt=Wt);var Wt=Ft&&Ft.exports===Lt&&Lt,Nt=function(){try{({toString:0}+"")}catch(n){return function(){return false}}return function(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}}(),Pt=d();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Tt._=Pt, define(function(){return Pt})):Lt&&Ft?Wt?(Ft.exports=Pt)._=Pt:Lt._=Pt:Tt._=Pt}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index 97228c370e..4cc42a4905 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -210,7 +210,7 @@ * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. - * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) + * See [Mathias Bynens's article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in Internet Explorer < 9, they can break out @@ -487,7 +487,7 @@ * given string. * * @private - * @param {Function} callback The function called to combine each word. + * @param {Function} callback The function invoked to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { @@ -738,25 +738,25 @@ * * The chainable wrapper functions are: * `after`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, - * `chain`, `chunk`, `compact`, `compose`, `concat`, `constant`, `countBy`, - * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, - * `flattenDeep`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, - * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, `matches`, `memoize`, - * `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, - * `partialRight`, `partition`, `pick`, `pluck`, `property`, `pull`, `pullAt`, - * `push`, `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, - * `sort`, `sortBy`, `splice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, - * `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, - * and `zipObject` + * `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `drop`, + * `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, `flattenDeep`, + * `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, + * `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, + * `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, + * `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, + * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `pluck`, `property`, + * `pull`, `pullAt`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `times`, `toArray`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, + * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, - * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, + * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, @@ -859,18 +859,6 @@ support.dom = false; } - /** - * Detect if the host objects are detectable (IE < 9). - * - * @memberOf _.support - * @type boolean - */ - try { - support.hostObject = !({ 'toString': 0 } + ''); - } catch(e) { - support.hostObject = false; - } - /** * Detect if `arguments` object indexes are non-enumerable. * @@ -959,7 +947,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { @@ -980,7 +968,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEachRight(array, iteratee) { @@ -1000,7 +988,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -1022,7 +1010,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { @@ -1042,7 +1030,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { @@ -1066,7 +1054,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. @@ -1091,7 +1079,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. @@ -1115,7 +1103,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -1421,7 +1409,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, iteratee) { @@ -1446,7 +1434,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, iteratee) { @@ -1469,7 +1457,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -1489,7 +1477,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { @@ -1510,7 +1498,7 @@ * * @private * @param {Array|Object|string} collection The collection to search. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey=false] Specify returning the key of the found * element instead of the element itself. @@ -1570,13 +1558,13 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iteratee` for + * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -1600,7 +1588,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -1623,7 +1611,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { @@ -1636,7 +1624,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { @@ -1649,7 +1637,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { @@ -1707,7 +1695,7 @@ othType = typeof other; // exit early for unlike primitive values - if (value === value && (value == null || other == null || + if (!(valType == 'number' && othType == 'number') && (value == null || other == null || (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { return false; } @@ -1722,13 +1710,13 @@ if (othIsArg) { othClass = objectClass; } - if (valClass != othClass) { - return false; - } - var isArr = arrayLikeClasses[valClass], - isErr = valClass == errorClass; + var valIsArr = arrayLikeClasses[valClass], + valIsErr = valClass == errorClass, + valIsObj = valClass == objectClass, + othIsObj = othClass == objectClass; - if (isArr) { + var isSameClass = valClass == othClass; + if (isSameClass && valIsArr) { var valLength = value.length, othLength = other.length; @@ -1736,78 +1724,84 @@ return false; } } - else if (isErr || (valClass == objectClass)) { + else { // unwrap any `lodash` wrapped values - var valWrapped = hasOwnProperty.call(value, '__wrapped__'), - othWrapped = hasOwnProperty.call(other, '__wrapped__'); + var valWrapped = valIsObj && hasOwnProperty.call(value, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (valWrapped || othWrapped) { return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, customizer, isWhere, stackA, stackB); } - // in older versions of Opera, `arguments` objects have `Array` constructors - var valCtor = valIsArg ? Object : value.constructor, - othCtor = othIsArg ? Object : other.constructor; - - if (isErr) { - // error objects of different types are not equal - if (valCtor.prototype.name != othCtor.prototype.name) { - return false; + if (!isSameClass) { + return false; + } + if (valIsErr || valIsObj) { + // in older versions of Opera, `arguments` objects have `Array` constructors + var valCtor = valIsArg ? Object : value.constructor, + othCtor = othIsArg ? Object : other.constructor; + + if (valIsErr) { + // error objects of different types are not equal + if (valCtor.prototype.name != othCtor.prototype.name) { + return false; + } } - } else { - var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), - othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); + else { + var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), + othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); - if (valHasCtor != othHasCtor) { - return false; - } - if (!valHasCtor) { - // non `Object` object instances with different constructors are not equal - if (valCtor != othCtor && - !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && - ('constructor' in value && 'constructor' in other) - ) { + if (valHasCtor != othHasCtor) { return false; } + if (!valHasCtor) { + // non `Object` object instances with different constructors are not equal + if (valCtor != othCtor && + !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && + ('constructor' in value && 'constructor' in other) + ) { + return false; + } + } } - } - var valProps = isErr ? ['message', 'name'] : keys(value), - othProps = isErr ? valProps : keys(other); + var valProps = valIsErr ? ['message', 'name'] : keys(value), + othProps = valIsErr ? valProps : keys(other); - if (valIsArg) { - valProps.push('length'); - } - if (othIsArg) { - othProps.push('length'); + if (valIsArg) { + valProps.push('length'); + } + if (othIsArg) { + othProps.push('length'); + } + valLength = valProps.length; + othLength = othProps.length; + if (valLength != othLength && !isWhere) { + return false; + } } - valLength = valProps.length; - othLength = othProps.length; - if (valLength != othLength && !isWhere) { + else { + switch (valClass) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal + return +value == +other; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return (value != +value) + ? other != +other + // but treat `-0` vs. `+0` as not equal + : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and + // treat strings primitives and string objects as equal + return value == String(other); + } return false; } } - else { - switch (valClass) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +value == +other; - - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (value != +value) - ? other != +other - // but treat `-0` vs. `+0` as not equal - : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); - - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and - // treat strings primitives and string objects as equal - return value == String(other); - } - return false; - } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) @@ -1826,7 +1820,7 @@ // recursively compare objects and arrays (susceptible to call stack limits) result = true; - if (isArr) { + if (valIsArr) { // deep compare the contents, ignoring non-numeric properties while (result && ++index < valLength) { var valValue = value[index]; @@ -1850,7 +1844,7 @@ else { while (result && ++index < valLength) { var key = valProps[index]; - result = isErr || hasOwnProperty.call(other, key); + result = valIsErr || hasOwnProperty.call(other, key); if (result) { valValue = value[key]; @@ -1901,7 +1895,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { @@ -2045,7 +2039,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. @@ -2089,7 +2083,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -2110,7 +2104,7 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted @@ -2148,7 +2142,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, iteratee) { @@ -2656,7 +2650,7 @@ * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns * the `baseCallback` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function} Returns the chosen function or its result. @@ -2688,7 +2682,7 @@ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. @@ -2830,7 +2824,7 @@ * * @private * @param {Object} object The source object. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { @@ -2871,7 +2865,7 @@ /** * Sets metadata for `func`. * - * **Note**: If this function becomes hot, i.e. is called a lot in a short + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity * function to avoid garbage collection pauses. * @@ -2890,7 +2884,7 @@ lastCalled = stamp; if (remaining > 0) { - if (++count > HOT_COUNT) { + if (++count >= HOT_COUNT) { return key; } } else { @@ -2913,8 +2907,9 @@ var Ctor, result; - // avoid non `Object` objects, `arguments` objects, and DOM elements - if (!(value && toString.call(value) == objectClass) || + // exit early for non `Object` objects + if (!(value && typeof value == 'object' && + toString.call(value) == objectClass) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor)))) { return false; @@ -2964,7 +2959,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function sortedUniq(array, iteratee) { @@ -3190,7 +3185,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -3239,7 +3234,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -3286,7 +3281,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3340,7 +3335,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3639,11 +3634,11 @@ * Removes all provided values from `array` using `SameValueZero` for equality * comparisons. * - * **Note:** Unlike `_.without`, this method mutates `array`. - * - * `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches - * `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Notes:** + * - Unlike `_.without`, this method mutates `array`. + * - `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches `NaN`. + * See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. * * @static * @memberOf _ @@ -3722,7 +3717,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to modify. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3814,7 +3809,7 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iteratee function is provided it is executed for `value` + * of the array. If an iteratee function is provided it is invoked for `value` * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * @@ -3830,7 +3825,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -3871,7 +3866,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -3966,7 +3961,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -4015,7 +4010,7 @@ * @type Function * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. @@ -4073,7 +4068,7 @@ * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster * search algorithm for sorted arrays. If an iteratee function is provided it - * is executed for each value in the array to generate the criterion by which + * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * @@ -4094,7 +4089,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4505,7 +4500,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4542,7 +4537,7 @@ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4591,7 +4586,7 @@ * @alias select * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4638,7 +4633,7 @@ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4681,7 +4676,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -4725,8 +4720,8 @@ } /** - * Iterates over elements of `collection` executing `iteratee` for each - * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -4739,7 +4734,7 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -4765,7 +4760,7 @@ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -4797,7 +4792,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4840,7 +4835,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4867,9 +4862,9 @@ /** * Invokes the method named by `methodName` on each element in the collection, - * returning an array of the results of each invoked method. Additional arguments - * is provided to each invoked method. If `methodName` is a function it is - * invoked for, and `this` bound to, each element in the 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 the collection. * * @static * @memberOf _ @@ -4908,7 +4903,7 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -4940,7 +4935,7 @@ /** * Retrieves the maximum value of `collection`. If the collection is empty * or falsey `-Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -4955,7 +4950,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5023,7 +5018,7 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty * or falsey `Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -5038,7 +5033,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -5120,7 +5115,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5177,7 +5172,7 @@ /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through `iteratee`, where each successive - * execution consumes the return value of the previous execution. If `accumulator` + * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of the collection is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). @@ -5187,7 +5182,7 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -5216,7 +5211,7 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -5246,7 +5241,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5384,7 +5379,7 @@ * @alias any * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5438,7 +5433,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=identity] The function - * called per iteration. If property name(s) or an object is provided it + * invoked per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. @@ -5554,13 +5549,13 @@ /*--------------------------------------------------------------------------*/ /** - * The opposite of `_.before`; this method creates a function that executes + * The opposite of `_.before`; this method creates a function that invokes * `func` only after it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of calls before `func` is executed. + * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -5589,13 +5584,13 @@ } /** - * Creates a function that executes `func`, with the `this` binding and + * Creates a function that invokes `func`, with the `this` binding and * arguments of the created function, until it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of times `func` may be executed. + * @param {number} n The number of times `func` may be called. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -5734,62 +5729,8 @@ } /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. - * - * @static - * @memberOf _ - * @category Function - * @param {...Function} [funcs] Functions to compose. - * @returns {Function} Returns the new composed function. - * @example - * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; - * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; - * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; - * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' - */ - function compose() { - var funcs = arguments, - length = funcs.length, - index = length - 1; - - if (!length) { - return function() {}; - } - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError(FUNC_ERROR_TEXT); - } - } - return function() { - length = index; - var result = funcs[length].apply(this, arguments); - - while (length--) { - result = funcs[length].call(this, result); - } - return result; - }; - } - - /** - * Creates a function which accepts one or more arguments of `func` that when - * invoked either executes `func` returning its result, if all `func` arguments + * Creates a function that accepts one or more arguments of `func` that when + * called either invokes `func` returning its result if all `func` arguments * have been provided, or returns a function that accepts one or more of the * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. @@ -5857,14 +5798,14 @@ } /** - * Creates a function that delays the execution of `func` until after `wait` + * Creates a function that delays the invocation of `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 calls. Provide an + * function comes with a `cancel` method to cancel delayed invokes. 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` call. + * debounced function return the result of the last `func` invocation. * - * **Note:** If `leading` and `trailing` options are `true`, `func` is called on + * **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 * invoked more than once during the `wait` timeout. * @@ -5877,11 +5818,11 @@ * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading + * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be - * delayed before it is called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * delayed before it is invoked. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example @@ -5889,13 +5830,13 @@ * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls + * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * }); * - * // ensure `batchLog` is executed once after 1 second of debounced calls + * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 @@ -6033,8 +5974,8 @@ } /** - * Defers executing the `func` function until the current call stack has - * cleared. Additional arguments are provided to `func` when it is invoked. + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -6056,14 +5997,14 @@ } /** - * Executes the `func` function after `wait` milliseconds. Additional arguments - * are provided to `func` when it is invoked. + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay execution. + * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example @@ -6079,12 +6020,102 @@ return setTimeout(function() { func.apply(undefined, args); }, wait); } + /** + * Creates a function that invokes the provided functions with the `this` + * binding of the created function, where each successive invocation is + * supplied the return value of the previous. + * + * @static + * @memberOf _ + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flow(add, square); + * addSquare(1, 2); + * // => 9 + */ + function flow() { + var funcs = arguments, + length = funcs.length; + + if (!length) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = 0, + result = funcs[index].apply(this, arguments); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + } + + /** + * This method is like `_.flow` except that it creates a function that + * invokes the provided functions from right to left. + * + * @static + * @memberOf _ + * @alias backflow, compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight(square, add); + * addSquare(1, 2); + * // => 9 + */ + function flowRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; + + if (fromIndex < 0) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = fromIndex, + result = funcs[index].apply(this, arguments); + + while (index--) { + result = funcs[index].call(this, result); + } + return result; + }; + } + /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the cache key. The `func` is - * executed with the `this` binding of the memoized function. The result cache + * invoked with the `this` binding of the memoized function. The result cache * is exposed as the `cache` property on the memoized function. * * @static @@ -6127,14 +6158,14 @@ return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); - } + }; memoized.cache = {}; return memoized; } /** * Creates a function that negates the result of the predicate `func`. The - * `func` function is executed with the `this` binding and arguments of the + * `func` predicate is invoked with the `this` binding and arguments of the * created function. * * @static @@ -6161,8 +6192,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls - * to the function return the value of the first call. The `func` is executed + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first call. The `func` is invoked * with the `this` binding of the created function. * * @static @@ -6176,17 +6207,17 @@ * var initialize = _.once(createApplication); * initialize(); * initialize(); - * // `initialize` executes `createApplication` once + * // `initialize` invokes `createApplication` once */ var once = partial(before, 2); /** - * Creates a function that invokes `func` with any additional `partial` arguments - * prepended to those provided to the new function. This method is similar to - * `_.bind` except it does **not** alter the `this` binding. + * Creates a function that invokes `func` with `partial` arguments prepended + * to those provided to the new function. This method is similar to `_.bind` + * except it does **not** alter the `this` binding. * - * **Note:** This method does not set the `length` property of partially applied - * functions. + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ @@ -6247,15 +6278,15 @@ } /** - * Creates a function that only calls the `func` function at most once per - * every `wait` milliseconds. The created function comes with a `cancel` method - * to cancel delayed calls. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * 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 invokes. 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 called on - * the trailing edge of the timeout only if the the throttled function is + * **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 * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) @@ -6265,11 +6296,11 @@ * @memberOf _ * @category Function * @param {Function} func The function to throttle. - * @param {number} wait The number of milliseconds to throttle executions to. + * @param {number} wait The number of milliseconds to throttle invocations to. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading + * @param {boolean} [options.leading=true] Specify invoking on the leading * edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example @@ -6277,7 +6308,7 @@ * // avoid excessively updating the position while scrolling * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * - * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes + * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) * jQuery('.interactive').on('click', throttled); * @@ -6305,9 +6336,9 @@ /** * Creates a function that provides `value` to the wrapper function as its - * first argument. Additional arguments provided to the function are appended - * to those provided to the wrapper function. The wrapper is executed with - * the `this` binding of the created function. + * first argument. Any additional arguments provided to the function are + * appended to those provided to the wrapper function. The wrapper is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ @@ -6333,7 +6364,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. - * If `customizer` is provided it is executed to produce the assigned values. + * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments; * (objectValue, sourceValue, key, object, source). * @@ -6363,7 +6394,7 @@ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is - * executed to produce the cloned values. If `customizer` returns `undefined` + * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * @@ -6425,7 +6456,7 @@ } /** - * Creates a deep clone of `value`. If `customizer` is provided it is executed + * Creates a deep clone of `value`. If `customizer` is provided it is invoked * to produce the cloned values. If `customizer` returns `undefined` cloning * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). @@ -6550,7 +6581,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6596,7 +6627,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -6628,7 +6659,7 @@ } /** - * Iterates over own and inherited enumerable properties of an object executing + * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. @@ -6637,7 +6668,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6669,7 +6700,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6692,7 +6723,7 @@ } /** - * Iterates over own enumerable properties of an object executing `iteratee` + * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. @@ -6701,7 +6732,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6726,7 +6757,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example @@ -6754,7 +6785,7 @@ * @example * * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + * // => ['all', 'any', 'bind', ...] */ function functions(object) { return baseFunctions(object, keysIn(object)); @@ -6845,7 +6876,8 @@ * // => false */ function isArguments(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && + var length = (value && typeof value == 'object') ? value.length : undefined; + return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER && toString.call(value) == argsClass) || false; } @@ -6981,7 +7013,7 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If `customizer` is provided it is executed to compare values. + * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). @@ -7175,12 +7207,7 @@ if (isFunction(value)) { return reNative.test(fnToString.call(value)); } - if (value && typeof value == 'object') { - return !('constructor' in value) && isHostObject(value) - ? reNative.test(value) - : reHostCtor.test(toString.call(value)); - } - return false; + return (value && typeof value == 'object' && reHostCtor.test(value)) || false; } /** @@ -7435,7 +7462,7 @@ * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -7468,8 +7495,8 @@ * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * overwrite property assignments of previous sources. If `customizer` is - * provided it is executed to produce the merged values of the destination - * and source properties. If `customizer` returns `undefined` merging is handled + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked * with five arguments; (objectValue, sourceValue, key, object, source). * @@ -7520,7 +7547,7 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` omitting the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -7529,7 +7556,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -7589,7 +7616,7 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` picking the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -7598,7 +7625,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -7626,7 +7653,7 @@ /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own - * enumerable properties through `iteratee`, with each execution potentially + * enumerable properties through `iteratee`, with each invocation potentially * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. @@ -7635,7 +7662,7 @@ * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -7808,7 +7835,7 @@ } /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to + * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional characters @@ -8437,7 +8464,7 @@ /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, and `'` in `string` to their + * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their * corresponding characters. * * **Note:** No other HTML entities are unescaped. To unescape additional HTML @@ -8463,7 +8490,7 @@ /*--------------------------------------------------------------------------*/ /** - * Attempts to execute `func`, returning either the result or the caught + * Attempts to invoke `func`, returning either the result or the caught * error object. * * @static @@ -8766,7 +8793,7 @@ * @example * * _.defer(function(stamp) { console.log(_.now() - stamp); }, _.now()); - * // => logs the number of milliseconds it took for the deferred function to be called + * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function() { return new Date().getTime(); @@ -9005,15 +9032,15 @@ } /** - * Executes the iteratee function `n` times, returning an array of the results - * of each execution. The `iteratee` is bound to `thisArg` and invoked with + * Invokes the iteratee function `n` times, returning an array of the results + * of each invocation. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iteratee`. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example @@ -9022,10 +9049,10 @@ * // => [3, 6, 4] * * _.times(3, function(n) { mage.castSpell(n); }); - * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively + * // => invokes `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively * * _.times(3, function(n) { this.cast(n); }, mage); - * // => also calls `mage.castSpell(n)` three times + * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; @@ -9085,7 +9112,6 @@ lodash.chain = chain; lodash.chunk = chunk; lodash.compact = compact; - lodash.compose = compose; lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; @@ -9103,6 +9129,8 @@ lodash.filter = filter; lodash.flatten = flatten; lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; lodash.forEach = forEach; lodash.forEachRight = forEachRight; lodash.forIn = forIn; @@ -9165,7 +9193,9 @@ lodash.zipObject = zipObject; // add aliases + lodash.backflow = flowRight; lodash.collect = map; + lodash.compose = flowRight; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 93c5c3717c..8a94581475 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -4,69 +4,69 @@ * Build: `lodash modern -o ./dist/lodash.js` */ ;(function(){function n(n,t){for(var r=-1,e=t.length,u=Array(e);++rt||typeof n=="undefined")return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) -}function v(n){for(var t=-1,r=n.length;++ti(t,a)&&c.push(a);return c}function qt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>T)return Gt(n,t); +}function f(n,t){for(var r=n.length;r--&&-1=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) +}function v(n){for(var t=-1,r=n.length;++ti(t,a)&&c.push(a);return c}function qt(n,t){var r=n?n.length:0;if(typeof r!="number"||-1>=r||r>T)return Ht(n,t); for(var e=-1,u=Nr(n);++e=r||r>T)return Qt(n,t);for(var e=Nr(n);r--&&false!==t(e[r],r,e););return n}function Zt(n,t){var r=true;return qt(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Kt(n,t){var r=[];return qt(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function Vt(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function Yt(n,t,r,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++e>>1,a=r(n[f]),c=e?a<=t:ao(l,s)&&((t||a)&&l.push(s),c.push(p))}return c}function sr(n,t){for(var r=-1,e=t(n),u=e.length,o=Be(u);++rt)return r; -var e=typeof arguments[2];if("number"!=e&&"string"!=e||!arguments[3]||arguments[3][arguments[2]]!==arguments[1]||(t=2),3e?ju(u+e,0):e||0;else if(e)return e=qr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function Mr(n){return zr(n,1) -}function zr(n,t,r){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),r=typeof r=="undefined"||r>o?o:+r||0,0>r&&(r+=o),r&&r==o&&!t)return e(n);for(o=t>r?0:r-t,r=Be(o);++ur?ju(e+r,0):r||0:0,typeof n=="string"||!Bu(n)&&Oe(n)?ru&&(u=f);else t=i&&f?o:xr(t,r,3),qt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n)});return u}function ee(n,t){return te(n,$e(t))}function ue(n,t,r,e){return(Bu(n)?St:fr)(n,xr(t,e,4),r,3>arguments.length,qt)}function oe(n,t,r,e){return(Bu(n)?Ct:fr)(n,xr(t,e,4),r,3>arguments.length,Pt) -}function ie(n){n=Nr(n);for(var t=-1,r=n.length,e=Be(r);++targuments.length)return Ar(n,w,null,t);var r=zr(arguments,2),e=Tr(r,ce.placeholder);return or(n,w|E,r,e,t)}function le(n,t){var r=w|j;if(2=r||r>t?(f&&iu(f),r=s,f=p=s=_,r&&(h=Vu(),a=n.apply(l,i),p||f||(i=l=null))):p=su(e,r)}function u(){p&&iu(p),f=p=s=_,(v||g!==t)&&(h=Vu(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=Vu(),l=this,s=v&&(p||!y),false===g)var r=y&&!p;else{f||y||(h=c);var o=g-(c-h),d=0>=o||o>g; -d?(f&&(f=iu(f)),h=c,a=n.apply(l,i)):f||(f=su(u,o))}return d&&p?p=iu(p):p||t===g||(p=su(e,t)),r&&(d=true,a=n.apply(l,i)),!d||p||f||(i=l=null),a}var i,f,a,c,l,p,s,h=0,g=false,v=true;if(!be(n))throw new Ye(C);if(t=0>t?0:t,true===r)var y=true,v=false;else we(r)&&(y=r.leading,g="maxWait"in r&&ju(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){p&&iu(p),f&&iu(f),f=p=s=_},o}function ge(n){var t=zr(arguments,1),r=Tr(t,ge.placeholder);return or(n,E,t,r)}function ve(n){var t=zr(arguments,1),r=Tr(t,ve.placeholder); -return or(n,I,t,r)}function ye(n){return nr(n,Ee(n))}function de(n){return n&&typeof n=="object"&&typeof n.length=="number"&&tu.call(n)==ut||false}function me(n){return n&&typeof n=="object"&&1===n.nodeType&&-1>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=Be(r),f=0t||null==n||!bu(t))return r;n=Ve(n);do t%2&&(r+=n),t=fu(t/2),n+=n;while(t);return r}function Se(n,t){return(n=null==n?"":Ve(n))?null==t?n.slice(v(n),y(n)+1):(t=Ve(t),n.slice(i(n,t),f(n,t)+1)):n}function Ce(n){try{return n()}catch(t){return _e(t)?t:Me(t)}}function Fe(n,t){return $t(n,t)}function Te(n){return n}function Ue(n){var t=zu(n),r=t.length; -if(1==r){var e=t[0],u=n[e];if(Sr(u))return function(n){return null!=n&&u===n[e]&&Qe.call(n,e)}}for(var o=r,i=Be(r),f=Be(r);o--;){var u=n[t[o]],a=Sr(u);i[o]=a,f[o]=a?u:Bt(u)}return function(n){if(o=r,null==n)return!o;for(;o--;)if(i[o]?f[o]!==n[t[o]]:!Qe.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!Qe.call(n,t[o]):!tr(f[o],n[t[o]],null,true))return false;return true}}function We(n,t,r){var e=true,u=we(t),o=null==r,i=o&&u&&zu(t),f=i&&nr(t,i);(i&&i.length&&!f.length||o&&!u)&&(o&&(r=t),f=false,t=n,n=this),f||(f=nr(t,zu(t))),false===r?e=false:we(r)&&"chain"in r&&(e=r.chain),r=-1,u=be(n); -for(o=f.length;++rk)return r}else n=0;return ar(r,e)}}(),Tu=yr(function(n,t,r){Qe.call(n,r)?++n[r]:n[r]=1}),Uu=yr(function(n,t,r){Qe.call(n,r)?n[r].push(t):n[r]=[t]}),Wu=yr(function(n,t,r){n[r]=t -}),Nu=yr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Lu=ge(ae,2),$u=dr(Lt),Bu=_u||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&tu.call(n)==ot||false};Su.dom||(me=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!Mu(n)||false});var Du=Ou||function(n){return typeof n=="number"&&bu(n)},Mu=au?function(n){if(!n||tu.call(n)!=lt)return false;var t=n.valueOf,r=je(t)&&(r=au(t))&&au(r);return r?n==r||au(n)==r:Ur(n)}:Ur,zu=wu?function(n){n=Lr(n);var t=n.constructor,r=n.length; -return t&&n===t.prototype||typeof r=="number"&&0--n?t.apply(this,arguments):void 0}},g.assign=$u,g.at=function(t){var r=t?t.length:0;return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),zr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--&&t(n[e],e,n););return zr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=xr(t,r,3);++e(s?u(s,a):i(p,a))){for(t=e;--t;){var h=o[t];if(0>(h?u(h,a):i(n[t],a)))continue n}s&&s.push(a),p.push(a)}return p},g.invert=function(n,t){for(var r=-1,e=zu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),zr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--&&t(n[e],e,n););return zr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=xr(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Ve(n),M.lastIndex=0,M.test(n)?n.replace(M,s):n},g.escapeRegExp=ke,g.every=Jr,g.find=Gr,g.findIndex=$r,g.findKey=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Gt,true)},g.findLast=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Pt)},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--;)if(t(n[e],e,n))return e; -return-1},g.findLastKey=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Qt,true)},g.findWhere=function(n,t){return Gr(n,Ue(t))},g.first=Br,g.has=function(n,t){return n?Qe.call(n,t):false},g.identity=Te,g.indexOf=Dr,g.isArguments=de,g.isArray=Bu,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&tu.call(n)==it||false},g.isDate=function(n){return n&&typeof n=="object"&&tu.call(n)==ft||false},g.isElement=me,g.isEmpty=function(n){if(null==n)return true;var t=n.length;return typeof t=="number"&&-1r?ju(u+r,0):Au(r||0,u-1))+1; -else if(r)return u=Pr(n,t)-1,e&&n[u]===t?u:-1;for(r=t===t;u--;)if(e=n[u],r?e===t:e!==e)return u;return-1},g.max=re,g.min=function(n,t,r){var e=1/0,u=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,f=!(i&&Bu(n))&&Oe(n);if(i&&!f)for(r=-1,n=Nr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=$u({},r||t,e,Nt),n=Ve(null==n?"":n),r=$u({},t.imports,e.imports,Nt); -var u,o,i=zu(r),f=Ie(r),a=0;r=t.interpolate||X;var c="__p+='";if(r=Ke((t.escape||X).source+"|"+r.source+"|"+(r===P?Z:X).source+"|"+(t.evaluate||X).source+"|$","g"),n.replace(r,function(t,r,e,i,f,l){return e||(e=i),c+=n.slice(a,l).replace(nt,h),r&&(u=true,c+="'+__e("+r+")+'"),f&&(o=true,c+="';"+f+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),a=l+t.length,t}),c+="';",(t=t.variable)||(c="with(obj){"+c+"}"),c=(o?c.replace(L,""):c).replace($,"$1").replace(B,"$1;"),c="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}",t=Ce(function(){return ze(i,"return "+c).apply(_,f) -}),t.source=c,_e(t))throw t;return t},g.trim=Se,g.trimLeft=function(n,t){return(n=null==n?"":Ve(n))?null==t?n.slice(v(n)):(t=Ve(t),n.slice(i(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Ve(n))?null==t?n.slice(0,y(n)+1):(t=Ve(t),n.slice(0,f(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(we(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Ve(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Ve(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; -if(r=n.slice(0,o),null==u)return r+e;if(xe(u)){if(n.slice(o).search(u)){var i,f,a=n.slice(0,o);for(u.global||(u=Ke(u.source,(K.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(a);)f=i.index;r=r.slice(0,null==f?o:f)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},Gt(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new J(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=Yr,g.prototype.toString=function(){return Ve(this.__wrapped__) -},g.prototype.value=Yr,g.prototype.valueOf=Yr,tt(["join","pop","shift"],function(n){var t=He[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new J(r,n):r}}),tt(["push","reverse","sort","unshift"],function(n){var t=He[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),tt(["concat","splice"],function(n){var t=He[n];g.prototype[n]=function(){return new J(t.apply(this.__wrapped__,arguments),this.__chain__)}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,O=16,E=32,I=64,k=150,R=16,S="__lodash_"+b.replace(/[-.]/g,"_")+"__",C="Expected a function",F=Math.pow(2,32)-1,T=Math.pow(2,53)-1,U="__lodash_placeholder__",W=0,N=/^[A-Z]+$/,L=/\b__p\+='';/g,$=/\b(__p\+=)''\+/g,B=/(__e\(.*?\)|\b__t\))\+'';/g,D=/&(?:amp|lt|gt|quot|#39|#96);/g,M=/[&<>"'`]/g,z=/<%-([\s\S]+?)%>/g,q=/<%([\s\S]+?)%>/g,P=/<%=([\s\S]+?)%>/g,Z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,Y=/^0[xX]/,H=/^\[object .+?Constructor\]$/,J=/[\xC0-\xFF]/g,X=/($^)/,G=/[.*+?^${}()|[\]\/\\]/g,Q=/\bthis\b/,nt=/['\n\r\u2028\u2029\\]/g,tt=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,rt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",et="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),ut="[object Arguments]",ot="[object Array]",it="[object Boolean]",ft="[object Date]",at="[object Error]",ct="[object Number]",lt="[object Object]",pt="[object RegExp]",st="[object String]",ht="[object ArrayBuffer]",gt="[object Float32Array]",vt="[object Float64Array]",yt="[object Int8Array]",dt="[object Int16Array]",mt="[object Int32Array]",_t="[object Uint8Array]",bt="[object Uint8ClampedArray]",wt="[object Uint16Array]",jt="[object Uint32Array]",At={}; -At[ut]=At[ot]=At[gt]=At[vt]=At[yt]=At[dt]=At[mt]=At[_t]=At[bt]=At[wt]=At[jt]=true,At[ht]=At[it]=At[ft]=At[at]=At["[object Function]"]=At["[object Map]"]=At[ct]=At[lt]=At[pt]=At["[object Set]"]=At[st]=At["[object WeakMap]"]=false;var xt={};xt[ut]=xt[ot]=xt[ht]=xt[it]=xt[ft]=xt[gt]=xt[vt]=xt[yt]=xt[dt]=xt[mt]=xt[ct]=xt[lt]=xt[pt]=xt[st]=xt[_t]=xt[bt]=xt[wt]=xt[jt]=true,xt[at]=xt["[object Function]"]=xt["[object Map]"]=xt["[object Set]"]=xt["[object WeakMap]"]=false;var Ot={leading:false,maxWait:0,trailing:false},Et={configurable:false,enumerable:false,value:null,writable:false},It={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},kt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Rt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},St={"function":true,object:true},Ct={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ft=St[typeof window]&&window||this,Tt=St[typeof exports]&&exports&&!exports.nodeType&&exports,St=St[typeof module]&&module&&!module.nodeType&&module,Ut=Tt&&St&&typeof global=="object"&&global; +if(f&&typeof f=="object"&&typeof f.length=="number"&&(Du(f)||me(f))){t&&(f=Yt(f,t,r));var a=-1,c=f.length;for(i.length+=c;++al))return false}else{var g=s&&nu.call(n,"__wrapped__"),h=h&&nu.call(t,"__wrapped__"); +if(g||h)return tr(g?n.__wrapped__:n,h?t.__wrapped__:t,r,e,u,o);if(!p)return false;if(!f&&!s){switch(c){case it:case ft:return+n==+t;case ct:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case pt:case st:return n==Ye(t)}return false}if(g=l?Ke:n.constructor,c=i?Ke:t.constructor,f){if(g.prototype.name!=c.prototype.name)return false}else if(s=!l&&nu.call(n,"constructor"),h=!i&&nu.call(t,"constructor"),s!=h||!(s||g==c||we(g)&&g instanceof g&&we(c)&&c instanceof c)&&"constructor"in n&&"constructor"in t)return false;if(g=f?["message","name"]:qu(n),c=f?g:qu(t),l&&g.push("length"),i&&c.push("length"),l=g.length,s=c.length,l!=s&&!e)return false +}for(u||(u=[]),o||(o=[]),c=u.length;c--;)if(u[c]==n)return o[c]==t;if(u.push(n),o.push(t),i=true,a)for(;i&&++c>>1,a=r(n[f]),c=e?a<=t:ao(l,s)&&((t||a)&&l.push(s),c.push(p))}return c}function sr(n,t){for(var r=-1,e=t(n),u=e.length,o=De(u);++rt)return r; +var e=typeof arguments[2];if("number"!=e&&"string"!=e||!arguments[3]||arguments[3][arguments[2]]!==arguments[1]||(t=2),3e?Au(u+e,0):e||0;else if(e)return e=qr(n,t),u&&n[e]===t?e:-1;return r(n,t,e)}function Mr(n){return zr(n,1)}function zr(n,t,r){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),r=typeof r=="undefined"||r>o?o:+r||0,0>r&&(r+=o),r&&r==o&&!t)return e(n);for(o=t>r?0:r-t,r=De(o);++ur?Au(e+r,0):r||0:0,typeof n=="string"||!Du(n)&&Oe(n)?ru&&(u=f);else t=i&&f?o:xr(t,r,3),qt(n,function(n,r,o){r=t(n,r,o),(r>e||-1/0===r&&r===u)&&(e=r,u=n) +});return u}function ee(n,t){return te(n,Be(t))}function ue(n,t,r,e){return(Du(n)?St:fr)(n,xr(t,e,4),r,3>arguments.length,qt)}function oe(n,t,r,e){return(Du(n)?Ct:fr)(n,xr(t,e,4),r,3>arguments.length,Pt)}function ie(n){n=Nr(n);for(var t=-1,r=n.length,e=De(r);++targuments.length)return Ar(n,w,null,t);var r=zr(arguments,2),e=Tr(r,ce.placeholder);return or(n,w|O,r,e,t)}function le(n,t){var r=w|j;if(2=r||r>t?(f&&fu(f),r=s,f=p=s=_,r&&(h=Yu(),a=n.apply(l,i),p||f||(i=l=null))):p=hu(e,r) +}function u(){p&&fu(p),f=p=s=_,(v||g!==t)&&(h=Yu(),a=n.apply(l,i),p||f||(i=l=null))}function o(){if(i=arguments,c=Yu(),l=this,s=v&&(p||!y),false===g)var r=y&&!p;else{f||y||(h=c);var o=g-(c-h),d=0>=o||o>g;d?(f&&(f=fu(f)),h=c,a=n.apply(l,i)):f||(f=hu(u,o))}return d&&p?p=fu(p):p||t===g||(p=hu(e,t)),r&&(d=true,a=n.apply(l,i)),!d||p||f||(i=l=null),a}var i,f,a,c,l,p,s,h=0,g=false,v=true;if(!we(n))throw new Je(C);if(t=0>t?0:t,true===r)var y=true,v=false;else je(r)&&(y=r.leading,g="maxWait"in r&&Au(+r.maxWait||0,t),v="trailing"in r?r.trailing:v); +return o.cancel=function(){p&&fu(p),f&&fu(f),f=p=s=_},o}function ge(){var n=arguments,t=n.length-1;if(0>t)return function(){};if(!It(n,we))throw new Je(C);return function(){for(var r=t,e=n[r].apply(this,arguments);r--;)e=n[r].call(this,e);return e}}function ve(n){var t=zr(arguments,1),r=Tr(t,ve.placeholder);return or(n,O,t,r)}function ye(n){var t=zr(arguments,1),r=Tr(t,ye.placeholder);return or(n,I,t,r)}function de(n){return nr(n,Ie(n))}function me(n){var t=n&&typeof n=="object"?n.length:_;return typeof t=="number"&&-1>>0,e=n.constructor,u=-1,e=e&&n===e.prototype,o=r-1,i=De(r),f=0t||null==n||!wu(t))return r;n=Ye(n);do t%2&&(r+=n),t=au(t/2),n+=n;while(t);return r}function Ce(n,t){return(n=null==n?"":Ye(n))?null==t?n.slice(v(n),y(n)+1):(t=Ye(t),n.slice(i(n,t),f(n,t)+1)):n}function Fe(n){try{return n()}catch(t){return be(t)?t:ze(t)}}function Te(n,t){return $t(n,t)}function Ue(n){return n}function We(n){var t=qu(n),r=t.length;if(1==r){var e=t[0],u=n[e];if(Sr(u))return function(n){return null!=n&&u===n[e]&&nu.call(n,e)}}for(var o=r,i=De(r),f=De(r);o--;){var u=n[t[o]],a=Sr(u); +i[o]=a,f[o]=a?u:Bt(u)}return function(n){if(o=r,null==n)return!o;for(;o--;)if(i[o]?f[o]!==n[t[o]]:!nu.call(n,t[o]))return false;for(o=r;o--;)if(i[o]?!nu.call(n,t[o]):!tr(f[o],n[t[o]],null,true))return false;return true}}function Ne(n,t,r){var e=true,u=je(t),o=null==r,i=o&&u&&qu(t),f=i&&nr(t,i);(i&&i.length&&!f.length||o&&!u)&&(o&&(r=t),f=false,t=n,n=this),f||(f=nr(t,qu(t))),false===r?e=false:je(r)&&"chain"in r&&(e=r.chain),r=-1,u=we(n);for(o=f.length;++r=k)return r}else n=0;return ar(r,e)}}(),Uu=yr(function(n,t,r){nu.call(n,r)?++n[r]:n[r]=1}),Wu=yr(function(n,t,r){nu.call(n,r)?n[r].push(t):n[r]=[t]}),Nu=yr(function(n,t,r){n[r]=t}),Lu=yr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),$u=ve(ae,2),Bu=dr(Lt),Du=bu||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ru.call(n)==ot||false +};Cu.dom||(_e=function(n){return n&&typeof n=="object"&&1===n.nodeType&&!zu(n)||false});var Mu=Ou||function(n){return typeof n=="number"&&wu(n)},zu=cu?function(n){if(!n||ru.call(n)!=lt)return false;var t=n.valueOf,r=Ae(t)&&(r=cu(t))&&cu(r);return r?n==r||cu(n)==r:Ur(n)}:Ur,qu=ju?function(n){n=Lr(n);var t=n.constructor,r=n.length;return t&&n===t.prototype||typeof r=="number"&&0--n?t.apply(this,arguments):void 0}},g.assign=Bu,g.at=function(t){var r=t?t.length:0; +return typeof r=="number"&&-1t?0:t)},g.dropRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),zr(n,0,0>t?0:t)},g.dropRightWhile=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--&&t(n[e],e,n););return zr(n,0,e+1)},g.dropWhile=function(n,t,r){var e=-1,u=n?n.length:0;for(t=xr(t,r,3);++e(s?u(s,a):i(p,a))){for(t=e;--t;){var h=o[t]; +if(0>(h?u(h,a):i(n[t],a)))continue n}s&&s.push(a),p.push(a)}return p},g.invert=function(n,t){for(var r=-1,e=qu(n),u=e.length,o={};++rt?0:t)},g.takeRight=function(n,t,r){var e=n?n.length:0;return t=e-((null==t||r?1:t)||0),zr(n,0>t?0:t)},g.takeRightWhile=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--&&t(n[e],e,n););return zr(n,e+1)},g.takeWhile=function(n,t,r){var e=-1,u=n?n.length:0; +for(t=xr(t,r,3);++er?0:+r||0,e))-t.length,0<=r&&n.indexOf(t,r)==r},g.escape=function(n){return n=null==n?"":Ye(n),M.lastIndex=0,M.test(n)?n.replace(M,s):n},g.escapeRegExp=Re,g.every=Xr,g.find=Hr,g.findIndex=$r,g.findKey=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Ht,true)},g.findLast=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Pt) +},g.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=xr(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},g.findLastKey=function(n,t,r){return t=xr(t,r,3),Vt(n,t,Qt,true)},g.findWhere=function(n,t){return Hr(n,We(t))},g.first=Br,g.has=function(n,t){return n?nu.call(n,t):false},g.identity=Ue,g.indexOf=Dr,g.isArguments=me,g.isArray=Du,g.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ru.call(n)==it||false},g.isDate=function(n){return n&&typeof n=="object"&&ru.call(n)==ft||false},g.isElement=_e,g.isEmpty=function(n){if(null==n)return true; +var t=n.length;return typeof t=="number"&&-1r?Au(u+r,0):xu(r||0,u-1))+1;else if(r)return u=Pr(n,t)-1,e&&n[u]===t?u:-1;for(r=t===t;u--;)if(e=n[u],r?e===t:e!==e)return u;return-1},g.max=re,g.min=function(n,t,r){var e=1/0,u=e,i=typeof t;"number"!=i&&"string"!=i||!r||r[t]!==n||(t=null);var i=null==t,f=!(i&&Du(n))&&Oe(n);if(i&&!f)for(r=-1,n=Nr(n),i=n.length;++rr?0:+r||0,n.length),n.lastIndexOf(t,r)==r},g.template=function(n,t,r){var e=g.templateSettings;t=Bu({},r||t,e,Nt),n=Ye(null==n?"":n),r=Bu({},t.imports,e.imports,Nt); +var u,o,i=qu(r),f=ke(r),a=0;r=t.interpolate||G;var c="__p+='";if(r=Ve((t.escape||G).source+"|"+r.source+"|"+(r===P?Z:G).source+"|"+(t.evaluate||G).source+"|$","g"),n.replace(r,function(t,r,e,i,f,l){return e||(e=i),c+=n.slice(a,l).replace(nt,h),r&&(u=true,c+="'+__e("+r+")+'"),f&&(o=true,c+="';"+f+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),a=l+t.length,t}),c+="';",(t=t.variable)||(c="with(obj){"+c+"}"),c=(o?c.replace(L,""):c).replace($,"$1").replace(B,"$1;"),c="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}",t=Fe(function(){return qe(i,"return "+c).apply(_,f) +}),t.source=c,be(t))throw t;return t},g.trim=Ce,g.trimLeft=function(n,t){return(n=null==n?"":Ye(n))?null==t?n.slice(v(n)):(t=Ye(t),n.slice(i(n,t))):n},g.trimRight=function(n,t){return(n=null==n?"":Ye(n))?null==t?n.slice(0,y(n)+1):(t=Ye(t),n.slice(0,f(n,t)+1)):n},g.trunc=function(n,t){var r=30,e="...";if(je(t))var u="separator"in t?t.separator:u,r="length"in t?+t.length||0:r,e="omission"in t?Ye(t.omission):e;else null!=t&&(r=+t||0);if(n=null==n?"":Ye(n),r>=n.length)return n;var o=r-e.length;if(1>o)return e; +if(r=n.slice(0,o),null==u)return r+e;if(Ee(u)){if(n.slice(o).search(u)){var i,f,a=n.slice(0,o);for(u.global||(u=Ve(u.source,(K.exec(u)||"")+"g")),u.lastIndex=0;i=u.exec(a);)f=i.index;r=r.slice(0,null==f?o:f)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),-1t?0:+t||0,n.length),n)},Ht(g,function(n,t){var r="sample"!=t;g.prototype[t]||(g.prototype[t]=function(t,e){var u=this.__chain__,o=n(this.__wrapped__,t,e);return u||null!=t&&(!e||r&&typeof t=="function")?new X(o,u):o})}),g.VERSION=b,g.prototype.chain=function(){return this.__chain__=true,this},g.prototype.toJSON=Yr,g.prototype.toString=function(){return Ye(this.__wrapped__) +},g.prototype.value=Yr,g.prototype.valueOf=Yr,tt(["join","pop","shift"],function(n){var t=Xe[n];g.prototype[n]=function(){var n=this.__chain__,r=t.apply(this.__wrapped__,arguments);return n?new X(r,n):r}}),tt(["push","reverse","sort","unshift"],function(n){var t=Xe[n];g.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),tt(["concat","splice"],function(n){var t=Xe[n];g.prototype[n]=function(){return new X(t.apply(this.__wrapped__,arguments),this.__chain__)}}),g}var _,b="3.0.0-pre",w=1,j=2,A=4,x=8,E=16,O=32,I=64,k=150,R=16,S="__lodash_"+b.replace(/[-.]/g,"_")+"__",C="Expected a function",F=Math.pow(2,32)-1,T=Math.pow(2,53)-1,U="__lodash_placeholder__",W=0,N=/^[A-Z]+$/,L=/\b__p\+='';/g,$=/\b(__p\+=)''\+/g,B=/(__e\(.*?\)|\b__t\))\+'';/g,D=/&(?:amp|lt|gt|quot|#39|#96);/g,M=/[&<>"'`]/g,z=/<%-([\s\S]+?)%>/g,q=/<%([\s\S]+?)%>/g,P=/<%=([\s\S]+?)%>/g,Z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,Y=/^0[xX]/,J=/^\[object .+?Constructor\]$/,X=/[\xC0-\xFF]/g,G=/($^)/,H=/[.*+?^${}()|[\]\/\\]/g,Q=/\bthis\b/,nt=/['\n\r\u2028\u2029\\]/g,tt=/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,rt=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",et="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),ut="[object Arguments]",ot="[object Array]",it="[object Boolean]",ft="[object Date]",at="[object Error]",ct="[object Number]",lt="[object Object]",pt="[object RegExp]",st="[object String]",ht="[object ArrayBuffer]",gt="[object Float32Array]",vt="[object Float64Array]",yt="[object Int8Array]",dt="[object Int16Array]",mt="[object Int32Array]",_t="[object Uint8Array]",bt="[object Uint8ClampedArray]",wt="[object Uint16Array]",jt="[object Uint32Array]",At={}; +At[ut]=At[ot]=At[gt]=At[vt]=At[yt]=At[dt]=At[mt]=At[_t]=At[bt]=At[wt]=At[jt]=true,At[ht]=At[it]=At[ft]=At[at]=At["[object Function]"]=At["[object Map]"]=At[ct]=At[lt]=At[pt]=At["[object Set]"]=At[st]=At["[object WeakMap]"]=false;var xt={};xt[ut]=xt[ot]=xt[ht]=xt[it]=xt[ft]=xt[gt]=xt[vt]=xt[yt]=xt[dt]=xt[mt]=xt[ct]=xt[lt]=xt[pt]=xt[st]=xt[_t]=xt[bt]=xt[wt]=xt[jt]=true,xt[at]=xt["[object Function]"]=xt["[object Map]"]=xt["[object Set]"]=xt["[object WeakMap]"]=false;var Et={leading:false,maxWait:0,trailing:false},Ot={configurable:false,enumerable:false,value:null,writable:false},It={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},kt={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Rt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"AE","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\xd7":" ","\xf7":" "},St={"function":true,object:true},Ct={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ft=St[typeof window]&&window||this,Tt=St[typeof exports]&&exports&&!exports.nodeType&&exports,St=St[typeof module]&&module&&!module.nodeType&&module,Ut=Tt&&St&&typeof global=="object"&&global; !Ut||Ut.global!==Ut&&Ut.window!==Ut&&Ut.self!==Ut||(Ft=Ut);var Ut=St&&St.exports===Tt&&Tt,Wt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Ft._=Wt, define(function(){return Wt})):Tt&&St?Ut?(St.exports=Wt)._=Wt:Tt._=Wt:Ft._=Wt}).call(this); \ No newline at end of file diff --git a/dist/lodash.underscore.js b/dist/lodash.underscore.js index d1a8226434..32ce69e613 100644 --- a/dist/lodash.underscore.js +++ b/dist/lodash.underscore.js @@ -120,7 +120,7 @@ * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. - * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) + * See [Mathias Bynens's article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in Internet Explorer < 9, they can break out @@ -348,25 +348,25 @@ * * The chainable wrapper functions are: * `after`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, - * `chain`, `chunk`, `compact`, `compose`, `concat`, `constant`, `countBy`, - * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, - * `flattenDeep`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, - * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, - * `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, `matches`, `memoize`, - * `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, - * `partialRight`, `partition`, `pick`, `pluck`, `property`, `pull`, `pullAt`, - * `push`, `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, - * `sort`, `sortBy`, `splice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, - * `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, - * `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, - * and `zipObject` + * `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `drop`, + * `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, `flattenDeep`, + * `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, + * `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, + * `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, + * `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, + * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `pluck`, `property`, + * `pull`, `pullAt`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `times`, `toArray`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, + * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, - * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, + * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, @@ -449,18 +449,6 @@ * @type boolean */ support.spliceObjects = (splice.call(object, 0, 1), !object[0]); - - /** - * Detect if the host objects are detectable (IE < 9). - * - * @memberOf _.support - * @type boolean - */ - try { - support.hostObject = !({ 'toString': 0 } + ''); - } catch(e) { - support.hostObject = false; - } }(0, 0)); /** @@ -515,7 +503,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { @@ -536,7 +524,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -558,7 +546,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { @@ -578,7 +566,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { @@ -602,7 +590,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the first element of * `array` as the initial value. @@ -627,7 +615,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray=false] Specify using the last element of * `array` as the initial value. @@ -651,7 +639,7 @@ * * @private * @param {Array} array The array to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -788,7 +776,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, iteratee) { @@ -813,7 +801,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, iteratee) { @@ -836,7 +824,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ @@ -856,7 +844,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { @@ -877,7 +865,7 @@ * * @private * @param {Array|Object|string} collection The collection to search. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey=false] Specify returning the key of the found * element instead of the element itself. @@ -937,13 +925,13 @@ /** * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` executing `iteratee` for + * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -967,7 +955,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ @@ -990,7 +978,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { @@ -1003,7 +991,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { @@ -1016,7 +1004,7 @@ * * @private * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { @@ -1199,7 +1187,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { @@ -1254,7 +1242,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. @@ -1276,7 +1264,7 @@ * * @private * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ @@ -1297,7 +1285,7 @@ * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iteratee The function called per iteration. + * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted @@ -1335,7 +1323,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, iteratee) { @@ -1611,7 +1599,7 @@ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function - * is executed with the arguments and its result is returned. + * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. @@ -1651,7 +1639,7 @@ * * @private * @param {Object} object The source object. - * @param {Function} predicate The function called per iteration. + * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { @@ -1718,7 +1706,7 @@ * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function called per iteration. + * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function sortedUniq(array, iteratee) { @@ -1875,7 +1863,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -2215,7 +2203,7 @@ /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order - * of the array. If an iteratee function is provided it is executed for `value` + * of the array. If an iteratee function is provided it is invoked for `value` * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * @@ -2231,7 +2219,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -2315,7 +2303,7 @@ * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster * search algorithm for sorted arrays. If an iteratee function is provided it - * is executed for each value in the array to generate the criterion by which + * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * @@ -2336,7 +2324,7 @@ * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -2661,7 +2649,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -2698,7 +2686,7 @@ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -2747,7 +2735,7 @@ * @alias select * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -2794,7 +2782,7 @@ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -2858,8 +2846,8 @@ } /** - * Iterates over elements of `collection` executing `iteratee` for each - * element. The `iteratee` is bound to `thisArg` and invoked with three arguments; + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -2872,7 +2860,7 @@ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example @@ -2907,7 +2895,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -2950,7 +2938,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -2977,9 +2965,9 @@ /** * Invokes the method named by `methodName` on each element in the collection, - * returning an array of the results of each invoked method. Additional arguments - * is provided to each invoked method. If `methodName` is a function it is - * invoked for, and `this` bound to, each element in the 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 the collection. * * @static * @memberOf _ @@ -3018,7 +3006,7 @@ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=identity] The function called + * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -3050,7 +3038,7 @@ /** * Retrieves the maximum value of `collection`. If the collection is empty * or falsey `-Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -3065,7 +3053,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -3128,7 +3116,7 @@ /** * Retrieves the minimum value of `collection`. If the collection is empty * or falsey `Infinity` is returned. If an iteratee function is provided it - * is executed for each value in the collection to generate the criterion by + * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * @@ -3143,7 +3131,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee] The function called per iteration. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. @@ -3220,7 +3208,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3277,7 +3265,7 @@ /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through `iteratee`, where each successive - * execution consumes the return value of the previous execution. If `accumulator` + * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of the collection is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). @@ -3287,7 +3275,7 @@ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -3316,7 +3304,7 @@ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. @@ -3346,7 +3334,7 @@ * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3484,7 +3472,7 @@ * @alias any * @category Collection * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=identity] The function called + * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -3538,7 +3526,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=identity] The function - * called per iteration. If property name(s) or an object is provided it + * invoked per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. @@ -3642,13 +3630,13 @@ /*--------------------------------------------------------------------------*/ /** - * The opposite of `_.before`; this method creates a function that executes + * The opposite of `_.before`; this method creates a function that invokes * `func` only after it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of calls before `func` is executed. + * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -3677,13 +3665,13 @@ } /** - * Creates a function that executes `func`, with the `this` binding and + * Creates a function that invokes `func`, with the `this` binding and * arguments of the created function, until it is called `n` times. * * @static * @memberOf _ * @category Function - * @param {number} n The number of times `func` may be executed. + * @param {number} n The number of times `func` may be called. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example @@ -3772,68 +3760,14 @@ } /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. - * - * @static - * @memberOf _ - * @category Function - * @param {...Function} [funcs] Functions to compose. - * @returns {Function} Returns the new composed function. - * @example - * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; - * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; - * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; - * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' - */ - function compose() { - var funcs = arguments, - length = funcs.length, - index = length - 1; - - if (!length) { - return function() {}; - } - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError(FUNC_ERROR_TEXT); - } - } - return function() { - length = index; - var result = funcs[length].apply(this, arguments); - - while (length--) { - result = funcs[length].call(this, result); - } - return result; - }; - } - - /** - * Creates a function that delays the execution of `func` until after `wait` + * Creates a function that delays the invocation of `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 calls. Provide an + * function comes with a `cancel` method to cancel delayed invokes. 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` call. + * debounced function return the result of the last `func` invocation. * - * **Note:** If `leading` and `trailing` options are `true`, `func` is called on + * **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 * invoked more than once during the `wait` timeout. * @@ -3846,11 +3780,11 @@ * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading + * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be - * delayed before it is called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * delayed before it is invoked. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example @@ -3858,13 +3792,13 @@ * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls + * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * }); * - * // ensure `batchLog` is executed once after 1 second of debounced calls + * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 @@ -4002,8 +3936,8 @@ } /** - * Defers executing the `func` function until the current call stack has - * cleared. Additional arguments are provided to `func` when it is invoked. + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -4025,14 +3959,14 @@ } /** - * Executes the `func` function after `wait` milliseconds. Additional arguments - * are provided to `func` when it is invoked. + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay execution. + * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example @@ -4048,12 +3982,57 @@ return setTimeout(function() { func.apply(undefined, args); }, wait); } + /** + * This method is like `_.flow` except that it creates a function that + * invokes the provided functions from right to left. + * + * @static + * @memberOf _ + * @alias backflow, compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. + * @example + * + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight(square, add); + * addSquare(1, 2); + * // => 9 + */ + function flowRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; + + if (fromIndex < 0) { + return function() {}; + } + if (!arrayEvery(funcs, isFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = fromIndex, + result = funcs[index].apply(this, arguments); + + while (index--) { + result = funcs[index].call(this, result); + } + return result; + }; + } + /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the cache key. The `func` is - * executed with the `this` binding of the memoized function. The result cache + * invoked with the `this` binding of the memoized function. The result cache * is exposed as the `cache` property on the memoized function. * * @static @@ -4100,8 +4079,8 @@ } /** - * Creates a function that is restricted to execute `func` once. Repeat calls - * to the function return the value of the first call. The `func` is executed + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first call. The `func` is invoked * with the `this` binding of the created function. * * @static @@ -4115,17 +4094,17 @@ * var initialize = _.once(createApplication); * initialize(); * initialize(); - * // `initialize` executes `createApplication` once + * // `initialize` invokes `createApplication` once */ var once = partial(before, 2); /** - * Creates a function that invokes `func` with any additional `partial` arguments - * prepended to those provided to the new function. This method is similar to - * `_.bind` except it does **not** alter the `this` binding. + * Creates a function that invokes `func` with `partial` arguments prepended + * to those provided to the new function. This method is similar to `_.bind` + * except it does **not** alter the `this` binding. * - * **Note:** This method does not set the `length` property of partially applied - * functions. + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ @@ -4148,15 +4127,15 @@ } /** - * Creates a function that only calls the `func` function at most once per - * every `wait` milliseconds. The created function comes with a `cancel` method - * to cancel delayed calls. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * 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 invokes. 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 called on - * the trailing edge of the timeout only if the the throttled function is + * **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 * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) @@ -4166,11 +4145,11 @@ * @memberOf _ * @category Function * @param {Function} func The function to throttle. - * @param {number} wait The number of milliseconds to throttle executions to. + * @param {number} wait The number of milliseconds to throttle invocations to. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify execution on the leading + * @param {boolean} [options.leading=true] Specify invoking on the leading * edge of the timeout. - * @param {boolean} [options.trailing=true] Specify execution on the trailing + * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example @@ -4178,7 +4157,7 @@ * // avoid excessively updating the position while scrolling * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * - * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes + * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) * jQuery('.interactive').on('click', throttled); * @@ -4207,9 +4186,9 @@ /** * Creates a function that provides `value` to the wrapper function as its - * first argument. Additional arguments provided to the function are appended - * to those provided to the wrapper function. The wrapper is executed with - * the `this` binding of the created function. + * first argument. Any additional arguments provided to the function are + * appended to those provided to the wrapper function. The wrapper is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ @@ -4235,7 +4214,7 @@ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. - * If `customizer` is provided it is executed to produce the assigned values. + * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments; * (objectValue, sourceValue, key, object, source). * @@ -4284,7 +4263,7 @@ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is - * executed to produce the cloned values. If `customizer` returns `undefined` + * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * @@ -4388,7 +4367,7 @@ * @example * * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + * // => ['all', 'any', 'bind', ...] */ function functions(object) { return baseFunctions(object, keysIn(object)); @@ -4468,7 +4447,8 @@ * // => false */ function isArguments(value) { - return (value && typeof value == 'object' && typeof value.length == 'number' && + var length = (value && typeof value == 'object') ? value.length : undefined; + return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER && toString.call(value) == argsClass) || false; } // fallback for environments without a `[[Class]]` for `arguments` objects @@ -4603,7 +4583,7 @@ /** * Performs a deep comparison between two values to determine if they are - * equivalent. If `customizer` is provided it is executed to compare values. + * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). @@ -4801,12 +4781,7 @@ if (isFunction(value)) { return reNative.test(fnToString.call(value)); } - if (value && typeof value == 'object') { - return !('constructor' in value) && isHostObject(value) - ? reNative.test(value) - : reHostCtor.test(toString.call(value)); - } - return false; + return (value && typeof value == 'object' && reHostCtor.test(value)) || false; } /** @@ -4976,7 +4951,7 @@ /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` omitting the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -4985,7 +4960,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5040,7 +5015,7 @@ /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of - * property names. If a predicate is provided it is executed for each property + * property names. If a predicate is provided it is invoked for each property * of `object` picking the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). @@ -5049,7 +5024,7 @@ * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function called per + * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. @@ -5097,7 +5072,7 @@ /*--------------------------------------------------------------------------*/ /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to + * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional characters @@ -5297,7 +5272,7 @@ /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, and `'` in `string` to their + * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their * corresponding characters. * * **Note:** No other HTML entities are unescaped. To unescape additional HTML @@ -5323,7 +5298,7 @@ /*--------------------------------------------------------------------------*/ /** - * Attempts to execute `func`, returning either the result or the caught + * Attempts to invoke `func`, returning either the result or the caught * error object. * * @static @@ -5521,7 +5496,7 @@ * @example * * _.defer(function(stamp) { console.log(_.now() - stamp); }, _.now()); - * // => logs the number of milliseconds it took for the deferred function to be called + * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function() { return new Date().getTime(); @@ -5700,15 +5675,15 @@ } /** - * Executes the iteratee function `n` times, returning an array of the results - * of each execution. The `iteratee` is bound to `thisArg` and invoked with + * Invokes the iteratee function `n` times, returning an array of the results + * of each invocation. The `iteratee` is bound to `thisArg` and invoked with * one argument; (index). * * @static * @memberOf _ * @category Utility - * @param {number} n The number of times to execute `iteratee`. - * @param {Function} [iteratee=identity] The function called per iteration. + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the array of results. * @example @@ -5717,10 +5692,10 @@ * // => [3, 6, 4] * * _.times(3, function(n) { mage.castSpell(n); }); - * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively + * // => invokes `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively * * _.times(3, function(n) { this.cast(n); }, mage); - * // => also calls `mage.castSpell(n)` three times + * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { n = nativeIsFinite(n = +n) && n > -1 ? n : 0; @@ -5774,7 +5749,6 @@ lodash.bindAll = bindAll; lodash.chain = chain; lodash.compact = compact; - lodash.compose = compose; lodash.constant = constant; lodash.countBy = countBy; lodash.debounce = debounce; @@ -5826,6 +5800,7 @@ // add aliases lodash.collect = map; + lodash.compose = flowRight; lodash.each = forEach; lodash.extend = assign; lodash.methods = functions; diff --git a/dist/lodash.underscore.min.js b/dist/lodash.underscore.min.js index f0c9b9e3d9..b0144d3851 100644 --- a/dist/lodash.underscore.min.js +++ b/dist/lodash.underscore.min.js @@ -8,38 +8,38 @@ return t}function h(n,r){for(var t=-1,e=n.length;++tu(r,i)&&o.push(i)}return o}function b(n,r){var t=n?n.length:0;if(typeof t!="number"||-1>=t||t>Br){for(var t=-1,e=Nt(n),u=e.length;++t=t||t>Br){for(var t=Nt(n),e=t.length;e--;){var u=t[e];if(r(n[u],u,n)===Fr)break}return n}for(e=z(n);t--&&r(e[t],t,e)!==Fr;);return n }function d(n,r){var t=true;return b(n,function(n,e,u){return(t=!!r(n,e,u))||Fr}),t}function j(n,r){var t=[];return b(n,function(n,e,u){r(n,e,u)&&t.push(n)}),t}function w(n,r,t){var e;return t(n,function(n,t,u){return r(n,t,u)?(e=n,Fr):void 0}),e}function A(n,r,t,e){e=(e||0)-1;for(var u=n.length,o=-1,i=[];++ee(i,f)&&(r&&i.push(f),o.push(a))}return o}function M(n,r){return function(t,e,u){var o=r?r():{};if(e=v(e,u,3),$t(t)){u=-1;for(var i=t.length;++ur?0:r)}function H(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?At(u+e,0):e||0;else if(e)return e=G(r,t),u&&r[e]===t?e:-1; -return n(r,t,e)}function P(n,r,t){return V(n,null==r||t?1:0>r?0:r)}function V(n,t,e){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),e=typeof e=="undefined"||e>o?o:+e||0,0>e&&(e+=o),e&&e==o&&!t)return r(n);for(o=t>e?0:e-t,e=Array(o);++u>>1,a=t(n[i]),f=ar?0:r)}function P(r,t,e){var u=r?r.length:0;if(typeof e=="number")e=0>e?At(u+e,0):e||0;else if(e)return e=H(r,t),u&&r[e]===t?e:-1; +return n(r,t,e)}function V(n,r,t){return G(n,null==r||t?1:0>r?0:r)}function G(n,t,e){var u=-1,o=n?n.length:0;if(t=null==t?0:+t||0,0>t&&(t=-t>o?0:o+t),e=typeof e=="undefined"||e>o?o:+e||0,0>e&&(e+=o),e&&e==o&&!t)return r(n);for(o=t>e?0:e-t,e=Array(o);++u>>1,a=t(n[i]),f=au&&(u=i)}else r=v(r,t,3),b(n,function(n,t,o){t=r(n,t,o),(t>e||-1/0===t&&t===u)&&(e=t,u=n)});return u}function rr(n,r){return Z(n,Er(r))}function tr(n,r,t,e){return($t(n)?s:S)(n,v(r,e,4),t,3>arguments.length,b)}function er(n,r,t,e){return($t(n)?g:S)(n,v(r,e,4),t,3>arguments.length,_)}function ur(n){n=z(n);for(var r=-1,t=n.length,e=Array(t);++rarguments.length?R(n,kr,r):O(n,kr|Ir,V(arguments,2),[],r)}function ar(n,r,t){function e(){var t=r-(Rt()-c);0>=t||t>r?(a&&clearTimeout(a),t=s,a=p=s=Or,t&&(g=Rt(),f=n.apply(l,i),p||a||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),a=p=s=Or,(v||h!==r)&&(g=Rt(),f=n.apply(l,i),p||a||(i=l=null))}function o(){if(i=arguments,c=Rt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p;else{a||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(a&&(a=clearTimeout(a)),g=c,f=n.apply(l,i)):a||(a=setTimeout(u,o)) -}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,f=n.apply(l,i)),!m||p||a||(i=l=null),f}var i,a,f,c,l,p,s,g=0,h=false,v=true;if(!hr(n))throw new TypeError(Mr);if(r=0>r?0:r,true===t)var y=true,v=false;else vr(t)&&(y=t.leading,h="maxWait"in t&&At(+t.maxWait||0,r),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),a&&clearTimeout(a),a=p=s=Or},o}function fr(n){for(var r=V(arguments,1),t=r,e=fr.placeholder,u=-1,o=t.length,i=-1,a=[];++uarguments.length?R(n,kr,r):O(n,kr|Ir,G(arguments,2),[],r)}function ar(n,r,t){function e(){var t=r-(Rt()-c);0>=t||t>r?(a&&clearTimeout(a),t=s,a=p=s=Or,t&&(g=Rt(),f=n.apply(l,i),p||a||(i=l=null))):p=setTimeout(e,t)}function u(){p&&clearTimeout(p),a=p=s=Or,(v||h!==r)&&(g=Rt(),f=n.apply(l,i),p||a||(i=l=null))}function o(){if(i=arguments,c=Rt(),l=this,s=v&&(p||!y),false===h)var t=y&&!p;else{a||y||(g=c);var o=h-(c-g),m=0>=o||o>h;m?(a&&(a=clearTimeout(a)),g=c,f=n.apply(l,i)):a||(a=setTimeout(u,o)) +}return m&&p?p=clearTimeout(p):p||r===h||(p=setTimeout(e,r)),t&&(m=true,f=n.apply(l,i)),!m||p||a||(i=l=null),f}var i,a,f,c,l,p,s,g=0,h=false,v=true;if(!hr(n))throw new TypeError(Mr);if(r=0>r?0:r,true===t)var y=true,v=false;else vr(t)&&(y=t.leading,h="maxWait"in t&&At(+t.maxWait||0,r),v="trailing"in t?t.trailing:v);return o.cancel=function(){p&&clearTimeout(p),a&&clearTimeout(a),a=p=s=Or},o}function fr(n){for(var r=G(arguments,1),t=r,e=fr.placeholder,u=-1,o=t.length,i=-1,a=[];++u"'`]/g,Wr=/^\[object .+?Constructor\]$/,Dr=/($^)/,zr=/[.*+?^${}()|[\]\/\\]/g,Cr=/['\n\r\u2028\u2029\\]/g,Hr="[object Arguments]",Pr="[object Boolean]",Vr="[object Date]",Gr="[object Error]",Jr="[object Number]",Kr="[object Object]",Lr="[object RegExp]",Qr="[object String]",Xr={}; -Xr[Hr]=Xr["[object Array]"]=Xr["[object Float32Array]"]=Xr["[object Float64Array]"]=Xr["[object Int8Array]"]=Xr["[object Int16Array]"]=Xr["[object Int32Array]"]=Xr["[object Uint8Array]"]=Xr["[object Uint8ClampedArray]"]=Xr["[object Uint16Array]"]=Xr["[object Uint32Array]"]=true,Xr["[object ArrayBuffer]"]=Xr[Pr]=Xr[Vr]=Xr[Gr]=Xr["[object Function]"]=Xr["[object Map]"]=Xr[Jr]=Xr[Kr]=Xr[Lr]=Xr["[object Set]"]=Xr[Qr]=Xr["[object WeakMap]"]=false;var Yr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Zr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},nt={"function":true,object:true},rt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},tt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof module]&&module&&!module.nodeType&&module,ot=et&&ut&&typeof global=="object"&&global; +hr(n[i])&&(o[++u]=i)}return o}function sr(n){var r=n&&typeof n=="object"?n.length:Or;return typeof r=="number"&&-1"'`]/g,Wr=/^\[object .+?Constructor\]$/,Dr=/($^)/,zr=/[.*+?^${}()|[\]\/\\]/g,Cr=/['\n\r\u2028\u2029\\]/g,Pr="[object Arguments]",Vr="[object Boolean]",Gr="[object Date]",Hr="[object Error]",Jr="[object Number]",Kr="[object Object]",Lr="[object RegExp]",Qr="[object String]",Xr={}; +Xr[Pr]=Xr["[object Array]"]=Xr["[object Float32Array]"]=Xr["[object Float64Array]"]=Xr["[object Int8Array]"]=Xr["[object Int16Array]"]=Xr["[object Int32Array]"]=Xr["[object Uint8Array]"]=Xr["[object Uint8ClampedArray]"]=Xr["[object Uint16Array]"]=Xr["[object Uint32Array]"]=true,Xr["[object ArrayBuffer]"]=Xr[Vr]=Xr[Gr]=Xr[Hr]=Xr["[object Function]"]=Xr["[object Map]"]=Xr[Jr]=Xr[Kr]=Xr[Lr]=Xr["[object Set]"]=Xr[Qr]=Xr["[object WeakMap]"]=false;var Yr={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Zr={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},nt={"function":true,object:true},rt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},tt=nt[typeof window]&&window||this,et=nt[typeof exports]&&exports&&!exports.nodeType&&exports,ut=nt[typeof module]&&module&&!module.nodeType&&module,ot=et&&ut&&typeof global=="object"&&global; !ot||ot.global!==ot&&ot.window!==ot&&ot.self!==ot||(tt=ot);var it=ut&&ut.exports===et&&et,at=Array.prototype,ft=Object.prototype,ct=Function.prototype.toString,lt=ft.hasOwnProperty,pt=tt._,st=ft.toString,gt=RegExp("^"+function(n){return n=null==n?"":n+"",zr.lastIndex=0,zr.test(n)?n.replace(zr,"\\$&"):n}(st).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ht=Math.ceil,vt=Math.floor,yt=at.push,mt=ft.propertyIsEnumerable,bt=at.splice,_t=yr(_t=Object.create)&&_t,dt=yr(dt=Array.isArray)&&dt,jt=tt.isFinite,wt=yr(wt=Object.keys)&&wt,At=Math.max,xt=Math.min,Tt=yr(Tt=Date.now)&&Tt,Et=Math.random,Ot={}; -!function(){var n={0:1,length:1};Ot.spliceObjects=(bt.call(n,0,1),!n[0]);try{Ot.hostObject=!({toString:0}+"")}catch(r){Ot.hostObject=false}}(0,0),i.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},_t||(y=function(){function n(){}return function(r){if(vr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||tt.Object()}}());var kt=P,St=C,It=M(function(n,r,t){lt.call(n,t)?++n[t]:n[t]=1}),Ft=M(function(n,r,t){lt.call(n,t)?n[t].push(r):n[t]=[r] -}),Mt=M(function(n,r,t){n[t]=r}),qt=M(function(n,r,t){n[t?0:1].push(r)},function(){return[[],[]]}),Bt=fr(function(n,r){var t;if(!hr(r))throw new TypeError(Mr);return function(){return 0<--n?t=r.apply(this,arguments):r=null,t}},2);sr(arguments)||(sr=function(n){var r=n&&typeof n=="object"?n.length:Or;return typeof r=="number"&&-1--n?r.apply(this,arguments):void 0}},i.bind=ir,i.bindAll=function(n){for(var r=n,t=1r?0:r)},i.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(f,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;f.push(e)}return f},i.invert=function(n){for(var r=-1,t=Nt(n),e=t.length,u={};++ro?0:o>>>0);for(r=v(r,e,3),b(n,function(n,t,e){i[++u]={a:r(n,t,e),b:u,c:n}}),o=i.length,i.sort(t);o--;)i[o]=i[o].c;return i},i.take=St,i.tap=function(n,r){return r(n),n},i.throttle=function(n,r,t){var e=true,u=true;if(!hr(n))throw new TypeError(funcErrorText);return false===t?e=false:vr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),ar(n,r,{leading:e,maxWait:r,trailing:u}) -},i.times=function(n,r,t){n=jt(n=+n)&&-1r?0:r))},i.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?At(e+t,0):xt(t||0,e-1))+1);e--;)if(n[e]===r)return e;return-1},i.max=nr,i.min=function(n,r,t){var e=1/0,u=e,o=typeof r; -if("number"!=o&&"string"!=o||!t||t[r]!==n||(r=null),null==r)for(t=-1,n=z(n),o=n.length;++tr?0:+r||0,n.length),n)},Tr(cr({},i)),i.VERSION="3.0.0-pre",i.prototype.chain=function(){return this.__chain__=true,this},i.prototype.value=function(){return this.__wrapped__ -},f("pop push reverse shift sort splice unshift".split(" "),function(n){var r=at[n];i.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Ot.spliceObjects||0!==n.length||delete n[0],this}}),f(["concat","join","slice"],function(n){var r=at[n];i.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new a(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=i, define("underscore",function(){return i -})):et&&ut?it?(ut.exports=i)._=i:et._=i:tt._=i}).call(this); \ No newline at end of file +!function(){var n={0:1,length:1};Ot.spliceObjects=(bt.call(n,0,1),!n[0])}(0,0),i.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},_t||(y=function(){function n(){}return function(r){if(vr(r)){n.prototype=r;var t=new n;n.prototype=null}return t||tt.Object()}}());var kt=V,St=C,It=M(function(n,r,t){lt.call(n,t)?++n[t]:n[t]=1}),Ft=M(function(n,r,t){lt.call(n,t)?n[t].push(r):n[t]=[r]}),Mt=M(function(n,r,t){n[t]=r}),qt=M(function(n,r,t){n[t?0:1].push(r) +},function(){return[[],[]]}),Bt=fr(function(n,r){var t;if(!hr(r))throw new TypeError(Mr);return function(){return 0<--n?t=r.apply(this,arguments):r=null,t}},2);sr(arguments)||(sr=function(n){var r=n&&typeof n=="object"?n.length:Or;return typeof r=="number"&&-1--n?r.apply(this,arguments):void 0}},i.bind=ir,i.bindAll=function(n){for(var r=n,t=1r?0:r)},i.intersection=function(){for(var n=[],r=-1,t=arguments.length;++ri(f,e)){for(r=t;--r;)if(0>i(n[r],e))continue n; +f.push(e)}return f},i.invert=function(n){for(var r=-1,t=Nt(n),e=t.length,u={};++ro?0:o>>>0); +for(r=v(r,e,3),b(n,function(n,t,e){i[++u]={a:r(n,t,e),b:u,c:n}}),o=i.length,i.sort(t);o--;)i[o]=i[o].c;return i},i.take=St,i.tap=function(n,r){return r(n),n},i.throttle=function(n,r,t){var e=true,u=true;if(!hr(n))throw new TypeError(funcErrorText);return false===t?e=false:vr(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),ar(n,r,{leading:e,maxWait:r,trailing:u})},i.times=function(n,r,t){n=jt(n=+n)&&-1r)return function(){}; +if(!c(n,hr))throw new TypeError(Mr);return function(){for(var t=r,e=n[t].apply(this,arguments);t--;)e=n[t].call(this,e);return e}},i.each=Y,i.extend=cr,i.methods=pr,i.object=function(n,r){var t=-1,e=n?n.length:0,u={};for(r||!e||$t(n[0])||(r=[]);++tr?0:r))},i.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?At(e+t,0):xt(t||0,e-1))+1);e--;)if(n[e]===r)return e; +return-1},i.max=nr,i.min=function(n,r,t){var e=1/0,u=e,o=typeof r;if("number"!=o&&"string"!=o||!t||t[r]!==n||(r=null),null==r)for(t=-1,n=z(n),o=n.length;++tr?0:+r||0,n.length),n) +},Tr(cr({},i)),i.VERSION="3.0.0-pre",i.prototype.chain=function(){return this.__chain__=true,this},i.prototype.value=function(){return this.__wrapped__},f("pop push reverse shift sort splice unshift".split(" "),function(n){var r=at[n];i.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),Ot.spliceObjects||0!==n.length||delete n[0],this}}),f(["concat","join","slice"],function(n){var r=at[n];i.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new a(n),n.__chain__=true),n +}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(tt._=i, define("underscore",function(){return i})):et&&ut?it?(ut.exports=i)._=i:et._=i:tt._=i}).call(this); \ No newline at end of file From 7f88a7c9bb1442e40f83604d943602a0d831335c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Aug 2014 09:02:02 -0700 Subject: [PATCH 1060/1608] Add more hot method tests. --- test/test.js | 76 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/test/test.js b/test/test.js index b348da1cc2..b57950402c 100644 --- a/test/test.js +++ b/test/test.js @@ -2455,28 +2455,6 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('curry methods'); - - _.each(['curry', 'curryRight'], function(methodName) { - var func = _[methodName]; - - function fn(a, b, c, d) { - return slice.call(arguments); - } - - test('`_.' + methodName + '` should work when hot', 1, function() { - var curried = func(fn); - - var actual = _.last(_.times(HOT_COUNT, function() { - return curried(1)(2)(3)(4); - })); - - deepEqual(actual, [1, 2, 3, 4]); - }); - }); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.debounce'); (function() { @@ -8296,9 +8274,9 @@ }); test('`_.' + methodName + '` should clone metadata for created functions', 3, function() { - var greet = function(greeting, name) { + function greet(greeting, name) { return greeting + ' ' + name; - }; + } var par1 = func(greet, 'hi'), par2 = func(par1, 'barney'), @@ -8452,6 +8430,56 @@ strictEqual(c(), 1); }); + + test('should work when hot', 6, function() { + _.times(2, function(index) { + function fn() { + var result = [this]; + push.apply(result, arguments); + return result; + } + + var object = {}, + bound1 = index ? _.bind(fn, object, 1) : _.bind(fn, object); + + var actual = _.last(_.times(HOT_COUNT, function() { + var bound2 = index ? _.bind(bound1, null, 2) : _.bind(bound1); + return index ? bound2(3) : bound2(1, 2, 3); + })); + + deepEqual(actual, [object, 1, 2, 3]); + }); + + _.each(['curry', 'curryRight'], function(methodName) { + function fn(a, b, c) { + return [a, b, c]; + } + + var curried = _[methodName](fn); + + var actual = _.last(_.times(HOT_COUNT, function() { + return curried(1)(2)(3); + })); + + deepEqual(actual, methodName == 'curry' ? [1, 2, 3] : [3, 2, 1]); + }); + + _.each(['partial', 'partialRight'], function(methodName) { + function fn() { + return slice.call(arguments); + } + + var func = _[methodName], + par1 = func(fn, 1); + + var actual = _.last(_.times(HOT_COUNT, function() { + var par2 = func(par1, 2); + return par2(3); + })); + + deepEqual(actual, methodName == 'partial' ? [1, 2, 3] : [3, 2, 1]); + }); + }); }()); /*--------------------------------------------------------------------------*/ From 87c21ba75e5705bd8b108f6745d2825f001a8106 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Aug 2014 09:32:26 -0700 Subject: [PATCH 1061/1608] Add coverage for WeakMap usage. --- test/asset/set.js | 4 +-- test/asset/weakmap.js | 76 +++++++++++++++++++++++++++++++++++++++++++ test/index.html | 10 ++++++ test/test.js | 20 +++++++++++- 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 test/asset/weakmap.js diff --git a/test/asset/set.js b/test/asset/set.js index 560615b84b..893291aa18 100644 --- a/test/asset/set.js +++ b/test/asset/set.js @@ -21,7 +21,7 @@ /*--------------------------------------------------------------------------*/ /** - * Creates a Set object to optimize linear searches of large arrays. + * Creates a `Set` object. */ function Set() { this.__cache__ = {}; @@ -81,7 +81,7 @@ * Adds `value` to the set. * * @memberOf Set - * @param {*} value The value to add to the set. + * @param {*} value The value to add. */ function add(value) { var cache = this.__cache__, diff --git a/test/asset/weakmap.js b/test/asset/weakmap.js new file mode 100644 index 0000000000..01d02be002 --- /dev/null +++ b/test/asset/weakmap.js @@ -0,0 +1,76 @@ +;(function() { + + /** Used to determine if values are of the language type Object */ + var objectTypes = { + 'function': true, + 'object': true + }; + + /** Used as the `WeakMap#toString` return value */ + var nativeString = String(Object.prototype.toString).replace(/toString/g, 'WeakMap'); + + /** Used as a reference to the global object */ + var root = (objectTypes[typeof window] && window) || this; + + /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ + var freeGlobal = objectTypes[typeof global] && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a `WeakMap` object. + */ + function WeakMap() { + // no-op + } + + /*--------------------------------------------------------------------------*/ + + /** + * Gets the value associated with the given key. + * + * @memberOf WeakMap + * @param {Object} key The key object. + * @returns {*} Returns the associated value, else `undefined`. + */ + function get(key) { + return key.__weakmap__; + } + + /** + * Sets a value for the given key. + * + * @memberOf WeakMap + * @param {Object} key The key object. + * @param {*} value The value to set. + */ + function set(key, value) { + key.__weakmap__ = value; + return this; + } + + /** + * Produces the `toString` result of `WeakMap`. + * + * @static + * @memberOf WeakMap + * @returns {string} Returns the string result. + */ + function toString() { + return nativeString; + } + + /*--------------------------------------------------------------------------*/ + + WeakMap.toString = toString; + WeakMap.prototype.get = get; + WeakMap.prototype.set = set; + + // expose `WeakMap` + if (!root.WeakMap) { + root.WeakMap = WeakMap; + } +}.call(this)); diff --git a/test/index.html b/test/index.html index 8e80e4e461..f9a90d7137 100644 --- a/test/index.html +++ b/test/index.html @@ -26,6 +26,7 @@ +
    @@ -154,6 +155,9 @@ return Float64Array; }()); } + setProperty(window, '_Set', window.Set); + setProperty(window, 'Set', noop); + setProperty(window, '_WeakMap', window.WeakMap); setProperty(window, 'WeakMap', noop); @@ -238,6 +242,11 @@ } setProperty(window, '_ArrayBuffer', undefined); + if (window._Set) { + Set = _Set; + } + setProperty(window, '_Set', undefined); + if (window._WeakMap) { WeakMap = _WeakMap; } @@ -274,6 +283,7 @@ // store Lo-Dash to test for bad extensions/shims if (!ui.isModularize) { var lodashBizarro = window._; + lodashBizarro.support.funcNames = !lodashBizarro.support.funcNames; window._ = undefined; removeBizarroMethods(); } diff --git a/test/test.js b/test/test.js index b57950402c..92c58a276f 100644 --- a/test/test.js +++ b/test/test.js @@ -38,6 +38,7 @@ noop = function() {}, params = root.arguments, push = arrayProto.push, + Set = root.Set, slice = arrayProto.slice, system = root.system, toString = objectProto.toString, @@ -339,8 +340,9 @@ function createToString(funcName) { return _.constant(nativeString.replace(reToString, funcName)); } - // load ES6 Set shim + // load ES6 Set and WeakMap shims require('./asset/set'); + require('./asset/weakmap'); // expose `baseEach` for better code coverage if (isModularize && !isNpm) { @@ -443,6 +445,12 @@ }; }())); + if (Set) { + setProperty(root, 'Set', _.noop); + } + if (WeakMap) { + setProperty(root, 'WeakMap', _.noop); + } // fake `WinRTError` setProperty(root, 'WinRTError', Error); @@ -485,6 +493,16 @@ } else { delete root.ArrayBuffer; } + if (Set) { + setProperty(root, 'Set', Set); + } else { + delete root.Set; + } + if (WeakMap) { + setProperty(root, 'WeakMap', WeakMap); + } else { + delete root.WeakMap; + } delete root.WinRTError; delete root.window; delete funcProto._method; From 06d8281f16e560ecea266b736ad1ebfd2967c49d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Aug 2014 10:25:01 -0700 Subject: [PATCH 1062/1608] Add more bizarro `support` changes. --- test/index.html | 1 + test/test.js | 1 + 2 files changed, 2 insertions(+) diff --git a/test/index.html b/test/index.html index f9a90d7137..33dd387df0 100644 --- a/test/index.html +++ b/test/index.html @@ -404,6 +404,7 @@ addBizarroMethods(); require(getConfig(), ['lodash'], function(lodash) { lodashBizarro = (lodash['default'] || lodash).noConflict(); + lodashBizarro.support.funcNames = !lodashBizarro.support.funcNames; delete requirejs.s.contexts._; removeBizarroMethods(); diff --git a/test/test.js b/test/test.js index 92c58a276f..5cd966021b 100644 --- a/test/test.js +++ b/test/test.js @@ -466,6 +466,7 @@ // load Lo-Dash and expose it to the bad extensions/shims lodashBizarro = (lodashBizarro = require(filePath))._ || lodashBizarro['default'] || lodashBizarro; + lodashBizarro.support.funcNames = !lodashBizarro.support.funcNames; // restore native methods setProperty(Array, 'isArray', _isArray); From 4eae95b88d21196f210afc405b9490cf060bb276 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Aug 2014 20:32:57 -0700 Subject: [PATCH 1063/1608] Ensure node version is consistent with its shorthand alias travis.yml. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 43f03b11de..156721008a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ branches: only: - master before_install: - - "mkdir ~/.npm" + - "nvm use $TRAVIS_NODE_VERSION && mkdir ~/.npm" - "[ $SAUCE_LABS == false ] || npm i chalk@\"^0.5.0\" ecstatic@\"^0.5.0\" request@\"^2.37.0\" sauce-tunnel@\"^2.1.0\"" - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.11.0\" && npm i istanbul@\"^0.3.0\")" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7R5 && sudo wget -O /opt/rhino-1.7R5/js.jar http://lodash.com/_travis/rhino-1.7R5.jar)" @@ -45,7 +45,7 @@ before_install: - "node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./dist/lodash.$BUILD.js" script: - "[ $ISTANBUL == false ] || (nvm install 0.11.11 && cp ./dist/lodash.$BUILD.js ./dist/lodash.js && $BIN --harmony ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./dist/lodash.js)" - - "[ $ISTANBUL == true ] && [ $TRAVIS_SECURE_ENV_VARS == true ] && nvm use 0.10 && cat ./coverage/lcov.info | coveralls || true" + - "([ $ISTANBUL == true ] && [ $TRAVIS_SECURE_ENV_VARS == true ] && nvm use $TRAVIS_NODE_VERSION && cat ./coverage/lcov.info | coveralls) || true" - "([ $SAUCE_LABS == true ] || [ $ISTANBUL == true ]) || cd ./test" - "([ $SAUCE_LABS == true ] || [ $ISTANBUL == true ]) || $BIN $OPTION ./test.js ../dist/lodash.$BUILD.js" - "([ $SAUCE_LABS == true ] || [ $ISTANBUL == true ]) || $BIN $OPTION ./test.js ../dist/lodash.$BUILD.min.js" From ba7be29153e26334cdc83272debddcb7c9a597c6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Aug 2014 21:44:18 -0700 Subject: [PATCH 1064/1608] Remove defineProperty mock. --- test/index.html | 9 --------- test/test.js | 15 ++------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/test/index.html b/test/index.html index 33dd387df0..c910a807d4 100644 --- a/test/index.html +++ b/test/index.html @@ -92,9 +92,6 @@ setProperty(Object, '_create', Object.create); setProperty(Object, 'create', noop); - setProperty(Object, '_defineProperty', Object.defineProperty); - setProperty(Object, 'defineProperty', noop); - setProperty(Object, '_getPrototypeOf', Object.getPrototypeOf); setProperty(Object, 'getPrototypeOf', noop); @@ -207,11 +204,6 @@ } else { delete Object.create; } - if (Object._defineProperty) { - setProperty(Object, 'defineProperty', Object._defineProperty); - } else { - delete Object.defineProperty; - } if (Object._getPrototypeOf) { setProperty(Object, 'getPrototypeOf', Object._getPrototypeOf); } else { @@ -265,7 +257,6 @@ delete Date._now; delete funcProto._method; delete Object._create; - delete Object._defineProperty; delete Object._getPrototypeOf; delete Object._keys; delete objectProto._propertyIsEnumerable; diff --git a/test/test.js b/test/test.js index 5cd966021b..fcd7df1766 100644 --- a/test/test.js +++ b/test/test.js @@ -372,9 +372,6 @@ var _create = create; setProperty(Object, 'create', _.noop); - var _defineProperty = Object.defineProperty; - setProperty(Object, 'defineProperty', _.noop); - var _getPrototypeOf = Object.getPrototypeOf; setProperty(Object, 'getPrototypeOf', _.noop); @@ -472,7 +469,6 @@ setProperty(Array, 'isArray', _isArray); setProperty(Date, 'now', _now); setProperty(Object, 'create', _create); - setProperty(Object, 'defineProperty', _defineProperty); setProperty(Object, 'getPrototypeOf', _getPrototypeOf); setProperty(Object, 'keys', _keys); @@ -618,7 +614,7 @@ } }); - test('should avoid overwritten native methods', 15, function() { + test('should avoid overwritten native methods', 14, function() { function Foo() {} function message(lodashMethod, nativeMethod) { @@ -652,13 +648,6 @@ ok(actual[0] instanceof Foo, message('_.create', 'Object.create')); deepEqual(actual[1], {}, message('_.create', 'Object.create')); - try { - actual = lodashBizarro.bind(function() { return this.a; }, object); - } catch(e) { - actual = null; - } - ok(!(EXPANDO in actual), message('_.bind', 'Object.defineProperty')); - try { actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; } catch(e) { @@ -727,7 +716,7 @@ } } else { - skipTest(15); + skipTest(14); } }); }()); From cc4fdfd8527a11f0bb414d5bb8cfb2eec5d9d36d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Aug 2014 23:14:28 -0700 Subject: [PATCH 1065/1608] Ensure arity is not less than 0. --- lodash.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index 4fcbc71f7e..d4d6145d43 100644 --- a/lodash.js +++ b/lodash.js @@ -2151,7 +2151,7 @@ var data = getData(func), arity = data ? data[2] : func.length; - arity -= args.length; + arity = nativeMax(arity - args.length, 0); } return (bitmask & PARTIAL_FLAG) ? createWrapper(func, bitmask, arity, thisArg, args, holders) From 81d0d5c59f5d2bcee52709495f3c56170747b3ac Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 26 Aug 2014 09:33:03 -0700 Subject: [PATCH 1066/1608] Adjust mocking to ensure coverage in modularized builds. --- test/index.html | 17 +++++++++-------- test/test.js | 42 ++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/test/index.html b/test/index.html index c910a807d4..5c5ca8893b 100644 --- a/test/index.html +++ b/test/index.html @@ -115,9 +115,6 @@ setProperty(stringProto, '_contains', stringProto.contains); setProperty(stringProto, 'contains', stringProto._contains ? noop : Boolean); - setProperty(document, '_createDocumentFragment', document.createDocumentFragment); - document.createDocumentFragment = noop; - setProperty(window, '_ArrayBuffer', window.ArrayBuffer); if (window.ArrayBuffer && window.Uint8Array) { ArrayBuffer = (function(_ArrayBuffer) { @@ -175,6 +172,10 @@ }; }(_parseInt))); + // fake lack of DOM support + setProperty(document, '_createDocumentFragment', document.createDocumentFragment); + document.createDocumentFragment = noop; + // fake `WinRTError` setProperty(window, 'WinRTError', Error); @@ -224,11 +225,6 @@ } else { delete stringProto.contains; } - setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable); - - document.createDocumentFragment = document._createDocumentFragment; - setProperty(document, '_createDocumentFragment', undefined); - if (window._ArrayBuffer) { ArrayBuffer = _ArrayBuffer; } @@ -247,12 +243,17 @@ setProperty(window, 'parseInt', window._parseInt); setProperty(window, '_parseInt', undefined); + document.createDocumentFragment = document._createDocumentFragment; + setProperty(document, '_createDocumentFragment', undefined); + setProperty(window, 'WinRTError', undefined); setProperty(window, 'exports', undefined); setProperty(window, 'global', undefined); setProperty(window, 'module', undefined); + setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable); + delete Array._isArray; delete Date._now; delete funcProto._method; diff --git a/test/test.js b/test/test.js index fcd7df1766..d140554489 100644 --- a/test/test.js +++ b/test/test.js @@ -38,12 +38,10 @@ noop = function() {}, params = root.arguments, push = arrayProto.push, - Set = root.Set, slice = arrayProto.slice, system = root.system, toString = objectProto.toString, - Uint8Array = root.Uint8Array, - WeakMap = root.WeakMap; + Uint8Array = root.Uint8Array; /** The file path of the Lo-Dash file to test */ var filePath = (function() { @@ -119,6 +117,10 @@ ? require : (isJava && root.load) || noop; + /** Load ES6 Set and WeakMap shims */ + load('./asset/set.js'); + load('./asset/weakmap.js'); + /** The unit testing framework */ var QUnit = (function() { return root.QUnit || ( @@ -340,9 +342,6 @@ function createToString(funcName) { return _.constant(nativeString.replace(reToString, funcName)); } - // load ES6 Set and WeakMap shims - require('./asset/set'); - require('./asset/weakmap'); // expose `baseEach` for better code coverage if (isModularize && !isNpm) { @@ -442,14 +441,11 @@ }; }())); - if (Set) { - setProperty(root, 'Set', _.noop); - } - if (WeakMap) { - setProperty(root, 'WeakMap', _.noop); - } - // fake `WinRTError` - setProperty(root, 'WinRTError', Error); + var _Set = root.Set; + setProperty(root, 'Set', _.noop); + + var _WeakMap = root.WeakMap; + setProperty(root, 'WeakMap', _.noop); // fake DOM setProperty(root, 'window', {}); @@ -458,6 +454,9 @@ return { 'nodeType': 11 }; }); + // fake `WinRTError` + setProperty(root, 'WinRTError', Error); + // clear cache so Lo-Dash can be reloaded emptyObject(require.cache); @@ -490,12 +489,12 @@ } else { delete root.ArrayBuffer; } - if (Set) { + if (_Set) { setProperty(root, 'Set', Set); } else { delete root.Set; } - if (WeakMap) { + if (_WeakMap) { setProperty(root, 'WeakMap', WeakMap); } else { delete root.WeakMap; @@ -614,7 +613,7 @@ } }); - test('should avoid overwritten native methods', 14, function() { + test('should avoid overwritten native methods', 15, function() { function Foo() {} function message(lodashMethod, nativeMethod) { @@ -648,6 +647,13 @@ ok(actual[0] instanceof Foo, message('_.create', 'Object.create')); deepEqual(actual[1], {}, message('_.create', 'Object.create')); + try { + actual = lodashBizarro.curry(function(a, b) { return [a, b]; })(1)(2); + } catch(e) { + actual = null; + } + deepEqual(actual, [1, 2], message('_.curry', 'Object.defineProperty')); + try { actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; } catch(e) { @@ -716,7 +722,7 @@ } } else { - skipTest(14); + skipTest(15); } }); }()); From c01623ba563ab727b7fa120e52acde04e50886f4 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 26 Aug 2014 09:33:46 -0700 Subject: [PATCH 1067/1608] Avoid false fail in environments that add an enumerable `constructor` property to `Date` objects. --- test/test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index d140554489..4e05f9b35e 100644 --- a/test/test.js +++ b/test/test.js @@ -5209,7 +5209,7 @@ (function() { var args = arguments; - test('should return `true` for empty or falsey values', 8, function() { + test('should return `true` for empty or falsey values', 7, function() { var expected = _.map(empties, _.constant(true)); var actual = _.map(empties, function(value) { @@ -5219,7 +5219,6 @@ deepEqual(actual, expected); strictEqual(_.isEmpty(true), true); - strictEqual(_.isEmpty(new Date), true); strictEqual(_.isEmpty(slice), true); strictEqual(_.isEmpty(1), true); strictEqual(_.isEmpty(NaN), true); From c4a7f899dbb731be468cb4c1908fc84c76af34b0 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 26 Aug 2014 21:36:04 -0700 Subject: [PATCH 1068/1608] Fix tests for `rhino -require`. --- test/asset/set.js | 189 +++++++++++++++------------- test/asset/weakmap.js | 99 ++++++++------- test/test.js | 54 ++++---- vendor/qunit-extras/qunit-extras.js | 4 - 4 files changed, 186 insertions(+), 160 deletions(-) diff --git a/test/asset/set.js b/test/asset/set.js index 893291aa18..256ee684a1 100644 --- a/test/asset/set.js +++ b/test/asset/set.js @@ -12,6 +12,9 @@ /** Used as a reference to the global object */ var root = (objectTypes[typeof window] && window) || this; + /** Detect free variable `exports` */ + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ var freeGlobal = objectTypes[typeof global] && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { @@ -21,113 +24,123 @@ /*--------------------------------------------------------------------------*/ /** - * Creates a `Set` object. - */ - function Set() { - this.__cache__ = {}; - } - - /*--------------------------------------------------------------------------*/ - - /** - * Gets the index at which the first occurrence of `value` is found using - * strict equality for comparisons, i.e. `===`. + * Installs `Set` on the given `context` object. * - * @private - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @returns {number} Returns the index of the matched value or `-1`. + * @memberOf exports + * @param {Object} context The context object. */ - function indexOf(array, value) { - var index = -1, - length = array.length; + function runInContext(context) { - while (++index < length) { - if (array[index] === value) { - return index; - } + /** + * Creates a `Set` object. + */ + function Set() { + this.__cache__ = {}; } - return -1; - } - - /*--------------------------------------------------------------------------*/ - - /** - * Checks if `value` is in the set. - * - * @memberOf Set - * @param {*} value The value to search for. - * @returns {boolean} Returns `true` if `value` is found, else `false`. - */ - function has(value) { - var type = typeof value, - cache = this.__cache__; - if (type == 'boolean' || value == null) { - return cache[value] || false; - } - if (type != 'number' && type != 'string') { - type = 'object'; + /** + * Gets the index at which the first occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. + * + * @private + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value or `-1`. + */ + function indexOf(array, value) { + var index = -1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; } - var key = type == 'number' ? value : '_' + value; - cache = (cache = cache[type]) && cache[key]; - - return type == 'object' - ? (cache && indexOf(cache, value) > -1 ? true : false) - : (cache || false); - } - /** - * Adds `value` to the set. - * - * @memberOf Set - * @param {*} value The value to add. - */ - function add(value) { - var cache = this.__cache__, - type = typeof value; - - if (type == 'boolean' || value == null) { - cache[value] = true; - } else { + /** + * Checks if `value` is in the set. + * + * @memberOf Set + * @param {*} value The value to search for. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + */ + function has(value) { + var type = typeof value, + cache = this.__cache__; + + if (type == 'boolean' || value == null) { + return cache[value] || false; + } if (type != 'number' && type != 'string') { type = 'object'; } - var key = type == 'number' ? value : '_' + value, - typeCache = cache[type] || (cache[type] = {}); + var key = type == 'number' ? value : '_' + value; + cache = (cache = cache[type]) && cache[key]; - if (type == 'object') { - var array = typeCache[key]; - if (array) { - array.push(value); + return type == 'object' + ? (cache && indexOf(cache, value) > -1 ? true : false) + : (cache || false); + } + + /** + * Adds `value` to the set. + * + * @memberOf Set + * @param {*} value The value to add. + */ + function add(value) { + var cache = this.__cache__, + type = typeof value; + + if (type == 'boolean' || value == null) { + cache[value] = true; + } else { + if (type != 'number' && type != 'string') { + type = 'object'; + } + var key = type == 'number' ? value : '_' + value, + typeCache = cache[type] || (cache[type] = {}); + + if (type == 'object') { + var array = typeCache[key]; + if (array) { + array.push(value); + } else { + typeCache[key] = [value]; + } } else { - typeCache[key] = [value]; + typeCache[key] = true; } - } else { - typeCache[key] = true; } } - } - /** - * Produces the `toString` result of `Set`. - * - * @static - * @memberOf Set - * @returns {string} Returns the string result. - */ - function toString() { - return nativeString; + /** + * Produces the `toString` result of `Set`. + * + * @static + * @memberOf Set + * @returns {string} Returns the string result. + */ + function toString() { + return nativeString; + } + + Set.toString = toString; + Set.prototype.add = add; + Set.prototype.has = has; + + if (!root.Set) { + context.Set = Set; + } } /*--------------------------------------------------------------------------*/ - Set.toString = toString; - Set.prototype.add = add; - Set.prototype.has = has; - - // expose `Set` - if (!root.Set) { - root.Set = Set; + if (freeExports) { + freeExports.runInContext = runInContext; + } else { + runInContext(root); } }.call(this)); diff --git a/test/asset/weakmap.js b/test/asset/weakmap.js index 01d02be002..06040e664c 100644 --- a/test/asset/weakmap.js +++ b/test/asset/weakmap.js @@ -12,6 +12,9 @@ /** Used as a reference to the global object */ var root = (objectTypes[typeof window] && window) || this; + /** Detect free variable `exports` */ + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ var freeGlobal = objectTypes[typeof global] && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { @@ -21,56 +24,68 @@ /*--------------------------------------------------------------------------*/ /** - * Creates a `WeakMap` object. + * Installs `WeakMap` on the given `context` object. + * + * @memberOf exports + * @param {Object} context The context object. */ - function WeakMap() { - // no-op - } + function runInContext(context) { - /*--------------------------------------------------------------------------*/ + /** + * Creates a `WeakMap` object. + */ + function WeakMap() { + // no-op + } - /** - * Gets the value associated with the given key. - * - * @memberOf WeakMap - * @param {Object} key The key object. - * @returns {*} Returns the associated value, else `undefined`. - */ - function get(key) { - return key.__weakmap__; - } + /** + * Gets the value associated with the given key. + * + * @memberOf WeakMap + * @param {Object} key The key object. + * @returns {*} Returns the associated value, else `undefined`. + */ + function get(key) { + return key.__weakmap__; + } - /** - * Sets a value for the given key. - * - * @memberOf WeakMap - * @param {Object} key The key object. - * @param {*} value The value to set. - */ - function set(key, value) { - key.__weakmap__ = value; - return this; - } + /** + * Sets a value for the given key. + * + * @memberOf WeakMap + * @param {Object} key The key object. + * @param {*} value The value to set. + */ + function set(key, value) { + key.__weakmap__ = value; + return this; + } - /** - * Produces the `toString` result of `WeakMap`. - * - * @static - * @memberOf WeakMap - * @returns {string} Returns the string result. - */ - function toString() { - return nativeString; + /** + * Produces the `toString` result of `WeakMap`. + * + * @static + * @memberOf WeakMap + * @returns {string} Returns the string result. + */ + function toString() { + return nativeString; + } + + WeakMap.toString = toString; + WeakMap.prototype.get = get; + WeakMap.prototype.set = set; + + if (!root.WeakMap) { + context.WeakMap = WeakMap; + } } /*--------------------------------------------------------------------------*/ - WeakMap.toString = toString; - WeakMap.prototype.get = get; - WeakMap.prototype.set = set; - - // expose `WeakMap` - if (!root.WeakMap) { - root.WeakMap = WeakMap; + if (freeExports) { + freeExports.runInContext = runInContext; + } else { + runInContext(root); } }.call(this)); diff --git a/test/test.js b/test/test.js index 4e05f9b35e..73cf30e3db 100644 --- a/test/test.js +++ b/test/test.js @@ -117,10 +117,6 @@ ? require : (isJava && root.load) || noop; - /** Load ES6 Set and WeakMap shims */ - load('./asset/set.js'); - load('./asset/weakmap.js'); - /** The unit testing framework */ var QUnit = (function() { return root.QUnit || ( @@ -132,11 +128,24 @@ ); }()); - /** Load and install QUnit Extras */ - var qe = load('../vendor/qunit-extras/qunit-extras.js'); - if (qe) { - qe.runInContext(root); - } + /** Load and install QUnit Extras and ES6 Set/WeakMap shims */ + (function() { + var paths = [ + './asset/set.js', + './asset/weakmap.js', + '../vendor/qunit-extras/qunit-extras.js' + ]; + + var index = -1, + length = paths.length; + + while (++index < length) { + var object = load(paths[index]); + if (object) { + object.runInContext(root); + } + } + }()); /*--------------------------------------------------------------------------*/ @@ -613,7 +622,7 @@ } }); - test('should avoid overwritten native methods', 15, function() { + test('should avoid overwritten native methods', 14, function() { function Foo() {} function message(lodashMethod, nativeMethod) { @@ -647,13 +656,6 @@ ok(actual[0] instanceof Foo, message('_.create', 'Object.create')); deepEqual(actual[1], {}, message('_.create', 'Object.create')); - try { - actual = lodashBizarro.curry(function(a, b) { return [a, b]; })(1)(2); - } catch(e) { - actual = null; - } - deepEqual(actual, [1, 2], message('_.curry', 'Object.defineProperty')); - try { actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; } catch(e) { @@ -722,7 +724,7 @@ } } else { - skipTest(15); + skipTest(14); } }); }()); @@ -2210,19 +2212,19 @@ var object = {}; - if ((defineProperty && !WeakMap) && _.support.funcDecomp) { - _.callback(a, object); + if (lodashBizarro && lodashBizarro.support.funcDecomp) { + lodashBizarro.callback(a, object); ok(EXPANDO in a); - _.callback(b, object); + lodashBizarro.callback(b, object); ok(!(EXPANDO in b)); - if (_.support.funcNames) { - _.support.funcNames = false; - _.callback(c, object); + if (lodashBizarro.support.funcNames) { + lodashBizarro.support.funcNames = false; + lodashBizarro.callback(c, object); ok(EXPANDO in c); - _.support.funcNames = true; + lodashBizarro.support.funcNames = true; } else { skipTest(); @@ -2236,7 +2238,7 @@ test('should not write metadata when `_.support.funcDecomp` is `false`', 1, function() { function a() {}; - if ((defineProperty && !WeakMap) && lodashBizarro) { + if (lodashBizarro) { lodashBizarro.callback(a, {}); ok(!(EXPANDO in a)); } diff --git a/vendor/qunit-extras/qunit-extras.js b/vendor/qunit-extras/qunit-extras.js index e8ad1062e9..fda9a4e1cd 100644 --- a/vendor/qunit-extras/qunit-extras.js +++ b/vendor/qunit-extras/qunit-extras.js @@ -177,10 +177,6 @@ * @param {Object} context The context object. */ function runInContext(context) { - // exit early if no `context` is provided or if `QUnit` does not exist - if (!context || !context.QUnit) { - return; - } /** Used to report the test module for failing tests */ var moduleName, From baee6b97383d3884075ae698486b590205eb42aa Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 26 Aug 2014 23:55:39 -0700 Subject: [PATCH 1069/1608] Update deps. --- vendor/backbone/backbone.js | 306 ++++-------- vendor/backbone/test/collection.js | 30 -- vendor/backbone/test/router.js | 79 +-- vendor/backbone/test/sync.js | 11 - vendor/backbone/test/view.js | 128 +---- vendor/dojo/LICENSE | 2 +- vendor/dojo/dojo.js | 39 +- vendor/platform.js/LICENSE.txt | 3 +- vendor/platform.js/platform.js | 70 +-- vendor/underscore/test/arrays.js | 126 ++++- vendor/underscore/test/chaining.js | 13 +- vendor/underscore/test/collections.js | 334 +++++++++---- vendor/underscore/test/functions.js | 122 ++++- vendor/underscore/test/objects.js | 160 ++++-- vendor/underscore/test/utility.js | 91 ++-- vendor/underscore/underscore-min.js | 4 +- vendor/underscore/underscore.js | 681 ++++++++++++++------------ 17 files changed, 1205 insertions(+), 994 deletions(-) diff --git a/vendor/backbone/backbone.js b/vendor/backbone/backbone.js index 28e9e30eb8..24a550a0ad 100644 --- a/vendor/backbone/backbone.js +++ b/vendor/backbone/backbone.js @@ -36,7 +36,9 @@ // Create local references to array methods we'll want to use later. var array = []; + var push = array.push; var slice = array.slice; + var splice = array.splice; // Current version of the library. Keep in sync with `package.json`. Backbone.VERSION = '1.1.2'; @@ -106,46 +108,27 @@ // callbacks for the event. If `name` is null, removes all bound // callbacks for all events. off: function(name, callback, context) { + var retain, ev, events, names, i, l, j, k; if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; - - // Remove all callbacks for all events. if (!name && !callback && !context) { this._events = void 0; return this; } - - var names = name ? [name] : _.keys(this._events); - for (var i = 0, length = names.length; i < length; i++) { + names = name ? [name] : _.keys(this._events); + for (i = 0, l = names.length; i < l; i++) { name = names[i]; - - // Bail out if there are no events stored. - var events = this._events[name]; - if (!events) continue; - - // Remove all callbacks for this event. - if (!callback && !context) { - delete this._events[name]; - continue; - } - - // Find any remaining events. - var remaining = []; - for (var j = 0, k = events.length; j < k; j++) { - var event = events[j]; - if ( - callback && callback !== event.callback && - callback !== event.callback._callback || - context && context !== event.context - ) { - remaining.push(event); + if (events = this._events[name]) { + this._events[name] = retain = []; + if (callback || context) { + for (j = 0, k = events.length; j < k; j++) { + ev = events[j]; + if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || + (context && context !== ev.context)) { + retain.push(ev); + } + } } - } - - // Replace events if there are any remaining. Otherwise, clean up. - if (remaining.length) { - this._events[name] = remaining; - } else { - delete this._events[name]; + if (!retain.length) delete this._events[name]; } } @@ -205,7 +188,7 @@ // Handle space separated event names. if (eventSplitter.test(name)) { var names = name.split(eventSplitter); - for (var i = 0, length = names.length; i < length; i++) { + for (var i = 0, l = names.length; i < l; i++) { obj[action].apply(obj, [names[i]].concat(rest)); } return false; @@ -370,7 +353,7 @@ // Trigger all relevant attribute changes. if (!silent) { if (changes.length) this._pending = options; - for (var i = 0, length = changes.length; i < length; i++) { + for (var i = 0, l = changes.length; i < l; i++) { this.trigger('change:' + changes[i], this, current[changes[i]], options); } } @@ -595,7 +578,6 @@ // Mix in each Underscore method as a proxy to `Model#attributes`. _.each(modelMethods, function(method) { - if (!_[method]) return; Model.prototype[method] = function() { var args = slice.call(arguments); args.unshift(this.attributes); @@ -607,7 +589,7 @@ // ------------------- // If models tend to represent a single row of data, a Backbone Collection is - // more analogous to a table full of data ... or a small slice or page of that + // more analagous to a table full of data ... or a small slice or page of that // table, or a collection of rows that belong together for a particular reason // -- all of the messages in this particular folder, all of the documents // belonging to this particular author, and so on. Collections maintain @@ -661,12 +643,13 @@ var singular = !_.isArray(models); models = singular ? [models] : _.clone(models); options || (options = {}); - for (var i = 0, length = models.length; i < length; i++) { - var model = models[i] = this.get(models[i]); + var i, l, index, model; + for (i = 0, l = models.length; i < l; i++) { + model = models[i] = this.get(models[i]); if (!model) continue; delete this._byId[model.id]; delete this._byId[model.cid]; - var index = this.indexOf(model); + index = this.indexOf(model); this.models.splice(index, 1); this.length--; if (!options.silent) { @@ -686,9 +669,10 @@ options = _.defaults({}, options, setOptions); if (options.parse) models = this.parse(models, options); var singular = !_.isArray(models); - models = singular ? (models ? [models] : []) : models.slice(); - var id, model, attrs, existing, sort; + models = singular ? (models ? [models] : []) : _.clone(models); + var i, l, id, model, attrs, existing, sort; var at = options.at; + var targetModel = this.model; var sortable = this.comparator && (at == null) && options.sort !== false; var sortAttr = _.isString(this.comparator) ? this.comparator : null; var toAdd = [], toRemove = [], modelMap = {}; @@ -697,12 +681,12 @@ // Turn bare objects into model references, and prevent invalid models // from being added. - for (var i = 0, length = models.length; i < length; i++) { + for (i = 0, l = models.length; i < l; i++) { attrs = models[i] || {}; - if (this._isModel(attrs)) { + if (attrs instanceof Model) { id = model = attrs; } else { - id = attrs[this.model.prototype.idAttribute || 'id']; + id = attrs[targetModel.prototype.idAttribute || 'id']; } // If a duplicate is found, prevent it from being added and @@ -727,14 +711,13 @@ // Do not add multiple models with the same `id`. model = existing || model; - if (!model) continue; if (order && (model.isNew() || !modelMap[model.id])) order.push(model); modelMap[model.id] = true; } // Remove nonexistent models if appropriate. if (remove) { - for (var i = 0, length = this.length; i < length; i++) { + for (i = 0, l = this.length; i < l; ++i) { if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); } if (toRemove.length) this.remove(toRemove, options); @@ -745,13 +728,13 @@ if (sortable) sort = true; this.length += toAdd.length; if (at != null) { - for (var i = 0, length = toAdd.length; i < length; i++) { + for (i = 0, l = toAdd.length; i < l; i++) { this.models.splice(at + i, 0, toAdd[i]); } } else { if (order) this.models.length = 0; var orderedModels = order || toAdd; - for (var i = 0, length = orderedModels.length; i < length; i++) { + for (i = 0, l = orderedModels.length; i < l; i++) { this.models.push(orderedModels[i]); } } @@ -762,7 +745,7 @@ // Unless silenced, it's time to fire all appropriate add/sort events. if (!options.silent) { - for (var i = 0, length = toAdd.length; i < length; i++) { + for (i = 0, l = toAdd.length; i < l; i++) { (model = toAdd[i]).trigger('add', model, this, options); } if (sort || (order && order.length)) this.trigger('sort', this, options); @@ -778,7 +761,7 @@ // Useful for bulk operations and optimizations. reset: function(models, options) { options || (options = {}); - for (var i = 0, length = this.models.length; i < length; i++) { + for (var i = 0, l = this.models.length; i < l; i++) { this._removeReference(this.models[i], options); } options.previousModels = this.models; @@ -912,10 +895,7 @@ // Create a new collection with an identical list of models as this one. clone: function() { - return new this.constructor(this.models, { - model: this.model, - comparator: this.comparator - }); + return new this.constructor(this.models); }, // Private method to reset all internal state. Called when the collection @@ -929,10 +909,7 @@ // Prepare a hash of attributes (or other model) to be added to this // collection. _prepareModel: function(attrs, options) { - if (this._isModel(attrs)) { - if (!attrs.collection) attrs.collection = this; - return attrs; - } + if (attrs instanceof Model) return attrs; options = options ? _.clone(options) : {}; options.collection = this; var model = new this.model(attrs, options); @@ -941,16 +918,11 @@ return false; }, - // Method for checking whether an object should be considered a model for - // the purposes of adding to the collection. - _isModel: function (model) { - return model instanceof Model; - }, - // Internal method to create a model's ties to a collection. _addReference: function(model, options) { this._byId[model.cid] = model; if (model.id != null) this._byId[model.id] = model; + if (!model.collection) model.collection = this; model.on('all', this._onModelEvent, this); }, @@ -984,11 +956,10 @@ 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle', - 'lastIndexOf', 'isEmpty', 'chain', 'sample', 'partition']; + 'lastIndexOf', 'isEmpty', 'chain', 'sample']; // Mix in each Underscore method as a proxy to `Collection#models`. _.each(methods, function(method) { - if (!_[method]) return; Collection.prototype[method] = function() { var args = slice.call(arguments); args.unshift(this.models); @@ -1001,7 +972,6 @@ // Use attributes instead of properties. _.each(attributeMethods, function(method) { - if (!_[method]) return; Collection.prototype[method] = function(value, context) { var iterator = _.isFunction(value) ? value : function(model) { return model.get(value); @@ -1029,6 +999,7 @@ _.extend(this, _.pick(options, viewOptions)); this._ensureElement(); this.initialize.apply(this, arguments); + this.delegateEvents(); }; // Cached regex to split keys for `delegate`. @@ -1063,35 +1034,19 @@ // Remove this view by taking the element out of the DOM, and removing any // applicable Backbone.Events listeners. remove: function() { - this._removeElement(); - this.stopListening(); - return this; - }, - - // Remove this view's element from the document and all event listeners - // attached to it. Exposed for subclasses using an alternative DOM - // manipulation API. - _removeElement: function() { this.$el.remove(); - }, - - // Change the view's element (`this.el` property) and re-delegate the - // view's events on the new element. - setElement: function(element) { - this.undelegateEvents(); - this._setElement(element); - this.delegateEvents(); + this.stopListening(); return this; }, - // Creates the `this.el` and `this.$el` references for this view using the - // given `el` and a hash of `attributes`. `el` can be a CSS selector or an - // HTML string, a jQuery context or an element. Subclasses can override - // this to utilize an alternative DOM manipulation API and are only required - // to set the `this.el` property. - _setElement: function(el) { - this.$el = el instanceof Backbone.$ ? el : Backbone.$(el); + // Change the view's element (`this.el` property), including event + // re-delegation. + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; }, // Set callbacks, where `this.events` is a hash of @@ -1107,6 +1062,8 @@ // pairs. Callbacks will be bound to the view, with `this` set properly. // Uses event delegation for efficiency. // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. delegateEvents: function(events) { if (!(events || (events = _.result(this, 'events')))) return this; this.undelegateEvents(); @@ -1114,39 +1071,28 @@ var method = events[key]; if (!_.isFunction(method)) method = this[events[key]]; if (!method) continue; + var match = key.match(delegateEventSplitter); - this.delegate(match[1], match[2], _.bind(method, this)); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this.cid; + if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } } return this; }, - // Add a single event listener to the view's element (or a child element - // using `selector`). This only works for delegate-able events: not `focus`, - // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. - delegate: function(eventName, selector, listener) { - this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); - }, - - // Clears all callbacks previously bound to the view by `delegateEvents`. + // Clears all callbacks previously bound to the view with `delegateEvents`. // You usually don't need to use this, but may wish to if you have multiple // Backbone views attached to the same DOM element. undelegateEvents: function() { - if (this.$el) this.$el.off('.delegateEvents' + this.cid); + this.$el.off('.delegateEvents' + this.cid); return this; }, - // A finer-grained `undelegateEvents` for removing a single delegated event. - // `selector` and `listener` are both optional. - undelegate: function(eventName, selector, listener) { - this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); - }, - - // Produces a DOM element to be assigned to your view. Exposed for - // subclasses using an alternative DOM manipulation API. - _createElement: function(tagName) { - return document.createElement(tagName); - }, - // Ensure that the View has a DOM element to render into. // If `this.el` is a string, pass it through `$()`, take the first // matching element, and re-assign it to `el`. Otherwise, create @@ -1156,17 +1102,11 @@ var attrs = _.extend({}, _.result(this, 'attributes')); if (this.id) attrs.id = _.result(this, 'id'); if (this.className) attrs['class'] = _.result(this, 'className'); - this.setElement(this._createElement(_.result(this, 'tagName'))); - this._setAttributes(attrs); + var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs); + this.setElement($el, false); } else { - this.setElement(_.result(this, 'el')); + this.setElement(_.result(this, 'el'), false); } - }, - - // Set attributes from a hash on this view's element. Exposed for - // subclasses using an alternative DOM manipulation API. - _setAttributes: function(attributes) { - this.$el.attr(attributes); } }); @@ -1244,14 +1184,6 @@ }; } - // Pass along `textStatus` and `errorThrown` from jQuery. - var error = options.error; - options.error = function(xhr, textStatus, errorThrown) { - options.textStatus = textStatus; - options.errorThrown = errorThrown; - if (error) error.apply(this, arguments); - }; - // Make the request, allowing the user to override any Ajax options. var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); model.trigger('request', model, xhr, options); @@ -1319,18 +1251,17 @@ var router = this; Backbone.history.route(route, function(fragment) { var args = router._extractParameters(route, fragment); - if (router.execute(callback, args, name) !== false) { - router.trigger.apply(router, ['route:' + name].concat(args)); - router.trigger('route', name, args); - Backbone.history.trigger('route', router, name, args); - } + router.execute(callback, args); + router.trigger.apply(router, ['route:' + name].concat(args)); + router.trigger('route', name, args); + Backbone.history.trigger('route', router, name, args); }); return this; }, // Execute a route handler with the provided parameters. This is an // excellent place to do pre-route setup or post-route cleanup. - execute: function(callback, args, name) { + execute: function(callback, args) { if (callback) callback.apply(this, args); }, @@ -1403,6 +1334,12 @@ // Cached regex for stripping leading and trailing slashes. var rootStripper = /^\/+|\/+$/g; + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Cached regex for removing a trailing slash. + var trailingSlash = /\/$/; + // Cached regex for stripping urls of hash. var pathStripper = /#.*$/; @@ -1418,8 +1355,7 @@ // Are we at the app root? atRoot: function() { - var path = this.location.pathname.replace(/[^\/]$/, '$&/'); - return path === this.root && !this.location.search; + return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root; }, // Gets the true hash value. Cannot use location.hash directly due to bug @@ -1429,19 +1365,14 @@ return match ? match[1] : ''; }, - // Get the pathname and search params, without the root. - getPath: function() { - var path = decodeURI(this.location.pathname + this.location.search); - var root = this.root.slice(0, -1); - if (!path.indexOf(root)) path = path.slice(root.length); - return path.slice(1); - }, - - // Get the cross-browser normalized URL fragment from the path or hash. - getFragment: function(fragment) { + // Get the cross-browser normalized URL fragment, either from the URL, + // the hash, or the override. + getFragment: function(fragment, forcePushState) { if (fragment == null) { - if (this._hasPushState || !this._wantsHashChange) { - fragment = this.getPath(); + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + fragment = decodeURI(this.location.pathname + this.location.search); + var root = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(root)) fragment = fragment.slice(root.length); } else { fragment = this.getHash(); } @@ -1460,43 +1391,36 @@ this.options = _.extend({root: '/'}, this.options, options); this.root = this.options.root; this._wantsHashChange = this.options.hashChange !== false; - this._hasHashChange = 'onhashchange' in window; this._wantsPushState = !!this.options.pushState; this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - this.fragment = this.getFragment(); - - // Add a cross-platform `addEventListener` shim for older browsers. - var addEventListener = window.addEventListener || function (eventName, listener) { - return attachEvent('on' + eventName, listener); - }; + var fragment = this.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); // Normalize root to always include a leading and trailing slash. this.root = ('/' + this.root + '/').replace(rootStripper, '/'); - // Proxy an iframe to handle location events if the browser doesn't - // support the `hashchange` event, HTML5 history, or the user wants - // `hashChange` but not `pushState`. - if (!this._hasHashChange && this._wantsHashChange && (!this._wantsPushState || !this._hasPushState)) { - var iframe = document.createElement('iframe'); - iframe.src = 'javascript:0'; - iframe.style.display = 'none'; - iframe.tabIndex = -1; - var body = document.body; - // Using `appendChild` will throw on IE < 9 if the document is not ready. - this.iframe = body.insertBefore(iframe, body.firstChild).contentWindow; - this.navigate(this.fragment); + if (oldIE && this._wantsHashChange) { + var frame = Backbone.$('