From 41cec2464461b77940ef9533f390fd0ff9fbbb48 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 10:49:52 -0700 Subject: [PATCH 001/107] Remove `debounceOptions` var. --- lodash.src.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index fedf96ae77..5aa050a796 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -197,13 +197,6 @@ cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; - /** Used as an internal `_.debounce` options object by `_.throttle`. */ - var debounceOptions = { - 'leading': false, - 'maxWait': 0, - 'trailing': false - }; - /** Used to map latin-1 supplementary letters to basic latin letters. */ var deburredLetters = { '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', @@ -8369,10 +8362,7 @@ leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } - debounceOptions.leading = leading; - debounceOptions.maxWait = +wait; - debounceOptions.trailing = trailing; - return debounce(func, wait, debounceOptions); + return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing }); } /** From c0e8cc0254a74f7a19cd9599fcf6b59b75c2dee2 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:14:25 -0700 Subject: [PATCH 002/107] Remove `_.isArguments` fallback and `_.support.argsTag`. --- lodash.src.js | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 5aa050a796..1da3d6cca9 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -999,15 +999,6 @@ Ctor.prototype = { 'valueOf': x, 'y': x }; for (var key in new Ctor) { props.push(key); } - /** - * Detect if the `toStringTag` of `arguments` objects is resolvable - * (all but Firefox < 4, IE < 9). - * - * @memberOf _.support - * @type boolean - */ - support.argsTag = objToString.call(arguments) == argsTag; - /** * Detect if `name` or `message` properties of `Error.prototype` are * enumerable by default (IE < 9, Safari < 5.1). @@ -4493,10 +4484,8 @@ support = lodash.support; // Exit early for non `Object` objects. - if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value)) || - (!hasOwnProperty.call(value, 'constructor') && - (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor))) || - (!support.argsTag && isArguments(value))) { + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) || + (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first @@ -8574,14 +8563,8 @@ * // => false */ function isArguments(value) { - return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag; - } - // Fallback for environments without a `toStringTag` for `arguments` objects. - if (!support.argsTag) { - isArguments = function(value) { - return isObjectLike(value) && isArrayLike(value) && - hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); - }; + return isObjectLike(value) && isArrayLike(value) && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); } /** @@ -9039,7 +9022,7 @@ * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && objToString.call(value) == objectTag) || (!lodash.support.argsTag && isArguments(value))) { + if (!(value && objToString.call(value) == objectTag && !isArguments(value))) { return false; } var valueOf = getNative(value, 'valueOf'), From 255da0a0d7a8423d615870963e0ff083013b390d Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:17:36 -0700 Subject: [PATCH 003/107] Remove `_.isPlainObject` fallback. --- lodash.src.js | 71 +++++++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 1da3d6cca9..7fed0d38bb 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -765,7 +765,6 @@ ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, - getPrototypeOf = getNative(Object, 'getPrototypeOf'), parseFloat = context.parseFloat, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, @@ -4470,44 +4469,6 @@ }; }()); - /** - * A fallback implementation of `_.isPlainObject` which checks if `value` - * is an object created by the `Object` constructor or has a `[[Prototype]]` - * of `null`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - */ - function shimIsPlainObject(value) { - var Ctor, - support = lodash.support; - - // Exit early for non `Object` objects. - if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) || - (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { - return false; - } - // IE < 9 iterates inherited properties before own properties. If the first - // iterated property is an object's own property then there are no inherited - // enumerable properties. - var result; - if (support.ownLast) { - baseForIn(value, function(subValue, key, object) { - result = hasOwnProperty.call(object, key); - return false; - }); - return result !== false; - } - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - baseForIn(value, function(subValue, key) { - result = key; - }); - return result === undefined || hasOwnProperty.call(value, result); - } - /** * A fallback implementation of `Object.keys` which creates an array of the * own enumerable property names of `object`. @@ -9021,16 +8982,32 @@ * _.isPlainObject(Object.create(null)); * // => true */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && objToString.call(value) == objectTag && !isArguments(value))) { + function isPlainObject(value) { + var Ctor; + + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) || + (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } - var valueOf = getNative(value, 'valueOf'), - objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); - - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + var result; + if (lodash.support.ownLast) { + baseForIn(value, function(subValue, key, object) { + result = hasOwnProperty.call(object, key); + return false; + }); + return result !== false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); }; /** From ae0bb54b2d6a865c9fb16c57906399216f9b175c Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:22:06 -0700 Subject: [PATCH 004/107] Remove `bufferClone` fork. --- lodash.src.js | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 7fed0d38bb..78be9d6b6b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -761,7 +761,6 @@ /** Native method references. */ var ArrayBuffer = getNative(context, 'ArrayBuffer'), - bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, @@ -3030,28 +3029,22 @@ * @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) ? constant(null) : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + var bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, + offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, + result = new ArrayBuffer(byteLength); - 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; - }; - } + 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, From 98956056e3c85e0bde5ab613b9fddc73cabf798f Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:26:48 -0700 Subject: [PATCH 005/107] Simplify `bufferClone`. --- lodash.src.js | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 78be9d6b6b..8b2a9a8170 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -773,18 +773,6 @@ Uint8Array = getNative(context, 'Uint8Array'), WeakMap = getNative(context, 'WeakMap'); - /** Used to clone array buffers. */ - var Float64Array = (function() { - // Safari 5 errors when using an array buffer to initialize a typed array - // where the array buffer's `byteLength` is not a multiple of the typed - // array's `BYTES_PER_ELEMENT`. - try { - var func = getNative(context, 'Float64Array'), - result = new func(new ArrayBuffer(10), 0, 1) && func; - } catch(e) {} - return result || null; - }()); - /* Native method references for those with the same name as other `lodash` methods. */ var nativeCreate = getNative(Object, 'create'), nativeIsArray = getNative(Array, 'isArray'), @@ -806,9 +794,6 @@ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - /** Used as the size, in bytes, of each `Float64Array` element. */ - var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; - /** * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * of an array-like value. @@ -3030,19 +3015,10 @@ * @returns {ArrayBuffer} Returns the cloned array buffer. */ var bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + var result = new ArrayBuffer(buffer.byteLength), + view = new Uint8Array(result); - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); - } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); - } + view.set(new Uint8Array(buffer)); return result; }; From acf82af0bfa6d0629a6cd4d512f0e18864fcf19c Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:35:35 -0700 Subject: [PATCH 006/107] Simplify `_.isElement`. --- lodash.src.js | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 8b2a9a8170..25475f6014 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -153,9 +153,9 @@ var contextProps = [ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', - 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', - 'isFinite', 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'window' + 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite', + 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap' ]; /** Used to fix the JScript `[[DontEnum]]` bug. */ @@ -732,9 +732,6 @@ objectProto = Object.prototype, stringProto = String.prototype; - /** Used to detect DOM support. */ - var document = (document = context.window) ? document.document : null; - /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; @@ -1005,14 +1002,6 @@ */ support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype'); - /** - * Detect if the `toStringTag` of DOM nodes is resolvable (all but IE < 9). - * - * @memberOf _.support - * @type boolean - */ - support.nodeTag = objToString.call(document) != objectTag; - /** * Detect if properties shadowing those on `Object.prototype` are non-enumerable. * @@ -1058,17 +1047,6 @@ */ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; - /** - * Detect if the DOM is supported. - * - * @memberOf _.support - * @type boolean - */ - try { - support.dom = document.createDocumentFragment().nodeType === 11; - } catch(e) { - support.dom = false; - } }(1, 0)); /** @@ -8574,14 +8552,7 @@ * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && - (lodash.support.nodeTag ? (objToString.call(value).indexOf('Element') > -1) : isHostObject(value)); - } - // Fallback for environments without DOM support. - if (!support.dom) { - isElement = function(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); - }; + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } /** From d266a0c0cee94f8f62fcb0dda54478c4ad4caac1 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:36:42 -0700 Subject: [PATCH 007/107] Simplify `_.parseInt`. --- lodash.src.js | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 25475f6014..b45bcfc67a 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -137,18 +137,6 @@ return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); }()); - /** Used to detect and test for whitespace. */ - var whitespace = ( - // Basic whitespace characters. - ' \t\x0b\f\xa0\ufeff' + - - // Line terminators. - '\n\r\u2028\u2029' + - - // Unicode category "Zs" space separators. - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); - /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', @@ -10517,25 +10505,16 @@ * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - if (guard && isIterateeCall(string, radix, guard)) { + // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. + // Chrome fails to trim leading whitespace characters. + // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { radix = 0; + } else if (radix) { + radix = +radix; } - return nativeParseInt(string, radix); - } - // Fallback for environments with pre-ES5 implementations. - if (nativeParseInt(whitespace + '08') != 8) { - parseInt = function(string, radix, guard) { - // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. - // Chrome fails to trim leading whitespace characters. - // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. - if (guard ? isIterateeCall(string, radix, guard) : radix == null) { - radix = 0; - } else if (radix) { - radix = +radix; - } - string = trim(string); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); - }; + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); } /** From 6bcbb6f7bbae7547139f18d5b974ce3036c40357 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:39:29 -0700 Subject: [PATCH 008/107] Simplify `_.now` and `_.isFinite`. --- lodash.src.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index b45bcfc67a..cec9e88297 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -765,8 +765,6 @@ nativeKeys = getNative(Object, 'keys'), nativeMax = Math.max, nativeMin = Math.min, - nativeNow = getNative(Date, 'now'), - nativeNumIsFinite = getNative(Number, 'isFinite'), nativeParseInt = context.parseInt, nativeRandom = Math.random; @@ -7293,9 +7291,9 @@ * }, _.now()); * // => logs the number of milliseconds it took for the deferred function to be invoked */ - var now = nativeNow || function() { + function now() { return new Date().getTime(); - }; + } /*------------------------------------------------------------------------*/ @@ -8679,9 +8677,9 @@ * _.isFinite(Infinity); * // => false */ - var isFinite = nativeNumIsFinite || function(value) { + function isFinite(value) { return typeof value == 'number' && nativeIsFinite(value); - }; + } /** * Checks if `value` is classified as a `Function` object. From 722eac1681b1d03b68889cc3e8df8dd745073858 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 26 May 2015 11:49:39 -0700 Subject: [PATCH 009/107] Simplify `_.isFunction`. --- lodash.src.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index cec9e88297..939d1b9ee8 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -8697,12 +8697,13 @@ * _.isFunction(/abc/); * // => false */ - var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) { + function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. - return objToString.call(value) == funcTag; - }; + var type = typeof value; + return type == 'function' || (type == 'object' && objToString.call(value) == funcTag); + } /** * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. From 32f223c683671cfbfee49394b3e96e728a7d741b Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 27 May 2015 15:20:22 -0400 Subject: [PATCH 010/107] New line nit. --- lodash.src.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 939d1b9ee8..829c5e751b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1032,7 +1032,6 @@ * @type boolean */ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; - }(1, 0)); /** From dfec16670421c76292666ea44e3de24e4c72e40c Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 27 May 2015 15:21:52 -0400 Subject: [PATCH 011/107] Remove dual environment `_.isElement` test. --- test/test.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/test/test.js b/test/test.js index 274616e8c6..2e20c82744 100644 --- a/test/test.js +++ b/test/test.js @@ -7240,7 +7240,7 @@ this.nodeType = 1; } - test('should use robust check', 7, function() { + test('should return `false` for plain objects', 7, function() { var element = body || new Element; strictEqual(_.isElement(element), true); @@ -7252,20 +7252,6 @@ strictEqual(_.isElement({ 'nodeType': '001' }), false); }); - test('should use a stronger check in browsers', 2, function() { - var expected = !_.support.dom; - - strictEqual(_.isElement(new Element), expected); - - if (lodashBizarro) { - expected = !lodashBizarro.support.dom; - strictEqual(lodashBizarro.isElement(new Element), expected); - } - else { - skipTest(); - } - }); - test('should return `false` for non DOM elements', 13, function() { var expected = _.map(falsey, _.constant(false)); From c0bc5657ea9e415311620efd0fedc62fcf45302c Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 27 May 2015 17:49:07 -0400 Subject: [PATCH 012/107] Remove unnecessary tests. --- test/index.html | 96 +----------------------------- test/test.js | 152 +----------------------------------------------- 2 files changed, 4 insertions(+), 244 deletions(-) diff --git a/test/index.html b/test/index.html index 55e8688c5e..b3ce68690b 100644 --- a/test/index.html +++ b/test/index.html @@ -56,10 +56,8 @@ fnToString = funcProto.toString, nativeString = fnToString.call(objectProto.toString), noop = function() {}, - parseInt = window.parseInt, 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'; + reToString = /toString/g; function constant(value) { return function() { @@ -87,12 +85,6 @@ setProperty(Array, '_isArray', Array.isArray); setProperty(Array, 'isArray', noop); - setProperty(Date, '_now', Date.now); - setProperty(Date, 'now', noop); - - setProperty(Object, '_getPrototypeOf', Object.getPrototypeOf); - setProperty(Object, 'getPrototypeOf', noop); - setProperty(Object, '_keys', Object.keys); setProperty(Object, 'keys', noop); @@ -107,70 +99,12 @@ return propertyIsEnumerable.call(this, key); }); - setProperty(Number, '_isFinite', Number.isFinite); - setProperty(Number, 'isFinite', noop); - - setProperty(window, '_ArrayBuffer', window.ArrayBuffer); - if (window.ArrayBuffer && window.Uint8Array) { - ArrayBuffer = (function(_ArrayBuffer) { - function ArrayBuffer(byteLength) { - var buffer = new _ArrayBuffer(byteLength); - if (!byteLength) { - setProperty(buffer, 'slice', buffer.slice ? null : bufferSlice); - } - return buffer; - } - function bufferSlice() { - var newBuffer = new _ArrayBuffer(this.byteLength), - view = new Uint8Array(newBuffer); - - view.set(new Uint8Array(this)); - return newBuffer; - } - setProperty(ArrayBuffer, 'toString', createToString('ArrayBuffer')); - setProperty(bufferSlice, 'toString', createToString('slice')); - return ArrayBuffer; - }(_ArrayBuffer)); - } - if (!window.Float64Array && window.Uint8Array) { - Float64Array = (function() { - function Float64Array(buffer, byteOffset, length) { - return arguments.length == 1 - ? new Uint8Array(buffer) - : new Uint8Array(buffer, byteOffset || 0, length || buffer.byteLength); - } - setProperty(Float64Array, 'BYTES_PER_ELEMENT', 8); - setProperty(Float64Array, 'toString', createToString('Float64Array')); - return Float64Array; - }()); - } setProperty(window, '_Set', window.Set); setProperty(window, 'Set', noop); setProperty(window, '_WeakMap', window.WeakMap); setProperty(window, 'WeakMap', noop); - setProperty(window, '_parseInt', parseInt); - setProperty(window, 'parseInt', (function() { - var checkStr = whitespace + '08', - isFaked = parseInt(checkStr) != 8, - reHexPrefix = /^0[xX]/, - reTrim = RegExp('^[' + whitespace + ']+|[' + whitespace + ']+$'); - - return function(value, radix) { - if (value == checkStr && !isFaked) { - isFaked = true; - return 0; - } - value = String(value == null ? '' : value).replace(reTrim, ''); - return parseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10)); - }; - }())); - - // Fake lack of DOM support. - setProperty(document, '_createDocumentFragment', document.createDocumentFragment); - document.createDocumentFragment = noop; - // Fake `WinRTError`. setProperty(window, 'WinRTError', Error); @@ -190,31 +124,11 @@ } else { delete Array.isArray; } - if (Date._now) { - setProperty(Date, 'now', Date._now); - } else { - delete Date.now; - } - if (Object._getPrototypeOf) { - setProperty(Object, 'getPrototypeOf', Object._getPrototypeOf); - } else { - delete Object.getPrototypeOf; - } if (Object._keys) { setProperty(Object, 'keys', Object._keys); } else { delete Object.keys; } - if (Number._isFinite) { - setProperty(Number, 'isFinite', Number._isFinite); - } else { - delete Number.isFinite; - } - if (window._ArrayBuffer) { - ArrayBuffer = _ArrayBuffer; - } - setProperty(window, '_ArrayBuffer', undefined); - if (window._Set) { Set = _Set; } @@ -225,12 +139,6 @@ } setProperty(window, '_WeakMap', undefined); - 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); @@ -240,8 +148,6 @@ setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable); delete Array._isArray; - delete Date._now; - delete Object._getPrototypeOf; delete Object._keys; delete funcProto._method; delete objectProto._propertyIsEnumerable; diff --git a/test/test.js b/test/test.js index 2e20c82744..0076944bab 100644 --- a/test/test.js +++ b/test/test.js @@ -419,12 +419,6 @@ var _isArray = Array.isArray; setProperty(Array, 'isArray', _.noop); - var _now = Date.now; - setProperty(Date, 'now', _.noop); - - var _getPrototypeOf = Object.getPrototypeOf; - setProperty(Object, 'getPrototypeOf', _.noop); - var _keys = Object.keys; setProperty(Object, 'keys', _.noop); @@ -436,73 +430,12 @@ return _propertyIsEnumerable.call(this, key); }); - var _isFinite = Number.isFinite; - setProperty(Number, 'isFinite', _.noop); - - var _ArrayBuffer = ArrayBuffer; - setProperty(root, 'ArrayBuffer', (function() { - function ArrayBuffer(byteLength) { - var buffer = new _ArrayBuffer(byteLength); - if (!byteLength) { - setProperty(buffer, 'slice', buffer.slice ? null : bufferSlice); - } - return buffer; - } - function bufferSlice() { - var newBuffer = new _ArrayBuffer(this.byteLength), - view = new Uint8Array(newBuffer); - - view.set(new Uint8Array(this)); - return newBuffer; - } - setProperty(ArrayBuffer, 'toString', createToString('ArrayBuffer')); - setProperty(bufferSlice, 'toString', createToString('slice')); - return ArrayBuffer; - }())); - - var _Float64Array = root.Float64Array; - if (!_Float64Array) { - setProperty(root, 'Float64Array', (function() { - function Float64Array(buffer, byteOffset, length) { - return arguments.length == 1 - ? new Uint8Array(buffer) - : new Uint8Array(buffer, byteOffset || 0, length || buffer.byteLength); - } - setProperty(Float64Array, 'BYTES_PER_ELEMENT', 8); - setProperty(Float64Array, 'toString', createToString('Float64Array')); - return Float64Array; - }())); - } - var _parseInt = parseInt; - setProperty(root, 'parseInt', (function() { - var checkStr = whitespace + '08', - isFaked = _parseInt(checkStr) != 8, - reHexPrefix = /^0[xX]/, - reTrim = RegExp('^[' + whitespace + ']+|[' + whitespace + ']+$'); - - return function(value, radix) { - if (value == checkStr && !isFaked) { - isFaked = true; - return 0; - } - value = String(value == null ? '' : value).replace(reTrim, ''); - return _parseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10)); - }; - }())); - var _Set = root.Set; setProperty(root, 'Set', _.noop); var _WeakMap = root.WeakMap; setProperty(root, 'WeakMap', _.noop); - // Fake the DOM. - setProperty(root, 'window', {}); - setProperty(root.window, 'document', {}); - setProperty(root.window.document, 'createDocumentFragment', function() { - return { 'nodeType': 11 }; - }); - // Fake `WinRTError`. setProperty(root, 'WinRTError', Error); @@ -514,26 +447,10 @@ // Restore built-in methods. setProperty(Array, 'isArray', _isArray); - setProperty(Date, 'now', _now); - setProperty(Object, 'getPrototypeOf', _getPrototypeOf); setProperty(Object, 'keys', _keys); setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable); - setProperty(root, 'parseInt', _parseInt); - if (_isFinite) { - setProperty(Number, 'isFinite', _isFinite); - } else { - delete Number.isFinite; - } - if (_ArrayBuffer) { - setProperty(root, 'ArrayBuffer', _ArrayBuffer); - } else { - delete root.ArrayBuffer; - } - if (!_Float64Array) { - delete root.Float64Array; - } if (_Set) { setProperty(root, 'Set', Set); } else { @@ -545,7 +462,6 @@ delete root.WeakMap; } delete root.WinRTError; - delete root.window; delete funcProto._method; }()); @@ -710,7 +626,7 @@ } }); - test('should avoid overwritten native methods', 12, function() { + test('should avoid overwritten native methods', 6, function() { function Foo() {} function message(lodashMethod, nativeMethod) { @@ -729,20 +645,6 @@ } deepEqual(actual, [true, false], message('_.isArray', 'Array.isArray')); - try { - actual = lodashBizarro.now(); - } catch(e) { - actual = null; - } - ok(typeof actual == 'number', message('_.now', 'Date.now')); - - try { - actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; - } catch(e) { - actual = null; - } - deepEqual(actual, [true, false], message('_.isPlainObject', 'Object.getPrototypeOf')); - try { actual = [lodashBizarro.keys(object), lodashBizarro.keys()]; } catch(e) { @@ -750,13 +652,6 @@ } deepEqual(actual, [['a'], []], message('_.keys', 'Object.keys')); - try { - actual = [lodashBizarro.isFinite(1), lodashBizarro.isFinite(NaN)]; - } catch(e) { - actual = null; - } - deepEqual(actual, [true, false], message('_.isFinite', 'Number.isFinite')); - try { actual = [ lodashBizarro.difference([object, otherObject], largeArray), @@ -768,27 +663,7 @@ } deepEqual(actual, [[otherObject], [object], [object]], message('_.difference`, `_.intersection`, and `_.uniq', 'Set')); - try { - actual = _.map(['6', '08', '10'], lodashBizarro.parseInt); - } catch(e) { - actual = null; - } - deepEqual(actual, [6, 8, 10], '`_.parseInt` should work in its bizarro form'); - // Avoid comparing buffers with `deepEqual` in Rhino because it errors. - if (ArrayBuffer && !isRhino) { - try { - var buffer = new ArrayBuffer(10); - actual = lodashBizarro.clone(buffer); - } catch(e) { - actual = null; - } - deepEqual(actual, buffer, message('_.clone', 'ArrayBuffer#slice')); - notStrictEqual(actual, buffer, message('_.clone', 'ArrayBuffer#slice')); - } - else { - skipTest(2); - } if (ArrayBuffer && Uint8Array) { try { var array = new Uint8Array(new ArrayBuffer(10)); @@ -805,7 +680,7 @@ } } else { - skipTest(12); + skipTest(6); } }); }()); @@ -15048,19 +14923,9 @@ test('should not contain minified properties (test production builds)', 1, function() { var props = [ - 'argsTag', - 'argsObject', - 'dom', 'enumErrorProps', 'enumPrototypes', - 'fastBind', - 'funcDecomp', - 'funcNames', - 'hostObject', - 'nodeTag', - 'nonEnumArgs', 'nonEnumShadows', - 'nonEnumStrings', 'ownLast', 'spliceObjects', 'unindexedChars' @@ -17818,7 +17683,7 @@ var args = arguments, array = [1, 2, 3, 4, 5, 6]; - test('should work with `arguments` objects', 29, function() { + test('should work with `arguments` objects', 27, function() { function message(methodName) { return '`_.' + methodName + '` should work with `arguments` objects'; } @@ -17852,17 +17717,6 @@ deepEqual(_.uniq(args), [1, null, [3], 5], message('uniq')); deepEqual(_.without(args, null), [1, [3], 5], message('without')); deepEqual(_.zip(args, args), [[1, 1], [null, null], [[3], [3]], [null, null], [5, 5]], message('zip')); - - if (_.support.argsTag && _.support.argsObject && !_.support.nonEnumArgs) { - _.pull(args, null); - 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')); - } - else { - skipTest(2); - } }); test('should accept falsey primary arguments', 4, function() { From 7c95c5e80a3980eacff1f4fff1e59c7e07a25967 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 28 May 2015 11:33:03 -0400 Subject: [PATCH 013/107] Remove wild semicolon. --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 829c5e751b..d8520b05b1 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -8934,7 +8934,7 @@ result = key; }); return result === undefined || hasOwnProperty.call(value, result); - }; + } /** * Checks if `value` is classified as a `RegExp` object. From 02a132a9d78212a6c58d74ef350890ab027e0019 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 28 May 2015 14:29:26 -0400 Subject: [PATCH 014/107] Ensure `_.chunk` floors `size` values. [closes #1243] --- lodash.src.js | 2 +- test/test.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index d8520b05b1..f8832a5bda 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -4527,7 +4527,7 @@ if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { - size = nativeMax(+size || 1, 1); + size = nativeMax(floor(size) || 1, 1); } var index = 0, length = array ? array.length : 0, diff --git a/test/test.js b/test/test.js index 0076944bab..9ac8952d36 100644 --- a/test/test.js +++ b/test/test.js @@ -1846,6 +1846,10 @@ deepEqual(actual, expected); }); + test('should floor `size` values', 1, function() { + deepEqual(_.chunk(array, array.length / 4), [[0], [1], [2], [3], [4], [5]]); + }); + test('should work as an iteratee for methods like `_.map`', 1, function() { var actual = _.map([[1, 2], [3, 4]], _.chunk); deepEqual(actual, [[[1], [2]], [[3], [4]]]); From 20127f6a2a54393d8d0baaf0407ed2b8566903f6 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 28 May 2015 16:32:19 -0400 Subject: [PATCH 015/107] Re-fix `_.isFunction` in old Safari. --- lodash.src.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index f8832a5bda..b37ba6a886 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -8700,8 +8700,7 @@ // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. - var type = typeof value; - return type == 'function' || (type == 'object' && objToString.call(value) == funcTag); + return isObject(value) && objToString.call(value) == funcTag; } /** From a02be5442109a27b3e8ff0a10ccd40abcdf22c98 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 28 May 2015 22:18:39 -0400 Subject: [PATCH 016/107] Increase max duration allowed for sauce to run tests. --- test/saucelabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index d076e9897a..f2f2e38577 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -76,7 +76,7 @@ var advisor = getOption('advisor', false), framework = getOption('framework', 'qunit'), idleTimeout = getOption('idleTimeout', 60), jobName = getOption('name', 'unit tests'), - maxDuration = getOption('maxDuration', 120), + maxDuration = getOption('maxDuration', 180), port = ports[Math.min(_.sortedIndex(ports, getOption('port', 9001)), ports.length - 1)], publicAccess = getOption('public', true), queueTimeout = getOption('queueTimeout', 240), From 79990cbb27c290a0f6588fc5b31d2379f313121c Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 29 May 2015 06:24:02 -0400 Subject: [PATCH 017/107] Remove `baseIsFunction`. --- lodash.src.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index b37ba6a886..f71a64e805 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -349,20 +349,6 @@ return -1; } - /** - * The base implementation of `_.isFunction` without support for environments - * with incorrect `typeof` results. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. - */ - function baseIsFunction(value) { - // Avoid a Chakra JIT bug in compatibility modes of IE 11. - // See https://github.com/jashkenas/underscore/issues/1621 for more details. - return typeof value == 'function' || false; - } - /** * Converts `value` to a string if it's not one. An empty string is returned * for `null` or `undefined` values. From f69715d999fe74682c95f65459ae2c9d51fc6ead Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 29 May 2015 07:16:10 -0400 Subject: [PATCH 018/107] Increase coverage of `isLaziable`. --- test/test.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/test/test.js b/test/test.js index 9ac8952d36..4f19b1eb89 100644 --- a/test/test.js +++ b/test/test.js @@ -2204,15 +2204,18 @@ test('`_.' + methodName + '` should support shortcut fusion', 6, function() { var filterCount, - mapCount; + mapCount, + filter = _.filter, + map = _.map, + take = _.take; - var filter = _.curry(_.rearg(_.ary(_.filter, 2), 1, 0), 2), - map = _.curry(_.rearg(_.ary(_.map, 2), 1, 0), 2), - take = _.curry(_.rearg(_.ary(_.take, 2), 1, 0), 2); + _.filter = _.curry(_.rearg(_.ary(_.filter, 2), 1, 0), 2); + _.map = _.curry(_.rearg(_.ary(_.map, 2), 1, 0), 2); + _.take = _.curry(_.rearg(_.ary(_.take, 2), 1, 0), 2); - var filter2 = filter(function(value) { filterCount++; return value % 2 == 0; }), - map2 = map(function(value) { mapCount++; return value * value; }), - take2 = take(2); + var filter2 = _.filter(function(value) { filterCount++; return value % 2 == 0; }), + map2 = _.map(function(value) { mapCount++; return value * value; }), + take2 = _.take(2); _.times(2, function(index) { var fn = index ? _['_' + methodName] : func; @@ -2235,6 +2238,10 @@ skipTest(2); } }); + + _.filter = filter; + _.map = map; + _.take = take; }); test('`_.' + methodName + '` should work with curried functions with placeholders', 1, function() { From 9c339367ad46c2de1b0b309018b0b40472fe445b Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 29 May 2015 11:26:14 -0400 Subject: [PATCH 019/107] Optimize `baseFlatten`. --- lodash.src.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index f71a64e805..4c902a0bcf 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -2031,13 +2031,15 @@ * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. + * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isDeep, isStrict) { + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length, - resIndex = -1, - result = []; + resIndex = result.length - 1; while (++index < length) { var value = array[index]; @@ -2045,13 +2047,14 @@ (isStrict || isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). - value = baseFlatten(value, isDeep, isStrict); - } - var valIndex = -1, - valLength = value.length; + baseFlatten(value, isDeep, isStrict, result); + } else { + var valIndex = -1, + valLength = value.length; - while (++valIndex < valLength) { - result[++resIndex] = value[valIndex]; + while (++valIndex < valLength) { + result[++resIndex] = value[valIndex]; + } } } else if (!isStrict) { result[++resIndex] = value; From 29e0d37009130b8c4158bfe827b149f5bef1f666 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Sat, 30 May 2015 14:01:14 -0400 Subject: [PATCH 020/107] Reset `resIndex` after recursive `baseFlatten`. --- lodash.src.js | 1 + test/test.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 4c902a0bcf..57527ef9be 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -2048,6 +2048,7 @@ if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, isDeep, isStrict, result); + resIndex = result.length - 1; } else { var valIndex = -1, valLength = value.length; diff --git a/test/test.js b/test/test.js index 4f19b1eb89..678b8c4b76 100644 --- a/test/test.js +++ b/test/test.js @@ -5215,12 +5215,12 @@ }); test('should support flattening of nested arrays', 3, function() { - var array = [1, [2], [3, [4]]], - expected = [1, 2, 3, [4]]; + var array = [1, [2, 3], 4, [[5]]], + expected = [1, 2, 3, 4, [5]]; deepEqual(_.flatten(array), expected); - expected = [1, 2, 3, 4]; + expected = [1, 2, 3, 4, 5]; deepEqual(_.flatten(array, true), expected); deepEqual(_.flattenDeep(array), expected); }); From 88270a7b6674da869357ac65793812ba5de559c3 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 31 May 2015 13:27:35 -0700 Subject: [PATCH 021/107] Add built-in `Date.now` fork back. --- lodash.src.js | 5 +++-- test/index.html | 9 +++++++++ test/test.js | 15 +++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 57527ef9be..da19784532 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -751,6 +751,7 @@ nativeKeys = getNative(Object, 'keys'), nativeMax = Math.max, nativeMin = Math.min, + nativeNow = getNative(Date, 'now'), nativeParseInt = context.parseInt, nativeRandom = Math.random; @@ -7280,9 +7281,9 @@ * }, _.now()); * // => logs the number of milliseconds it took for the deferred function to be invoked */ - function now() { + var now = nativeNow || function() { return new Date().getTime(); - } + }; /*------------------------------------------------------------------------*/ diff --git a/test/index.html b/test/index.html index b3ce68690b..7d52d3249c 100644 --- a/test/index.html +++ b/test/index.html @@ -85,6 +85,9 @@ setProperty(Array, '_isArray', Array.isArray); setProperty(Array, 'isArray', noop); + setProperty(Date, '_now', Date.now); + setProperty(Date, 'now', noop); + setProperty(Object, '_keys', Object.keys); setProperty(Object, 'keys', noop); @@ -124,6 +127,11 @@ } else { delete Array.isArray; } + if (Date._now) { + setProperty(Date, 'now', Date._now); + } else { + delete Date.now; + } if (Object._keys) { setProperty(Object, 'keys', Object._keys); } else { @@ -148,6 +156,7 @@ setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable); delete Array._isArray; + delete Date._now; delete Object._keys; delete funcProto._method; delete objectProto._propertyIsEnumerable; diff --git a/test/test.js b/test/test.js index 678b8c4b76..1d78c6c28d 100644 --- a/test/test.js +++ b/test/test.js @@ -419,6 +419,9 @@ var _isArray = Array.isArray; setProperty(Array, 'isArray', _.noop); + var _now = Date.now; + setProperty(Date, 'now', _.noop); + var _keys = Object.keys; setProperty(Object, 'keys', _.noop); @@ -447,6 +450,7 @@ // Restore built-in methods. setProperty(Array, 'isArray', _isArray); + setProperty(Date, 'now', _now); setProperty(Object, 'keys', _keys); setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable); @@ -626,7 +630,7 @@ } }); - test('should avoid overwritten native methods', 6, function() { + test('should avoid overwritten native methods', 7, function() { function Foo() {} function message(lodashMethod, nativeMethod) { @@ -645,6 +649,13 @@ } deepEqual(actual, [true, false], message('_.isArray', 'Array.isArray')); + try { + actual = lodashBizarro.now(); + } catch(e) { + actual = null; + } + ok(typeof actual == 'number', message('_.now', 'Date.now')); + try { actual = [lodashBizarro.keys(object), lodashBizarro.keys()]; } catch(e) { @@ -680,7 +691,7 @@ } } else { - skipTest(6); + skipTest(7); } }); }()); From 642d77bb91fc5ffbd4398e2e36698ac93627d64a Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 1 Jun 2015 00:14:19 -0700 Subject: [PATCH 022/107] Add `arrayConcat` and `arrayPush` helpers. --- lodash.src.js | 110 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 27 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index da19784532..a0d9a6f84b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -736,7 +736,6 @@ clearTimeout = context.clearTimeout, floor = Math.floor, parseFloat = context.parseFloat, - push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, 'Set'), setTimeout = context.setTimeout, @@ -1335,6 +1334,30 @@ /*------------------------------------------------------------------------*/ + /** + * Creates a new array joining `array` with `values`. + * + * @private + * @param {Array} array The array to join with `values`. + * @param {Array} values The values to join with `array`. + * @returns {Array} Returns the new concatenated array. + */ + function arrayConcat(array, values) { + var index = -1, + length = array.length, + valsIndex = -1, + valsLength = values.length, + result = Array(length + valsLength); + + while (++index < length) { + result[index] = array[index]; + } + while (++valsIndex < valsLength) { + result[index++] = values[valsIndex]; + } + return result; + } + /** * Copies the values of `source` to `array`. * @@ -1490,6 +1513,25 @@ return result; } + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands and `this` binding. @@ -2039,8 +2081,7 @@ result || (result = []); var index = -1, - length = array.length, - resIndex = result.length - 1; + length = array.length; while (++index < length) { var value = array[index]; @@ -2049,17 +2090,11 @@ if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, isDeep, isStrict, result); - resIndex = result.length - 1; } else { - var valIndex = -1, - valLength = value.length; - - while (++valIndex < valLength) { - result[++resIndex] = value[valIndex]; - } + arrayPush(result, value); } } else if (!isStrict) { - result[++resIndex] = value; + result[result.length] = value; } } return result; @@ -2837,11 +2872,8 @@ length = actions.length; while (++index < length) { - var args = [result], - action = actions[index]; - - push.apply(args, action.args); - result = action.func.apply(action.thisArg, args); + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([result], action.args)); } return result; } @@ -2992,7 +3024,7 @@ argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, - result = Array(argsLength + leftLength); + result = Array(leftLength + argsLength); while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; @@ -3641,7 +3673,7 @@ argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, - args = Array(argsLength + leftLength); + args = Array(leftLength + argsLength); while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; @@ -4577,7 +4609,7 @@ * // => [1, 3] */ var difference = restParam(function(array, values) { - return isArrayLike(array) + return (isObjectLike(array) && isArrayLike(array)) ? baseDifference(array, baseFlatten(values, false, true)) : []; }); @@ -5792,7 +5824,7 @@ var array = arguments[index]; if (isArrayLike(array)) { var result = result - ? baseDifference(result, array).concat(baseDifference(array, result)) + ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; } } @@ -6033,6 +6065,33 @@ return new LodashWrapper(this.value(), this.__chain__); } + /** + * Creates a new array joining a wrapped array with any additional arrays + * and/or values. + * + * @name concat + * @memberOf _ + * @category Chain + * @param {...*} [values] The arrays and/or values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).concat([3, 4]); + * + * console.log(wrapper.value()); + * // => [1, 2, 3, 4] + * + * console.log(array); + * // => [1, 2] + */ + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [toObject(array)], values); + }); + }); + /** * Creates a clone of the chained sequence planting `value` as the wrapped value. * @@ -11371,9 +11430,7 @@ result.__chain__ = chainAll; return result; } - var args = [this.value()]; - push.apply(args, arguments); - return func.apply(object, args); + return func.apply(object, arrayPush([this.value()], arguments)); }; }(func)); } @@ -12195,9 +12252,7 @@ : lodashFunc.call(lodash, this.value()); } var interceptor = function(value) { - var otherArgs = [value]; - push.apply(otherArgs, args); - return lodashFunc.apply(lodash, otherArgs); + return lodashFunc.apply(lodash, arrayPush([value], args)); }; if (useLazy) { var wrapper = onlyLazy ? value : new LazyWrapper(this), @@ -12214,7 +12269,7 @@ }); // Add `Array` and `String` methods to `lodash.prototype`. - arrayEach(['concat', 'join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { + arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { var protoFunc = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', fixObjects = !support.spliceObjects && /^(?:pop|shift|splice)$/.test(methodName), @@ -12262,6 +12317,7 @@ // Add chaining functions to the `lodash` wrapper. lodash.prototype.chain = wrapperChain; lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; lodash.prototype.plant = wrapperPlant; lodash.prototype.reverse = wrapperReverse; lodash.prototype.toString = wrapperToString; From 4972c94aed5692a40036c3ed812c1ec40d1c8040 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 1 Jun 2015 23:05:53 -0700 Subject: [PATCH 023/107] Remove the dot from the iojs identifier in travis.yml. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 87dfd45659..38e11bc973 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,9 +19,9 @@ env: - BIN="ringo" matrix: include: - - node_js: "io.js" + - node_js: "iojs" env: - - node_js: "io.js" + - node_js: "iojs" env: BUILD="modern" - node_js: "0.8" env: NPM_VERSION="~1.4.0" From 612bfd3acc44220d5d3b35cb0a6b7a63e3b9abc2 Mon Sep 17 00:00:00 2001 From: Steven Sojka Date: Thu, 28 May 2015 11:13:53 -0500 Subject: [PATCH 024/107] Add `_.modArgs`. --- lodash.src.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.js | 48 +++++++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index a0d9a6f84b..9b8a5550aa 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7387,6 +7387,73 @@ }; } + + /** + * Creates a function that runs each argument through a transform function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...Function} [transforms] The function to transform the corresponding argument. + * @returns {Function} Returns the new function. + * @example + * + * var square = function(x) { + * return x * x; + * }; + * + * var double = function(x) { + * return x * 2; + * }; + * + * var fn = _.modArgs(function(x, y) { + * return [x , y]; + * }, square, double); + * + * fn(1, 2); // => [1, 4] + * fn(5, 10); // => [25, 20] + * + * // Ensure proper argument types + * + * var defaultNumber = function(defaultValue, num) { + * return _.isUndefined(num) ? defaultValue : num; + * }; + * + * var alwaysArray = function(list) { + * var result = list; + * + * if (_.isUndefined(list)) { + * result = []; + * } else if (!_.isArray(list)) { + * result = [list]; + * } + * + * return result; + * }; + * + * var fn = _.modArgs(function(x, y) { + * console.log(x, y); + * }, alwaysArray, _.partial(defaultNumber, 0)); + * + * fn(); // => [], 0 + * fn('hello'); // => ['hello'], 0 + * fn([true], 15); // => [true], 15 + */ + var modArgs = restParam(function(callback, transforms) { + var length = transforms.length; + + return function() { + var index = -1; + + while (++index < length) { + arguments[index] = transforms[index].call(this, arguments[index]); + } + + return callback.apply(this, arguments); + } + }); + /** * Creates a function that accepts up to `n` arguments ignoring any * additional arguments. @@ -11846,6 +11913,7 @@ // Add functions that return wrapped values when chaining. lodash.after = after; lodash.ary = ary; + lodash.modArgs = modArgs; lodash.assign = assign; lodash.at = at; lodash.before = before; diff --git a/test/test.js b/test/test.js index 1d78c6c28d..929ddd87d5 100644 --- a/test/test.js +++ b/test/test.js @@ -959,6 +959,52 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.modArgs'); + + (function() { + function double(x) { + return x * 2; + } + + function square(x) { + return x * x; + } + + function fn() { + return Array.prototype.slice.call(arguments, 0); + } + + test('should transform each argument', 1, function() { + var wrapped = _.modArgs(fn, double, square); + var actual = wrapped(5, 10); + + deepEqual(actual, [10, 100]); + }); + + test('should not transform any argument greater than the number of transforms', 1, function() { + var wrapped = _.modArgs(fn, double, square); + var actual = wrapped(5, 10, 18); + + deepEqual(actual, [10, 100, 18]); + }); + + test('should not transform any arguments if no transforms are provided', 1, function() { + var wrapped = _.modArgs(fn); + var actual = wrapped(5, 10, 18); + + deepEqual(actual, [5, 10, 18]); + }); + + test('should not pass undefined if transforms > arguments', 1, function() { + var wrapped = _.modArgs(fn, double, _.identity); + var actual = wrapped(5); + + deepEqual(actual, [10]); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.ary'); (function() { @@ -17877,7 +17923,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 225, function() { + test('should accept falsey arguments', 226, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From 1b4f210d82bd6f379a04de4a51f62fbf882449aa Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 07:47:18 -0700 Subject: [PATCH 025/107] Add sparse array test for `_#concat`. --- test/test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/test.js b/test/test.js index 929ddd87d5..2087a1b5f7 100644 --- a/test/test.js +++ b/test/test.js @@ -17173,6 +17173,23 @@ QUnit.module('lodash(...).concat'); (function() { + test('should treat sparse arrays as dense', 3, function() { + if (!isNpm) { + var expected = [], + wrapped = _(Array(1)).concat(Array(1)), + actual = wrapped.value(); + + expected.push(undefined, undefined); + + ok('0'in actual); + ok('1' in actual); + deepEqual(actual, expected); + } + else { + skipTest(3); + } + }); + test('should return a new wrapped array', 3, function() { if (!isNpm) { var array = [1], From 51576018fda0005d41243419f4c7b6645e384288 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 08:07:22 -0700 Subject: [PATCH 026/107] Cleanup `arrayConcat` and `wrapperConcat` docs. [ci skip] --- lodash.src.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 9b8a5550aa..97c950311f 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1335,25 +1335,25 @@ /*------------------------------------------------------------------------*/ /** - * Creates a new array joining `array` with `values`. + * Creates a new array joining `array` with `other`. * * @private - * @param {Array} array The array to join with `values`. - * @param {Array} values The values to join with `array`. + * @param {Array} array The array to join. + * @param {Array} other The other array to join. * @returns {Array} Returns the new concatenated array. */ - function arrayConcat(array, values) { + function arrayConcat(array, other) { var index = -1, length = array.length, - valsIndex = -1, - valsLength = values.length, - result = Array(length + valsLength); + othIndex = -1, + othLength = other.length, + result = Array(length + othLength); while (++index < length) { result[index] = array[index]; } - while (++valsIndex < valsLength) { - result[index++] = values[valsIndex]; + while (++othIndex < othLength) { + result[index++] = other[othIndex]; } return result; } @@ -6072,12 +6072,12 @@ * @name concat * @memberOf _ * @category Chain - * @param {...*} [values] The arrays and/or values to concatenate. + * @param {...*} [values] The values to concatenate. * @returns {Array} Returns the new concatenated array. * @example * * var array = [1, 2]; - * var wrapper = _(array).concat([3, 4]); + * var wrapper = _(array).concat([3], 4); * * console.log(wrapper.value()); * // => [1, 2, 3, 4] From b3d577c93711be96bdd159827fe7b7c6278d1a85 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 08:10:10 -0700 Subject: [PATCH 027/107] Replace `wrapper` with `wrapped` in docs/tests. --- lodash.src.js | 18 +++++++++--------- test/test.js | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 97c950311f..8e971c59fa 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -6046,16 +6046,16 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).push(3); + * var wrapped = _(array).push(3); * * console.log(array); * // => [1, 2] * - * wrapper = wrapper.commit(); + * wrapped = wrapped.commit(); * console.log(array); * // => [1, 2, 3] * - * wrapper.last(); + * wrapped.last(); * // => 3 * * console.log(array); @@ -6077,9 +6077,9 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).concat([3], 4); + * var wrapped = _(array).concat([3], 4); * - * console.log(wrapper.value()); + * console.log(wrapped.value()); * // => [1, 2, 3, 4] * * console.log(array); @@ -6102,17 +6102,17 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).map(function(value) { + * var wrapped = _(array).map(function(value) { * return Math.pow(value, 2); * }); * * var other = [3, 4]; - * var otherWrapper = wrapper.plant(other); + * var otherWrapped = wrapped.plant(other); * - * otherWrapper.value(); + * otherWrapped.value(); * // => [9, 16] * - * wrapper.value(); + * wrapped.value(); * // => [1, 4] */ function wrapperPlant(value) { diff --git a/test/test.js b/test/test.js index 2087a1b5f7..17dd58dc77 100644 --- a/test/test.js +++ b/test/test.js @@ -17158,9 +17158,9 @@ test('should track the `__chain__` value of a wrapper', 2, function() { if (!isNpm) { - var wrapper = _([1]).chain().commit().first(); - ok(wrapper instanceof _); - strictEqual(wrapper.value(), 1); + var wrapped = _([1]).chain().commit().first(); + ok(wrapped instanceof _); + strictEqual(wrapped.value(), 1); } else { skipTest(2); @@ -17395,9 +17395,9 @@ test('should track the `__chain__` value of a wrapper', 2, function() { if (!isNpm) { - var wrapper = _([1, 2, 3]).chain().reverse().first(); - ok(wrapper instanceof _); - strictEqual(wrapper.value(), 3); + var wrapped = _([1, 2, 3]).chain().reverse().first(); + ok(wrapped instanceof _); + strictEqual(wrapped.value(), 3); } else { skipTest(2); From de4463d9a87f915b40d6ffadfc86f51a22f3dbf7 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 08:16:47 -0700 Subject: [PATCH 028/107] Add basic `_#concat` test. --- lodash.src.js | 8 ++++---- test/test.js | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 8e971c59fa..11baa3ac9b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -6076,14 +6076,14 @@ * @returns {Array} Returns the new concatenated array. * @example * - * var array = [1, 2]; - * var wrapped = _(array).concat([3], 4); + * var array = [1]; + * var wrapped = _(array).concat(2, [3], [[4]]); * * console.log(wrapped.value()); - * // => [1, 2, 3, 4] + * // => [1, 2, 3, [4]] * * console.log(array); - * // => [1, 2] + * // => [1] */ var wrapperConcat = restParam(function(values) { values = baseFlatten(values); diff --git a/test/test.js b/test/test.js index 17dd58dc77..986df8bf81 100644 --- a/test/test.js +++ b/test/test.js @@ -17173,6 +17173,19 @@ QUnit.module('lodash(...).concat'); (function() { + test('should concat arrays and values', 2, function() { + if (!isNpm) { + var array = [1], + wrapped = _(array).concat(2, [3], [[4]]); + + deepEqual(wrapped.value(), [1, 2, 3, [4]]); + deepEqual(array, [1]); + } + else { + skipTest(2); + } + }); + test('should treat sparse arrays as dense', 3, function() { if (!isNpm) { var expected = [], From 005b587588534b13c6e82a55bb66bdf531a07d4c Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 08:41:01 -0700 Subject: [PATCH 029/107] Cleanup `_.modArgs`. --- lodash.src.js | 109 +++++++++++++++++++------------------------------- test/test.js | 77 ++++++++++++++--------------------- 2 files changed, 72 insertions(+), 114 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 11baa3ac9b..8b39067f23 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7387,73 +7387,6 @@ }; } - - /** - * Creates a function that runs each argument through a transform function. - * - * @static - * @memberOf _ - * @category Function - * @param {Function} func The function to wrap. - * @param {...Function} [transforms] The function to transform the corresponding argument. - * @returns {Function} Returns the new function. - * @example - * - * var square = function(x) { - * return x * x; - * }; - * - * var double = function(x) { - * return x * 2; - * }; - * - * var fn = _.modArgs(function(x, y) { - * return [x , y]; - * }, square, double); - * - * fn(1, 2); // => [1, 4] - * fn(5, 10); // => [25, 20] - * - * // Ensure proper argument types - * - * var defaultNumber = function(defaultValue, num) { - * return _.isUndefined(num) ? defaultValue : num; - * }; - * - * var alwaysArray = function(list) { - * var result = list; - * - * if (_.isUndefined(list)) { - * result = []; - * } else if (!_.isArray(list)) { - * result = [list]; - * } - * - * return result; - * }; - * - * var fn = _.modArgs(function(x, y) { - * console.log(x, y); - * }, alwaysArray, _.partial(defaultNumber, 0)); - * - * fn(); // => [], 0 - * fn('hello'); // => ['hello'], 0 - * fn([true], 15); // => [true], 15 - */ - var modArgs = restParam(function(callback, transforms) { - var length = transforms.length; - - return function() { - var index = -1; - - while (++index < length) { - arguments[index] = transforms[index].call(this, arguments[index]); - } - - return callback.apply(this, arguments); - } - }); - /** * Creates a function that accepts up to `n` arguments ignoring any * additional arguments. @@ -8070,6 +8003,46 @@ return memoized; } + /** + * Creates a function that runs each argument through a transform function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...Function} [transforms] The function to transform the corresponding argument. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var modded = _.modArgs(function(x, y) { + * return [x , y]; + * }, square, doubled); + * + * modded(1, 2); + * // => [1, 4] + * + * modded(5, 10); + * // => [25, 20] + */ + var modArgs = restParam(function(func, transforms) { + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the @@ -11913,7 +11886,6 @@ // Add functions that return wrapped values when chaining. lodash.after = after; lodash.ary = ary; - lodash.modArgs = modArgs; lodash.assign = assign; lodash.at = at; lodash.before = before; @@ -11969,6 +11941,7 @@ lodash.method = method; lodash.methodOf = methodOf; lodash.mixin = mixin; + lodash.modArgs = modArgs; lodash.negate = negate; lodash.omit = omit; lodash.once = once; diff --git a/test/test.js b/test/test.js index 986df8bf81..2bc8f69b83 100644 --- a/test/test.js +++ b/test/test.js @@ -62,6 +62,7 @@ /** Math helpers. */ var add = function(x, y) { return x + y; }, + doubled = function(n) { return n * 2; }, square = function(n) { return n * n; }; /** Used to set property descriptors. */ @@ -959,52 +960,6 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.modArgs'); - - (function() { - function double(x) { - return x * 2; - } - - function square(x) { - return x * x; - } - - function fn() { - return Array.prototype.slice.call(arguments, 0); - } - - test('should transform each argument', 1, function() { - var wrapped = _.modArgs(fn, double, square); - var actual = wrapped(5, 10); - - deepEqual(actual, [10, 100]); - }); - - test('should not transform any argument greater than the number of transforms', 1, function() { - var wrapped = _.modArgs(fn, double, square); - var actual = wrapped(5, 10, 18); - - deepEqual(actual, [10, 100, 18]); - }); - - test('should not transform any arguments if no transforms are provided', 1, function() { - var wrapped = _.modArgs(fn); - var actual = wrapped(5, 10, 18); - - deepEqual(actual, [5, 10, 18]); - }); - - test('should not pass undefined if transforms > arguments', 1, function() { - var wrapped = _.modArgs(fn, double, _.identity); - var actual = wrapped(5); - - deepEqual(actual, [10]); - }); - }()); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.ary'); (function() { @@ -11438,6 +11393,36 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.modArgs'); + + (function() { + function fn() { + return slice.call(arguments); + } + + test('should transform each argument', 1, function() { + var modded = _.modArgs(fn, doubled, square); + deepEqual(modded(5, 10), [10, 100]); + }); + + test('should not transform any argument greater than the number of transforms', 1, function() { + var modded = _.modArgs(fn, doubled, square); + deepEqual(modded(5, 10, 18), [10, 100, 18]); + }); + + test('should not transform any arguments if no transforms are provided', 1, function() { + var modded = _.modArgs(fn); + deepEqual(modded(5, 10, 18), [5, 10, 18]); + }); + + test('should not pass `undefined` if there are more `transforms` than `arguments`', 1, function() { + var modded = _.modArgs(fn, doubled, _.identity); + deepEqual(modded(5), [10]); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.negate'); (function() { From 55af8b4cb4d7e413608bb4bf74ce196bcd4b0fa4 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 19:35:28 -0700 Subject: [PATCH 030/107] Remove `_.isFunction` fallback test. --- test/test.js | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/test/test.js b/test/test.js index 2bc8f69b83..87669eb0d1 100644 --- a/test/test.js +++ b/test/test.js @@ -8060,48 +8060,6 @@ strictEqual(_.isFunction('a'), false); }); - test('should work using its fallback', 3, function() { - if (!isModularize) { - // Simulate native `Uint8Array` constructor with a `toStringTag` of - // 'Function' and a `typeof` result of 'object'. - var lodash = _.runInContext({ - 'Function': { - 'prototype': { - 'toString': function() { - return _.has(this, 'toString') ? this.toString() : fnToString.call(this); - } - } - }, - 'Object': _.assign(function(value) { - return Object(value); - }, { - 'prototype': { - 'toString': _.assign(function() { - return _.has(this, '@@toStringTag') ? this['@@toStringTag'] : objToString.call(this); - }, { - 'toString': function() { - return String(toString); - } - }) - } - }), - 'Uint8Array': { - '@@toStringTag': funcTag, - 'toString': function() { - return String(Uint8Array || Array); - } - } - }); - - strictEqual(lodash.isFunction(slice), true); - strictEqual(lodash.isFunction(/x/), false); - strictEqual(lodash.isFunction(Uint8Array), objToString.call(Uint8Array) == funcTag); - } - else { - skipTest(3); - } - }); - test('should work with host objects in IE 8 document mode (test in IE 11)', 2, function() { // Trigger a Chakra JIT bug. // See https://github.com/jashkenas/underscore/issues/1621. From f402dbd1e35377610a1560d106cd310e49396e27 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 19:35:47 -0700 Subject: [PATCH 031/107] Use `_.isFunction` in `_.isNative`. --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 8b39067f23..8356a05971 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -8915,7 +8915,7 @@ if (value == null) { return false; } - if (objToString.call(value) == funcTag) { + if (isFunction(value)) { return reIsNative.test(fnToString.call(value)); } return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value); From 50e129bd8f395326a339befa044a4836ea6987cf Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 20:14:55 -0700 Subject: [PATCH 032/107] Add function checks to `_.modArgs`. --- lodash.src.js | 17 +++++++++++++++++ test/test.js | 5 +++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 8356a05971..cebf3bc95d 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -348,6 +348,20 @@ } return -1; } + + /** + * The base implementation of `_.isFunction` without support for environments + * with incorrect `typeof` results. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + */ + function baseIsFunction(value) { + // Avoid a Chakra JIT bug in compatibility modes of IE 11. + // See https://github.com/jashkenas/underscore/issues/1621 for more details. + return typeof value == 'function' || false; + } /** * Converts `value` to a string if it's not one. An empty string is returned @@ -8033,6 +8047,9 @@ * // => [25, 20] */ var modArgs = restParam(function(func, transforms) { + if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } var length = transforms.length; return restParam(function(args) { var index = nativeMin(args.length, length); diff --git a/test/test.js b/test/test.js index 87669eb0d1..5b72920001 100644 --- a/test/test.js +++ b/test/test.js @@ -17836,6 +17836,7 @@ 'defer', 'delay', 'memoize', + 'modArgs', 'negate', 'once', 'partial', @@ -17896,7 +17897,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 226, function() { + test('should accept falsey arguments', 225, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; @@ -17962,7 +17963,7 @@ }); }); - test('should throw an error for falsey arguments', 24, function() { + test('should throw an error for falsey arguments', 25, function() { _.each(rejectFalsey, function(methodName) { var expected = _.map(falsey, _.constant(true)), func = _[methodName]; From f4709ce1f049dcf447d294f3cb02ce69fd040cd1 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 21:03:37 -0700 Subject: [PATCH 033/107] Move `this` binding tests around. --- test/test.js | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/test.js b/test/test.js index 5b72920001..5cf0aae43b 100644 --- a/test/test.js +++ b/test/test.js @@ -10274,16 +10274,6 @@ strictEqual(memoized(1, 3, 5), 9); }); - test('should not set a `this` binding', 2, function() { - var memoized = _.memoize(function(a, b, c) { - return a + this.b + this.c; - }); - - 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); }); @@ -10300,6 +10290,16 @@ deepEqual(actual, expected); }); + test('should not set a `this` binding', 2, function() { + var memoized = _.memoize(function(a, b, c) { + return a + this.b + this.c; + }); + + var object = { 'b': 2, 'c': 3, 'memoized': memoized }; + strictEqual(object.memoized(1), 6); + strictEqual(object.memoized(2), 7); + }); + test('should check cache for own properties', 1, function() { var memoized = _.memoize(_.identity); @@ -16809,15 +16809,6 @@ deepEqual(args, [_.noop, 1, 2, 3]); }); - test('should not set a `this` binding', 1, function() { - var p = _.wrap(_.escape, function(func) { - return '

' + func(this.text) + '

'; - }); - - var object = { 'p': p, 'text': 'fred, barney, & pebbles' }; - strictEqual(object.p(), '

fred, barney, & pebbles

'); - }); - test('should use `_.identity` when `wrapper` is nullish', 1, function() { var values = [, null, undefined], expected = _.map(values, _.constant('a')); @@ -16829,6 +16820,15 @@ deepEqual(actual, expected); }); + + test('should not set a `this` binding', 1, function() { + var p = _.wrap(_.escape, function(func) { + return '

' + func(this.text) + '

'; + }); + + var object = { 'p': p, 'text': 'fred, barney, & pebbles' }; + strictEqual(object.p(), '

fred, barney, & pebbles

'); + }); }()); /*--------------------------------------------------------------------------*/ From e062c8c6f251afc3da4c1211f0f0f39ad5d0308c Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 21:03:58 -0700 Subject: [PATCH 034/107] Tweak test label. --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index 5cf0aae43b..9c88789c1f 100644 --- a/test/test.js +++ b/test/test.js @@ -13717,7 +13717,7 @@ deepEqual(rp(1), [1, undefined, []]); }); - test('should work on functions with more than 3 params', 1, function() { + test('should work on functions with more than three params', 1, function() { var rp = _.restParam(function(a, b, c, d) { return slice.call(arguments); }); From 4beadcc4f3bd21603307cb43a31ce1ebc337cb8a Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 21:04:18 -0700 Subject: [PATCH 035/107] Add `this` binding test for `_.modArgs`. --- test/test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test.js b/test/test.js index 9c88789c1f..776cd05323 100644 --- a/test/test.js +++ b/test/test.js @@ -11377,6 +11377,17 @@ var modded = _.modArgs(fn, doubled, _.identity); deepEqual(modded(5), [10]); }); + + test('should not set a `this` binding', 1, function() { + var modded = _.modArgs(function(x) { + return this[x]; + }, function(x) { + return this === x; + }); + + var object = { 'modded': modded, 'false': 1 }; + strictEqual(object.modded(object), 1); + }); }()); /*--------------------------------------------------------------------------*/ From 11eebfb78dde0f92dd8616c2413395c07c1b5189 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 2 Jun 2015 21:40:25 -0700 Subject: [PATCH 036/107] Cleanup `fn` declaration style in tests. --- test/test.js | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/test/test.js b/test/test.js index 776cd05323..e2fc1b7611 100644 --- a/test/test.js +++ b/test/test.js @@ -2506,11 +2506,11 @@ (function() { test('should provide arguments to `func`', 3, function() { - function fn() { + var fn = function() { var result = [this]; push.apply(result, arguments); return result; - } + }; var callback = _.callback(fn), actual = callback('a', 'b', 'c', 'd', 'e', 'f'); @@ -2647,11 +2647,11 @@ }); test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() { - function fn() { + var fn = function() { var result = [this.a]; push.apply(result, arguments); return result; - } + }; var expected = [1, 2, 3], object = { 'a': 1 }, @@ -11952,16 +11952,16 @@ QUnit.module('methods using `createWrapper`'); (function() { + function fn() { + return slice.call(arguments); + } + var ph1 = _.bind.placeholder, ph2 = _.bindKey.placeholder, ph3 = _.partial.placeholder, ph4 = _.partialRight.placeholder; test('combinations of partial functions should work', 1, function() { - function fn() { - return slice.call(arguments); - } - var a = _.partial(fn), b = _.partialRight(a, 3), c = _.partial(b, 1); @@ -11970,11 +11970,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 }; @@ -11999,10 +11999,6 @@ }); test('combinations of functions with placeholders should work', 3, function() { - function fn() { - return slice.call(arguments); - } - var expected = [1, 2, 3, 4, 5, 6], object = { 'fn': fn }; @@ -12026,10 +12022,6 @@ }); test('combinations of functions with overlaping placeholders should work', 3, function() { - function fn() { - return slice.call(arguments); - } - var expected = [1, 2, 3, 4], object = { 'fn': fn }; @@ -12053,9 +12045,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 }), From bdbc157c30a21b1b4856722ed6dde85c36403189 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 3 Jun 2015 22:51:04 -0700 Subject: [PATCH 037/107] Whitespace nits. [ci skip] --- lodash.src.js | 2 +- test/test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index cebf3bc95d..8ffeb460e9 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -348,7 +348,7 @@ } return -1; } - + /** * The base implementation of `_.isFunction` without support for environments * with incorrect `typeof` results. diff --git a/test/test.js b/test/test.js index e2fc1b7611..d151692e29 100644 --- a/test/test.js +++ b/test/test.js @@ -10299,7 +10299,7 @@ strictEqual(object.memoized(1), 6); strictEqual(object.memoized(2), 7); }); - + test('should check cache for own properties', 1, function() { var memoized = _.memoize(_.identity); @@ -11377,7 +11377,7 @@ var modded = _.modArgs(fn, doubled, _.identity); deepEqual(modded(5), [10]); }); - + test('should not set a `this` binding', 1, function() { var modded = _.modArgs(function(x) { return this[x]; @@ -16823,7 +16823,7 @@ deepEqual(actual, expected); }); - + test('should not set a `this` binding', 1, function() { var p = _.wrap(_.escape, function(func) { return '

' + func(this.text) + '

'; From cce9c2225e471190fa84407c47e7ecd69df8526e Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 3 Jun 2015 22:54:47 -0700 Subject: [PATCH 038/107] Ensure bailouts of lazy chaining will fallback appropriately. --- lodash.src.js | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 8ffeb460e9..fd6f3db56f 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1168,7 +1168,7 @@ function lazyValue() { var array = this.__wrapped__.value(); if (!isArray(array)) { - return baseWrapperValue(array, this.__actions__); + return baseWrapperValue(array, this.__actions__ || []); } var dir = this.__dir__, isRight = dir < 0, @@ -6169,15 +6169,20 @@ */ function wrapperReverse() { var value = this.__wrapped__; + + var interceptor = function(value) { + return value.reverse(); + }; if (value instanceof LazyWrapper) { if (this.__actions__.length) { value = new LazyWrapper(this); } - return new LodashWrapper(value.reverse(), this.__chain__); + value = value.reverse(); + var actions = value.__actions__ || (value.__actions__ = []); + actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + return new LodashWrapper(value, this.__chain__); } - return this.thru(function(value) { - return value.reverse(); - }); + return this.thru(interceptor); } /** @@ -12283,15 +12288,15 @@ // Add `LazyWrapper` methods to `lodash.prototype`. baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var lodashFunc = lodash[methodName]; + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), + retUnwrapped = /^(?:first|last)$/.test(methodName), + lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName]; + if (!lodashFunc) { return; } - var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), - retUnwrapped = /^(?:first|last)$/.test(methodName); - lodash.prototype[methodName] = function() { - var args = arguments, + var args = retUnwrapped ? [1] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, @@ -12299,24 +12304,27 @@ iteratee = args[0], useLazy = isLazy || isArray(value); + var interceptor = function(value) { + return lodashFunc.apply(lodash, arrayPush([value], args)); + }; if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { - // avoid lazy use if the iteratee has a "length" value other than `1` + // Avoid lazy use if the iteratee has a "length" value other than `1`. isLazy = useLazy = false; } var onlyLazy = isLazy && !isHybrid; if (retUnwrapped && !chainAll) { - return onlyLazy - ? func.call(value) - : lodashFunc.call(lodash, this.value()); + if (onlyLazy) { + value = value.clone(); + var actions = value.__actions__ || (value.__actions__ = []); + actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + return func.call(value); + } + return lodashFunc.call(lodash, this.value())[0]; } - var interceptor = function(value) { - return lodashFunc.apply(lodash, arrayPush([value], args)); - }; if (useLazy) { - var wrapper = onlyLazy ? value : new LazyWrapper(this), - result = func.apply(wrapper, args); - - if (!retUnwrapped && (isHybrid || result.__actions__)) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + if (!retUnwrapped) { var actions = result.__actions__ || (result.__actions__ = []); actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); } From c89fe8bdbc07c3d6545eb5b91d6005b54b874b12 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 3 Jun 2015 23:20:03 -0700 Subject: [PATCH 039/107] Simplify array properties of `LazyWrapper`. --- lodash.src.js | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index fd6f3db56f..d9930dc215 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1105,13 +1105,13 @@ */ function LazyWrapper(value) { this.__wrapped__ = value; - this.__actions__ = null; + this.__actions__ = []; this.__dir__ = 1; this.__dropCount__ = 0; this.__filtered__ = false; - this.__iteratees__ = null; + this.__iteratees__ = []; this.__takeCount__ = POSITIVE_INFINITY; - this.__views__ = null; + this.__views__ = []; } /** @@ -1123,17 +1123,13 @@ * @returns {Object} Returns the cloned `LazyWrapper` object. */ function lazyClone() { - var actions = this.__actions__, - iteratees = this.__iteratees__, - views = this.__views__, - result = new LazyWrapper(this.__wrapped__); - - result.__actions__ = actions ? arrayCopy(actions) : null; + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); result.__dir__ = this.__dir__; result.__filtered__ = this.__filtered__; - result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__iteratees__ = arrayCopy(this.__iteratees__); result.__takeCount__ = this.__takeCount__; - result.__views__ = views ? arrayCopy(views) : null; + result.__views__ = arrayCopy(this.__views__); return result; } @@ -1168,7 +1164,7 @@ function lazyValue() { var array = this.__wrapped__.value(); if (!isArray(array)) { - return baseWrapperValue(array, this.__actions__ || []); + return baseWrapperValue(array, this.__actions__); } var dir = this.__dir__, isRight = dir < 0, @@ -1179,7 +1175,7 @@ index = isRight ? end : (start - 1), takeCount = nativeMin(length, this.__takeCount__), iteratees = this.__iteratees__, - iterLength = iteratees ? iteratees.length : 0, + iterLength = iteratees.length, resIndex = 0, result = []; @@ -4038,13 +4034,13 @@ * @private * @param {number} start The start of the view. * @param {number} end The end of the view. - * @param {Array} [transforms] The transformations to apply to the view. + * @param {Array} transforms The transformations to apply to the view. * @returns {Object} Returns an object containing the `start` and `end` * positions of the view. */ function getView(start, end, transforms) { var index = -1, - length = transforms ? transforms.length : 0; + length = transforms.length; while (++index < length) { var data = transforms[index], @@ -6178,8 +6174,7 @@ value = new LazyWrapper(this); } value = value.reverse(); - var actions = value.__actions__ || (value.__actions__ = []); - actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); return new LodashWrapper(value, this.__chain__); } return this.thru(interceptor); @@ -12179,10 +12174,9 @@ LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { var filtered = this.__filtered__, - result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(), - iteratees = result.__iteratees__ || (result.__iteratees__ = []); + result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(); - iteratees.push({ + result.__iteratees__.push({ 'done': false, 'count': 0, 'index': 0, @@ -12212,8 +12206,7 @@ last(result.__iteratees__).limit = n; } } else { - var views = result.__views__ || (result.__views__ = []); - views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); + result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); } return result; }; @@ -12315,8 +12308,7 @@ if (retUnwrapped && !chainAll) { if (onlyLazy) { value = value.clone(); - var actions = value.__actions__ || (value.__actions__ = []); - actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); return func.call(value); } return lodashFunc.call(lodash, this.value())[0]; @@ -12325,8 +12317,7 @@ value = onlyLazy ? value : new LazyWrapper(this); var result = func.apply(value, args); if (!retUnwrapped) { - var actions = result.__actions__ || (result.__actions__ = []); - actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); } return new LodashWrapper(result, chainAll); } From 224a6c1e7c2803a4a2cec34bb344ef8cf6c40c3e Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 4 Jun 2015 09:40:30 -0700 Subject: [PATCH 040/107] Adjust lazy eval heuristic. --- lodash.src.js | 40 +++++++++++++++++++++++----------------- test/test.js | 4 ++-- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index d9930dc215..3443966086 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1162,22 +1162,25 @@ * @returns {*} Returns the unwrapped value. */ function lazyValue() { - var array = this.__wrapped__.value(); - if (!isArray(array)) { - return baseWrapperValue(array, this.__actions__); - } - var dir = this.__dir__, + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), isRight = dir < 0, - view = getView(0, array.length, this.__views__), + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : (start - 1), - takeCount = nativeMin(length, this.__takeCount__), iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, - result = []; + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (iterLength < 2 && arrLength == length && takeCount == length)) { + return baseWrapperValue(isRight ? array.reverse() : array, this.__actions__); + } + var result = []; outer: while (length-- && resIndex < takeCount) { @@ -3419,12 +3422,14 @@ } } return function() { - var args = arguments; - if (wrapper && args.length == 1 && isArray(args[0])) { - return wrapper.plant(args[0]).value(); + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); } var index = 0, - result = length ? funcs[index].apply(this, args) : args[0]; + result = length ? funcs[index].apply(this, args) : value; while (++index < length) { result = funcs[index].call(this, result); @@ -6167,15 +6172,16 @@ var value = this.__wrapped__; var interceptor = function(value) { - return value.reverse(); + return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse(); }; if (value instanceof LazyWrapper) { + var wrapped = value; if (this.__actions__.length) { - value = new LazyWrapper(this); + wrapped = new LazyWrapper(this); } - value = value.reverse(); - value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); - return new LodashWrapper(value, this.__chain__); + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + return new LodashWrapper(wrapped, this.__chain__); } return this.thru(interceptor); } diff --git a/test/test.js b/test/test.js index d151692e29..fa3f83d423 100644 --- a/test/test.js +++ b/test/test.js @@ -2240,7 +2240,7 @@ : fn(take2, _.compact, filter2, map2); filterCount = mapCount = 0; - deepEqual(combined(_.range(100)), [4, 16]); + deepEqual(combined(_.range(200)), [4, 16]); if (!isNpm && WeakMap && WeakMap.name) { strictEqual(filterCount, 5, 'filterCount'); @@ -4050,7 +4050,7 @@ args = slice.call(arguments); }).value(); - deepEqual(args, [16]); + deepEqual(args, expected); _(array).map(square).dropRightWhile(function() { args = slice.call(arguments); From 7a9011c7e100ead04ba02ee4e9e1b7348e28f0e0 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 4 Jun 2015 09:40:54 -0700 Subject: [PATCH 041/107] Add `modArgs` to `lodash` doc block. [ci skip] --- lodash.src.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 3443966086..eef31f7081 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -859,10 +859,10 @@ * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`, - * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`, - * `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, - * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, + * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `modArgs`, `negate`, + * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, + * `plant`, `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, + * `rearg`, `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, From 9e1f68d9eb20927a6437ef2919c8397743edc625 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 4 Jun 2015 19:27:19 -0700 Subject: [PATCH 042/107] Update vendor/backbone to 1.2.1. --- vendor/backbone/backbone.js | 237 +++++++++++++++-------------- vendor/backbone/test/collection.js | 43 +++++- vendor/backbone/test/events.js | 18 +++ vendor/backbone/test/model.js | 15 ++ vendor/backbone/test/router.js | 2 +- vendor/backbone/test/view.js | 42 ++++- 6 files changed, 229 insertions(+), 128 deletions(-) diff --git a/vendor/backbone/backbone.js b/vendor/backbone/backbone.js index 8ebdac9304..58800425c7 100644 --- a/vendor/backbone/backbone.js +++ b/vendor/backbone/backbone.js @@ -1,4 +1,4 @@ -// Backbone.js 1.2.0 +// Backbone.js 1.2.1 // (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Backbone may be freely distributed under the MIT license. @@ -40,12 +40,11 @@ // restored later on, if `noConflict` is used. var previousBackbone = root.Backbone; - // Create local references to array methods we'll want to use later. - var array = []; - var slice = array.slice; + // Create a local reference to a common array method we'll want to use later. + var slice = [].slice; // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '1.2.0'; + Backbone.VERSION = '1.2.1'; // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns // the `$` variable. @@ -69,6 +68,35 @@ // form param named `model`. Backbone.emulateJSON = false; + // Proxy Underscore methods to a Backbone class' prototype using a + // particular attribute as the data argument + var addMethod = function(length, method, attribute) { + switch (length) { + case 1: return function() { + return _[method](this[attribute]); + }; + case 2: return function(value) { + return _[method](this[attribute], value); + }; + case 3: return function(iteratee, context) { + return _[method](this[attribute], iteratee, context); + }; + case 4: return function(iteratee, defaultVal, context) { + return _[method](this[attribute], iteratee, defaultVal, context); + }; + default: return function() { + var args = slice.call(arguments); + args.unshift(this[attribute]); + return _[method].apply(_, args); + }; + } + }; + var addUnderscoreMethods = function(Class, methods, attribute) { + _.each(methods, function(length, method) { + if (_[method]) Class.prototype[method] = addMethod(length, method, attribute); + }); + }; + // Backbone.Events // --------------- @@ -96,6 +124,7 @@ var i = 0, names; if (name && typeof name === 'object') { // Handle event maps. + if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback; for (names = _.keys(name); i < names.length ; i++) { memo = iteratee(memo, names[i], name[names[i]], opts); } @@ -205,7 +234,7 @@ // No events to consider. if (!events) return; - var i = 0, length, listening; + var i = 0, listening; var context = options.context, listeners = options.listeners; // Delete all events listeners and "drop" events. @@ -274,7 +303,7 @@ }; // Reduces the event callbacks into a map of `{event: onceWrapper}`. - // `offer` unbinds the `onceWrapper` after it as been called. + // `offer` unbinds the `onceWrapper` after it has been called. var onceMap = function(map, name, callback, offer) { if (callback) { var once = map[name] = _.once(function() { @@ -327,35 +356,6 @@ } }; - // Proxy Underscore methods to a Backbone class' prototype using a - // particular attribute as the data argument - var addMethod = function(length, method, attribute) { - switch (length) { - case 1: return function() { - return _[method](this[attribute]); - }; - case 2: return function(value) { - return _[method](this[attribute], value); - }; - case 3: return function(iteratee, context) { - return _[method](this[attribute], iteratee, context); - }; - case 4: return function(iteratee, defaultVal, context) { - return _[method](this[attribute], iteratee, defaultVal, context); - }; - default: return function() { - var args = slice.call(arguments); - args.unshift(this[attribute]); - return _[method].apply(_, args); - }; - } - }; - var addUnderscoreMethods = function(Class, methods, attribute) { - _.each(methods, function(length, method) { - if (_[method]) Class.prototype[method] = addMethod(length, method, attribute); - }); - }; - // Aliases for backwards compatibility. Events.bind = Events.on; Events.unbind = Events.off; @@ -444,10 +444,10 @@ // the core primitive operation of a model, updating the data and notifying // anyone who needs to know about the change in state. The heart of the beast. set: function(key, val, options) { - var attr, attrs, unset, changes, silent, changing, prev, current; if (key == null) return this; // Handle both `"key", value` and `{key: value}` -style arguments. + var attrs; if (typeof key === 'object') { attrs = key; options = val; @@ -461,29 +461,32 @@ if (!this._validate(attrs, options)) return false; // Extract attributes and options. - unset = options.unset; - silent = options.silent; - changes = []; - changing = this._changing; - this._changing = true; + var unset = options.unset; + var silent = options.silent; + var changes = []; + var changing = this._changing; + this._changing = true; if (!changing) { this._previousAttributes = _.clone(this.attributes); this.changed = {}; } - current = this.attributes, prev = this._previousAttributes; + + var current = this.attributes; + var changed = this.changed; + var prev = this._previousAttributes; // Check for changes of `id`. if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; // For each `set` attribute, update or delete the current value. - for (attr in attrs) { + for (var attr in attrs) { val = attrs[attr]; if (!_.isEqual(current[attr], val)) changes.push(attr); if (!_.isEqual(prev[attr], val)) { - this.changed[attr] = val; + changed[attr] = val; } else { - delete this.changed[attr]; + delete changed[attr]; } unset ? delete current[attr] : current[attr] = val; } @@ -539,13 +542,14 @@ // determining if there *would be* a change. changedAttributes: function(diff) { if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; - var val, changed = false; var old = this._changing ? this._previousAttributes : this.attributes; + var changed = {}; for (var attr in diff) { - if (_.isEqual(old[attr], (val = diff[attr]))) continue; - (changed || (changed = {}))[attr] = val; + var val = diff[attr]; + if (_.isEqual(old[attr], val)) continue; + changed[attr] = val; } - return changed; + return _.size(changed) ? changed : false; }, // Get the previous value of an attribute, recorded at the time the last @@ -564,12 +568,12 @@ // Fetch the model from the server, merging the response with the model's // local attributes. Any changed attributes will trigger a "change" event. fetch: function(options) { - options = options ? _.clone(options) : {}; - if (options.parse === void 0) options.parse = true; + options = _.extend({parse: true}, options); var model = this; var success = options.success; options.success = function(resp) { - if (!model.set(model.parse(resp, options), options)) return false; + var serverAttrs = options.parse ? model.parse(resp, options) : resp; + if (!model.set(serverAttrs, options)) return false; if (success) success.call(options.context, model, resp, options); model.trigger('sync', model, resp, options); }; @@ -581,9 +585,8 @@ // If the server returns an attributes hash that differs, the model's // state will be `set` again. save: function(key, val, options) { - var attrs, method, xhr, attributes = this.attributes, wait; - // Handle both `"key", value` and `{key: value}` -style arguments. + var attrs; if (key == null || typeof key === 'object') { attrs = key; options = val; @@ -591,8 +594,8 @@ (attrs = {})[key] = val; } - options = _.extend({validate: true}, options); - wait = options.wait; + options = _.extend({validate: true, parse: true}, options); + var wait = options.wait; // If we're not waiting and attributes exist, save acts as // `set(attr).save(null, opts)` with validation. Otherwise, check if @@ -603,35 +606,31 @@ if (!this._validate(attrs, options)) return false; } - // Set temporary attributes if `{wait: true}`. - if (attrs && wait) { - this.attributes = _.extend({}, attributes, attrs); - } - // After a successful server-side save, the client is (optionally) // updated with the server-side state. - if (options.parse === void 0) options.parse = true; var model = this; var success = options.success; + var attributes = this.attributes; options.success = function(resp) { // Ensure attributes are restored during synchronous saves. model.attributes = attributes; var serverAttrs = options.parse ? model.parse(resp, options) : resp; - if (wait) serverAttrs = _.extend(attrs || {}, serverAttrs); - if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { - return false; - } + if (wait) serverAttrs = _.extend({}, attrs, serverAttrs); + if (serverAttrs && !model.set(serverAttrs, options)) return false; if (success) success.call(options.context, model, resp, options); model.trigger('sync', model, resp, options); }; wrapError(this, options); - method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); + // Set temporary attributes if `{wait: true}` to properly find new ids. + if (attrs && wait) this.attributes = _.extend({}, attributes, attrs); + + var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); if (method === 'patch' && !options.attrs) options.attrs = attrs; - xhr = this.sync(method, this, options); + var xhr = this.sync(method, this, options); // Restore attributes. - if (attrs && wait) this.attributes = attributes; + this.attributes = attributes; return xhr; }, @@ -676,8 +675,8 @@ _.result(this.collection, 'url') || urlError(); if (this.isNew()) return base; - var id = this.id || this.attributes[this.idAttribute]; - return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(id); + var id = this.get(this.idAttribute); + return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id); }, // **parse** converts a response into the hash of attributes to be `set` on @@ -698,7 +697,7 @@ // Check if the model is currently in a valid state. isValid: function(options) { - return this._validate({}, _.extend(options || {}, { validate: true })); + return this._validate({}, _.defaults({validate: true}, options)); }, // Run validation against the next complete set of model attributes, @@ -761,7 +760,7 @@ // The JSON representation of a Collection is an array of the // models' attributes. toJSON: function(options) { - return this.map(function(model){ return model.toJSON(options); }); + return this.map(function(model) { return model.toJSON(options); }); }, // Proxy `Backbone.sync` by default. @@ -776,12 +775,12 @@ // Remove a model, or a list of models from the set. remove: function(models, options) { - var singular = !_.isArray(models), removed; + options = _.extend({}, options); + var singular = !_.isArray(models); models = singular ? [models] : _.clone(models); - options || (options = {}); - removed = this._removeModels(models, options); + var removed = this._removeModels(models, options); if (!options.silent && removed) this.trigger('update', this, options); - return singular ? models[0] : models; + return singular ? removed[0] : removed; }, // Update a collection by `set`-ing a new list of models, adding new ones, @@ -790,7 +789,7 @@ // the core operation for updating the data contained by the collection. set: function(models, options) { options = _.defaults({}, options, setOptions); - if (options.parse) models = this.parse(models, options); + if (options.parse && !this._isModel(models)) models = this.parse(models, options); var singular = !_.isArray(models); models = singular ? (models ? [models] : []) : models.slice(); var id, model, attrs, existing, sort; @@ -910,8 +909,7 @@ // Remove a model from the end of the collection. pop: function(options) { var model = this.at(this.length - 1); - this.remove(model, options); - return model; + return this.remove(model, options); }, // Add a model to the beginning of the collection. @@ -922,8 +920,7 @@ // Remove a model from the beginning of the collection. shift: function(options) { var model = this.at(0); - this.remove(model, options); - return model; + return this.remove(model, options); }, // Slice out a sub-array of models from the collection. @@ -986,8 +983,7 @@ // collection when they arrive. If `reset: true` is passed, the response // data will be passed through the `reset` method instead of `set`. fetch: function(options) { - options = options ? _.clone(options) : {}; - if (options.parse === void 0) options.parse = true; + options = _.extend({parse: true}, options); var success = options.success; var collection = this; options.success = function(resp) { @@ -1006,7 +1002,8 @@ create: function(model, options) { options = options ? _.clone(options) : {}; var wait = options.wait; - if (!(model = this._prepareModel(model, options))) return false; + model = this._prepareModel(model, options); + if (!model) return false; if (!wait) this.add(model, options); var collection = this; var success = options.success; @@ -1060,31 +1057,27 @@ return false; }, - // Internal method called by both remove and set. Does not trigger any - // additional events. Returns true if anything was actually removed. + // Internal method called by both remove and set. + // Returns removed models, or false if nothing is removed. _removeModels: function(models, options) { - var i, l, index, model, removed = false; - for (var i = 0, j = 0; i < models.length; i++) { - var model = models[i] = this.get(models[i]); + var removed = []; + for (var i = 0; i < models.length; i++) { + var model = this.get(models[i]); if (!model) continue; - var id = this.modelId(model.attributes); - if (id != null) delete this._byId[id]; - delete this._byId[model.cid]; + var index = this.indexOf(model); this.models.splice(index, 1); this.length--; + if (!options.silent) { options.index = index; model.trigger('remove', model, this, options); } - models[j++] = model; + + removed.push(model); this._removeReference(model, options); - removed = true; } - // We only need to slice if models array should be smaller, which is - // caused by some models not actually getting removed. - if (models.length !== j) models = models.slice(0, j); - return removed; + return removed.length ? removed : false; }, // Method for checking whether an object should be considered a model for @@ -1103,6 +1096,9 @@ // Internal method to sever a model's ties to a collection. _removeReference: function(model, options) { + delete this._byId[model.cid]; + var id = this.modelId(model.attributes); + if (id != null) delete this._byId[id]; if (this === model.collection) delete model.collection; model.off('all', this._onModelEvent, this); }, @@ -1133,7 +1129,7 @@ var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4, foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3, select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 2, - contains: 2, invoke: 2, max: 3, min: 3, toArray: 1, size: 1, first: 3, + contains: 2, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, isEmpty: 1, chain: 1, sample: 3, partition: 3 }; @@ -1170,7 +1166,6 @@ // if an existing element is not provided... var View = Backbone.View = function(options) { this.cid = _.uniqueId('view'); - options || (options = {}); _.extend(this, _.pick(options, viewOptions)); this._ensureElement(); this.initialize.apply(this, arguments); @@ -1253,11 +1248,12 @@ // Uses event delegation for efficiency. // Omitting the selector binds the event to `this.el`. delegateEvents: function(events) { - if (!(events || (events = _.result(this, 'events')))) return this; + events || (events = _.result(this, 'events')); + if (!events) return this; this.undelegateEvents(); for (var key in events) { var method = events[key]; - if (!_.isFunction(method)) method = this[events[key]]; + if (!_.isFunction(method)) method = this[method]; if (!method) continue; var match = key.match(delegateEventSplitter); this.delegate(match[1], match[2], _.bind(method, this)); @@ -1270,6 +1266,7 @@ // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. delegate: function(eventName, selector, listener) { this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); + return this; }, // Clears all callbacks previously bound to the view by `delegateEvents`. @@ -1284,6 +1281,7 @@ // `selector` and `listener` are both optional. undelegate: function(eventName, selector, listener) { this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); + return this; }, // Produces a DOM element to be assigned to your view. Exposed for @@ -1647,15 +1645,16 @@ // support the `hashchange` event, HTML5 history, or the user wants // `hashChange` but not `pushState`. if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) { - var iframe = document.createElement('iframe'); - iframe.src = 'javascript:0'; - iframe.style.display = 'none'; - iframe.tabIndex = -1; + this.iframe = document.createElement('iframe'); + this.iframe.src = 'javascript:0'; + this.iframe.style.display = 'none'; + this.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.iframe.document.open().close(); - this.iframe.location.hash = '#' + this.fragment; + var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow; + iWindow.document.open(); + iWindow.document.close(); + iWindow.location.hash = '#' + this.fragment; } // Add a cross-platform `addEventListener` shim for older browsers. @@ -1693,7 +1692,7 @@ // Clean up the iframe if necessary. if (this.iframe) { - document.body.removeChild(this.iframe.frameElement); + document.body.removeChild(this.iframe); this.iframe = null; } @@ -1716,7 +1715,7 @@ // If the user pressed the back button, the iframe's hash will have // changed and we should use that for comparison. if (current === this.fragment && this.iframe) { - current = this.getHash(this.iframe); + current = this.getHash(this.iframe.contentWindow); } if (current === this.fragment) return false; @@ -1774,12 +1773,18 @@ // fragment to store history. } else if (this._wantsHashChange) { this._updateHash(this.location, fragment, options.replace); - if (this.iframe && (fragment !== this.getHash(this.iframe))) { + if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) { + var iWindow = this.iframe.contentWindow; + // Opening and closing the iframe tricks IE7 and earlier to push a // history entry on hash-tag change. When replace is true, we don't // want this. - if (!options.replace) this.iframe.document.open().close(); - this._updateHash(this.iframe.location, fragment, options.replace); + if (!options.replace) { + iWindow.document.open(); + iWindow.document.close(); + } + + this._updateHash(iWindow.location, fragment, options.replace); } // If you've told us that you explicitly don't want fallback hashchange- diff --git a/vendor/backbone/test/collection.js b/vendor/backbone/test/collection.js index 51a9b7befd..fa84818612 100644 --- a/vendor/backbone/test/collection.js +++ b/vendor/backbone/test/collection.js @@ -298,17 +298,13 @@ deepEqual(col.pluck('id'), [1, 2, 3]); }); - test("remove", 7, function() { + test("remove", 10, function() { var removed = null; - var otherRemoved = null; var result = null; col.on('remove', function(model, col, options) { removed = model.get('label'); equal(options.index, 3); }); - otherCol.on('remove', function(model, col, options) { - otherRemoved = true; - }); result = col.remove(d); equal(removed, 'd'); strictEqual(result, d); @@ -317,7 +313,13 @@ strictEqual(result, undefined); equal(col.length, 3); equal(col.first(), a); - equal(otherRemoved, null); + col.off(); + result = col.remove([c, d]); + equal(result.length, 1, 'only returns removed models'); + equal(result[0], c, 'only returns removed models'); + result = col.remove([c, b]); + equal(result.length, 1, 'only returns removed models'); + equal(result[0], b, 'only returns removed models'); }); test("add and remove return values", 13, function() { @@ -559,6 +561,20 @@ }); + test("create with wait:true should not call collection.parse", 0, function() { + var Collection = Backbone.Collection.extend({ + url: '/test', + parse: function () { + ok(false); + } + }); + + var collection = new Collection; + + collection.create({}, {wait: true}); + this.ajaxSettings.success(); + }); + test("a failing create returns model with errors", function() { var ValidatingModel = Backbone.Model.extend({ validate: function(attrs) { @@ -1605,4 +1621,19 @@ collection.set([{id: 1}, {id: 2}]); }); + test("#3610 - invoke collects arguments", 3, function() { + var Model = Backbone.Model.extend({ + method: function(a, b, c) { + equal(a, 1); + equal(b, 2); + equal(c, 3); + } + }); + var Collection = Backbone.Collection.extend({ + model: Model + }); + var collection = new Collection([{id: 1}]); + collection.invoke('method', 1, 2, 3); + }); + })(); diff --git a/vendor/backbone/test/events.js b/vendor/backbone/test/events.js index 017cf47f6b..a2730bc01d 100644 --- a/vendor/backbone/test/events.js +++ b/vendor/backbone/test/events.js @@ -66,6 +66,24 @@ equal(obj.counter, 5); }); + test("binding and trigger with event maps context", 2, function() { + var obj = { counter: 0 }; + var context = {}; + _.extend(obj, Backbone.Events); + + obj.on({ + a: function() { + strictEqual(this, context, 'defaults `context` to `callback` param'); + } + }, context).trigger('a'); + + obj.off().on({ + a: function() { + strictEqual(this, context, 'will not override explicit `context` param'); + } + }, this, context).trigger('a'); + }); + test("listenTo and stopListening", 1, function() { var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); diff --git a/vendor/backbone/test/model.js b/vendor/backbone/test/model.js index 94647bbd03..faaf61dda3 100644 --- a/vendor/backbone/test/model.js +++ b/vendor/backbone/test/model.js @@ -550,6 +550,21 @@ model.destroy(options); }); + test("#3470 - save and fetch with parse false", 2, function() { + var i = 0; + var model = new Backbone.Model(); + model.parse = function() { + ok(false); + }; + model.sync = function(method, model, options) { + options.success({i: ++i}); + }; + model.fetch({parse: false}); + equal(model.get('i'), i); + model.save(null, {parse: false}); + equal(model.get('i'), i); + }); + test("save with PATCH", function() { doc.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4}); doc.save(); diff --git a/vendor/backbone/test/router.js b/vendor/backbone/test/router.js index db2db909c2..acd17cecb0 100644 --- a/vendor/backbone/test/router.js +++ b/vendor/backbone/test/router.js @@ -918,7 +918,7 @@ test('#3358 - pushState to hashChange transition with search params', 1, function() { Backbone.history.stop(); - location.replace('/root?foo=bar'); + location.replace('http://example.com/root?foo=bar'); location.replace = function(url) { strictEqual(url, '/root#?foo=bar'); }; diff --git a/vendor/backbone/test/view.js b/vendor/backbone/test/view.js index 392a50f790..a3e2697490 100644 --- a/vendor/backbone/test/view.js +++ b/vendor/backbone/test/view.js @@ -48,6 +48,11 @@ strictEqual(new View().one, 1); }); + test("render", 1, function() { + var view = new Backbone.View; + equal(view.render(), view, '#render returns the view instance'); + }); + test("delegateEvents", 6, function() { var counter1 = 0, counter2 = 0; @@ -72,7 +77,7 @@ equal(counter2, 3); }); - test("delegate", 2, function() { + test("delegate", 3, function() { var view = new Backbone.View({el: '#testElement'}); view.delegate('click', 'h1', function() { ok(true); @@ -81,6 +86,8 @@ ok(true); }); view.$('h1').trigger('click'); + + equal(view.delegate(), view, '#delegate returns the view instance'); }); test("delegateEvents allows functions for callbacks", 3, function() { @@ -112,7 +119,7 @@ view.$el.trigger('click'); }); - test("undelegateEvents", 6, function() { + test("undelegateEvents", 7, function() { var counter1 = 0, counter2 = 0; var view = new Backbone.View({el: '#testElement'}); @@ -135,9 +142,11 @@ view.$('h1').trigger('click'); equal(counter1, 2); equal(counter2, 3); + + equal(view.undelegateEvents(), view, '#undelegateEvents returns the view instance'); }); - test("undelegate", 0, function() { + test("undelegate", 1, function() { view = new Backbone.View({el: '#testElement'}); view.delegate('click', function() { ok(false); }); view.delegate('click', 'h1', function() { ok(false); }); @@ -146,6 +155,8 @@ view.$('h1').trigger('click'); view.$el.trigger('click'); + + equal(view.undelegate(), view, '#undelegate returns the view instance'); }); test("undelegate with passed handler", 1, function() { @@ -387,14 +398,14 @@ equal(counter, 2); }); - test("remove", 1, function() { + test("remove", 2, function() { var view = new Backbone.View; document.body.appendChild(view.el); view.delegate('click', function() { ok(false); }); view.listenTo(view, 'all x', function() { ok(false); }); - view.remove(); + equal(view.remove(), view, '#remove returns the view instance'); view.$el.trigger('click'); view.trigger('x'); @@ -402,4 +413,25 @@ notEqual(view.el.parentNode, document.body); }); + test("setElement", 3, function() { + var view = new Backbone.View({ + events: { + click: function() { ok(false); } + } + }); + view.events = { + click: function() { ok(true); } + }; + var oldEl = view.el; + var $oldEl = view.$el; + + view.setElement(document.createElement('div')); + + $oldEl.click(); + view.$el.click(); + + notEqual(oldEl, view.el); + notEqual($oldEl, view.$el); + }); + })(); From 56f199bd69e2f20478d7595c4786d4e36dd3b020 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 4 Jun 2015 21:14:26 -0700 Subject: [PATCH 043/107] Make `_.sortByOrder` support orders of "asc" and "desc". --- lodash.src.js | 31 ++++++++++++++++--------------- test/test.js | 16 ++++++++++------ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index eef31f7081..426fc7a32b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -416,8 +416,8 @@ * sort them in ascending order. * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @returns {number} Returns the sort order indicator for `object`. */ function compareAscending(object, other) { @@ -425,16 +425,16 @@ } /** - * Used by `_.sortByOrder` to compare multiple properties of each element - * in a collection and stable sort them in the following order: + * Used by `_.sortByOrder` to compare multiple properties of a value to another + * and stable sort them. * - * If `orders` is unspecified, sort in ascending order for all properties. - * Otherwise, for each property, sort in ascending order if its corresponding value in - * orders is true, and descending order if false. + * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise, + * a value is sorted in ascending order if its corresponding order is "asc", and + * descending if "desc". * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @param {boolean[]} orders The order to sort by for each property. * @returns {number} Returns the sort order indicator for `object`. */ @@ -451,7 +451,8 @@ if (index >= ordersLength) { return result; } - return result * (orders[index] ? 1 : -1); + var order = orders[index]; + return result * ((order === 'asc' || order === true) ? 1 : -1); } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications @@ -7263,9 +7264,9 @@ /** * This method is like `_.sortByAll` except that it allows specifying the - * sort orders of the iteratees to sort by. A truthy value in `orders` will - * sort the corresponding property name in ascending order while a falsey - * value will sort it in descending order. + * sort orders of the iteratees to sort by. If `orders` is unspecified, all + * values are sorted in ascending order. Otherwise, a value is sorted in + * ascending order if its corresponding order is "asc", and descending if "desc". * * If a property name is provided for an iteratee the created `_.property` * style callback returns the property value of the given element. @@ -7279,7 +7280,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {boolean[]} orders The sort orders of `iteratees`. + * @param {boolean[]} [orders] The sort orders of `iteratees`. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Array} Returns the new sorted array. * @example @@ -7292,7 +7293,7 @@ * ]; * * // sort by `user` in ascending order and by `age` in descending order - * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values); + * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values); * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] */ function sortByOrder(collection, iteratees, orders, guard) { diff --git a/test/test.js b/test/test.js index fa3f83d423..e384bbe153 100644 --- a/test/test.js +++ b/test/test.js @@ -14525,14 +14525,18 @@ { 'a': 'y', 'b': 2 } ]; - test('should sort multiple properties by specified orders', 1, function() { - var actual = _.sortByOrder(objects, ['a', 'b'], [false, true]); - deepEqual(actual, [objects[3], objects[1], objects[2], objects[0]]); + test('should sort multiple properties by specified orders', 2, function() { + _.each([[false, true], ['desc', 'asc']], function(orders) { + var actual = _.sortByOrder(objects, ['a', 'b'], orders); + deepEqual(actual, [objects[3], objects[1], objects[2], objects[0]]); + }); }); - test('should sort a property in ascending order when its order is not specified', 1, function() { - var actual = _.sortByOrder(objects, ['a', 'b'], [false]); - deepEqual(actual, [objects[3], objects[1], objects[2], objects[0]]); + test('should sort a property in ascending order when its order is not specified', 2, function() { + _.each([[false], ['desc']], function(orders) { + var actual = _.sortByOrder(objects, ['a', 'b'], orders); + deepEqual(actual, [objects[3], objects[1], objects[2], objects[0]]); + }); }); }()); From 948faf6cf9e4086319c0597a5fa7569039222b4d Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 4 Jun 2015 21:15:09 -0700 Subject: [PATCH 044/107] Fix `object` doc param typo for `equalByTag`. [ci skip] --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 426fc7a32b..e2908e752d 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3840,7 +3840,7 @@ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private - * @param {Object} value The object to compare. + * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. From 497cde7e926eb179438254acdfaf06a9d290197e Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 5 Jun 2015 17:30:39 -0700 Subject: [PATCH 045/107] Add `LARGE_ARRAY_SIZE` to more easily track what's considered a large array. --- lodash.src.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index e2908e752d..a7fa0cfcfd 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -33,6 +33,9 @@ var HOT_COUNT = 150, HOT_SPAN = 16; + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** Used to indicate the type of lazy iteratees. */ var LAZY_DROP_WHILE_FLAG = 0, LAZY_FILTER_FLAG = 1, @@ -1178,7 +1181,7 @@ resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); - if (!isArr || (iterLength < 2 && arrLength == length && takeCount == length)) { + if (!isArr || array.length < LARGE_ARRAY_SIZE || (iterLength < 2 && arrLength == length && takeCount == length)) { return baseWrapperValue(isRight ? array.reverse() : array, this.__actions__); } var result = []; @@ -1912,7 +1915,7 @@ var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, - cache = (isCommon && values.length >= 200) ? createCache(values) : null, + cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, valuesLength = values.length; if (cache) { @@ -2787,7 +2790,7 @@ indexOf = getIndexOf(), length = array.length, isCommon = indexOf == baseIndexOf, - isLarge = isCommon && length >= 200, + isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; @@ -3426,7 +3429,7 @@ var args = arguments, value = args[0]; - if (wrapper && args.length == 1 && isArray(value)) { + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { return wrapper.plant(value).value(); } var index = 0, From e143936a8291480c5e6fa5bb5ba019d411ac9535 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 6 Jun 2015 14:53:31 -0700 Subject: [PATCH 046/107] Simplify lazy chaining by removing support for `dropWhile` and `dropRightWhile`. --- lodash.src.js | 104 +++++++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 65 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index a7fa0cfcfd..0388eef9dd 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -37,8 +37,7 @@ var LARGE_ARRAY_SIZE = 200; /** Used to indicate the type of lazy iteratees. */ - var LAZY_DROP_WHILE_FLAG = 0, - LAZY_FILTER_FLAG = 1, + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; /** Used as the `TypeError` message for "Functions" methods. */ @@ -1111,7 +1110,6 @@ this.__wrapped__ = value; this.__actions__ = []; this.__dir__ = 1; - this.__dropCount__ = 0; this.__filtered__ = false; this.__iteratees__ = []; this.__takeCount__ = POSITIVE_INFINITY; @@ -1196,30 +1194,16 @@ while (++iterIndex < iterLength) { var data = iteratees[iterIndex], iteratee = data.iteratee, - type = data.type; + type = data.type, + computed = iteratee(value); - if (type == LAZY_DROP_WHILE_FLAG) { - if (data.done && (isRight ? (index > data.index) : (index < data.index))) { - data.count = 0; - data.done = false; - } - data.index = index; - if (!data.done) { - var limit = data.limit; - if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) { - continue outer; - } - } - } else { - var computed = iteratee(value); - if (type == LAZY_MAP_FLAG) { - value = computed; - } else if (!computed) { - if (type == LAZY_FILTER_FLAG) { - continue outer; - } else { - break outer; - } + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; } } } @@ -12177,44 +12161,18 @@ lodash[methodName].placeholder = lodash; }); - // Add `LazyWrapper` methods that accept an `iteratee` value. - arrayEach(['dropWhile', 'filter', 'map', 'takeWhile'], function(methodName, type) { - var isFilter = type != LAZY_MAP_FLAG, - isDropWhile = type == LAZY_DROP_WHILE_FLAG; - - LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { - var filtered = this.__filtered__, - result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(); - - result.__iteratees__.push({ - 'done': false, - 'count': 0, - 'index': 0, - 'iteratee': getCallback(iteratee, thisArg, 1), - 'limit': -1, - 'type': type - }); - - result.__filtered__ = filtered || isFilter; - return result; - }; - }); - // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. arrayEach(['drop', 'take'], function(methodName, index) { - var whileName = methodName + 'While'; - LazyWrapper.prototype[methodName] = function(n) { - var filtered = this.__filtered__, - result = (filtered && !index) ? this.dropWhile() : this.clone(); - + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } n = n == null ? 1 : nativeMax(floor(n) || 0, 0); + + var result = this.clone(); if (filtered) { - if (index) { - result.__takeCount__ = nativeMin(result.__takeCount__, n); - } else { - last(result.__iteratees__).limit = n; - } + result.__takeCount__ = nativeMin(result.__takeCount__, n); } else { result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); } @@ -12224,9 +12182,18 @@ LazyWrapper.prototype[methodName + 'Right'] = function(n) { return this.reverse()[methodName](n).reverse(); }; + }); - LazyWrapper.prototype[methodName + 'RightWhile'] = function(predicate, thisArg) { - return this.reverse()[whileName](predicate, thisArg).reverse(); + // Add `LazyWrapper` methods that accept an `iteratee` value. + arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { + var type = index + 1, + isFilter = type != LAZY_MAP_FLAG; + + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ 'iteratee': getCallback(iteratee, thisArg, 1), 'type': type }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; }; }); @@ -12244,7 +12211,7 @@ var dropName = 'drop' + (index ? '' : 'Right'); LazyWrapper.prototype[methodName] = function() { - return this[dropName](1); + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); }; }); @@ -12273,10 +12240,13 @@ start = start == null ? 0 : (+start || 0); var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } if (start < 0) { - result = this.takeRight(-start); + result = result.takeRight(-start); } else if (start) { - result = this.drop(start); + result = result.drop(start); } if (end !== undefined) { end = (+end || 0); @@ -12285,8 +12255,12 @@ return result; }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { - return this.drop(0); + return this.take(POSITIVE_INFINITY); }; // Add `LazyWrapper` methods to `lodash.prototype`. From ab981ce15a1e3f34289fb990006265ddfaed3e83 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 6 Jun 2015 14:53:45 -0700 Subject: [PATCH 047/107] Update lazy tests using larger arrays. --- test/test.js | 387 +++++++++++++++++++++++---------------------------- 1 file changed, 173 insertions(+), 214 deletions(-) diff --git a/test/test.js b/test/test.js index e384bbe153..666c257b0c 100644 --- a/test/test.js +++ b/test/test.js @@ -2161,10 +2161,10 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [1, null, 3], - actual = _(array).map(square).compact().reverse().take().value(); + var array = _.range(0, LARGE_ARRAY_SIZE).concat(null), + actual = _(array).slice(1).compact().reverse().take().value(); - deepEqual(actual, [9]); + deepEqual(actual, _.take(_.compact(_.slice(array, 1)).reverse())); } else { skipTest(); @@ -2408,11 +2408,15 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [1, 2, 1, 3], - predicate = function(value) { return value > 2; }, - actual = _(array).countBy(_.identity).map(square).filter(predicate).take().value(); + var array = _.range(LARGE_ARRAY_SIZE).concat( + _.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE), + _.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZE) + ); + + var predicate = function(value) { return value > 2; }, + actual = _(array).countBy().map(square).filter(predicate).take().value(); - deepEqual(actual, [4]); + deepEqual(actual, _.take(_.filter(_.map(_.countBy(array), square), predicate))); } else { skipTest(); @@ -3862,25 +3866,25 @@ test('should work in a lazy chain sequence', 6, function() { if (!isNpm) { - var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), values = [], predicate = function(value) { values.push(value); return value > 2; }, actual = _(array).drop(2).drop().value(); - deepEqual(actual, [4, 5, 6, 7, 8, 9, 10]); + deepEqual(actual, array.slice(3)); actual = _(array).filter(predicate).drop(2).drop().value(); - deepEqual(actual, [6, 7, 8, 9, 10]); deepEqual(values, array); + deepEqual(actual, _.drop(_.drop(_.filter(array, predicate), 2))); actual = _(array).drop(2).dropRight().drop().dropRight(2).value(); - deepEqual(actual, [4, 5, 6, 7]); + deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(array, 2))), 2)); values = []; actual = _(array).drop().filter(predicate).drop(2).dropRight().drop().dropRight(2).value(); - deepEqual(actual, [6, 7]); deepEqual(values, array.slice(1)); + deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(_.filter(_.drop(array), predicate), 2))), 2)); } else { skipTest(6); @@ -3932,25 +3936,25 @@ test('should work in a lazy chain sequence', 6, function() { if (!isNpm) { - var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), values = [], predicate = function(value) { values.push(value); return value < 9; }, actual = _(array).dropRight(2).dropRight().value(); - deepEqual(actual, [1, 2, 3, 4, 5, 6, 7]); + deepEqual(actual, array.slice(0, -3)); actual = _(array).filter(predicate).dropRight(2).dropRight().value(); - deepEqual(actual, [1, 2, 3, 4, 5]); deepEqual(values, array); + deepEqual(actual, _.dropRight(_.dropRight(_.filter(array, predicate), 2))); actual = _(array).dropRight(2).drop().dropRight().drop(2).value(); - deepEqual(actual, [4, 5, 6, 7]); + deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(array, 2))), 2)); values = []; actual = _(array).dropRight().filter(predicate).dropRight(2).drop().dropRight().drop(2).value(); - deepEqual(actual, [4, 5]); deepEqual(values, array.slice(0, -1)); + deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(_.filter(_.dropRight(array), predicate), 2))), 2)); } else { skipTest(6); @@ -4022,46 +4026,6 @@ skipTest(2); } }); - - test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { - if (!isNpm) { - var args, - expected = [16, 3, [1, 4, 9 ,16]]; - - _(array).dropRightWhile(function(value, index, array) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, [4, 3, array]); - - _(array).map(square).dropRightWhile(function(value, index, array) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - - _(array).map(square).dropRightWhile(function(value, index) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - - _(array).map(square).dropRightWhile(function(value) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - - _(array).map(square).dropRightWhile(function() { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - } - else { - skipTest(5); - } - }); }()); /*--------------------------------------------------------------------------*/ @@ -4117,13 +4081,14 @@ test('should work in a lazy chain sequence', 3, function() { if (!isNpm) { - var wrapped = _(array).dropWhile(function(num) { - return num < 3; - }); + var array = _.range(1, LARGE_ARRAY_SIZE + 3), + predicate = function(num) { return num < 3; }, + expected = _.dropWhile(array, predicate), + wrapped = _(array).dropWhile(predicate); - deepEqual(wrapped.value(), [3, 4]); - deepEqual(wrapped.reverse().value(), [4, 3]); - strictEqual(wrapped.last(), 4); + deepEqual(wrapped.value(), expected); + deepEqual(wrapped.reverse().value(), expected.slice().reverse()); + strictEqual(wrapped.last(), _.last(expected)); } else { skipTest(3); @@ -4132,58 +4097,20 @@ test('should work in a lazy chain sequence with `drop`', 1, function() { if (!isNpm) { + var array = _.range(1, LARGE_ARRAY_SIZE + 3); + var actual = _(array) .dropWhile(function(num) { return num == 1; }) .drop() .dropWhile(function(num) { return num == 3; }) .value(); - deepEqual(actual, [4]); + deepEqual(actual, array.slice(3)); } else { skipTest(); } }); - - test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { - if (!isNpm) { - var args, - expected = [1, 0, [1, 4, 9, 16]]; - - _(array).dropWhile(function(value, index, array) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, [1, 0, array]); - - _(array).map(square).dropWhile(function(value, index, array) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - - _(array).map(square).dropWhile(function(value, index) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - - _(array).map(square).dropWhile(function(index) { - args = slice.call(arguments); - }).value(); - - deepEqual(args, [1]); - - _(array).map(square).dropWhile(function() { - args = slice.call(arguments); - }).value(); - - deepEqual(args, expected); - } - else { - skipTest(5); - } - }); }()); /*--------------------------------------------------------------------------*/ @@ -4756,7 +4683,7 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [1, 2, 3, 4]; + var array = _.range(1, LARGE_ARRAY_SIZE + 1); var wrapped = _(array).filter(function(value) { return value % 2 == 0; @@ -4818,25 +4745,25 @@ test('should work in a lazy chain sequence', 6, function() { if (!isNpm) { - var array = [1, 2, 3, 4, 5, 6, 7, 8, 9 , 10], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), values = [], predicate = function(value) { values.push(value); return value > 2; }, actual = _(array).take(2).take().value(); - deepEqual(actual, [1]); + deepEqual(actual, _.take(_.take(array, 2))); actual = _(array).filter(predicate).take(2).take().value(); - deepEqual(actual, [3]); - deepEqual(values, array.slice(0, 3)); + deepEqual(values, [1, 2, 3]); + deepEqual(actual, _.take(_.take(_.filter(array, predicate), 2))); actual = _(array).take(6).takeRight(4).take(2).takeRight().value(); - deepEqual(actual, [4]); + deepEqual(actual, _.takeRight(_.take(_.takeRight(_.take(array, 6), 4), 2))); values = []; actual = _(array).take(array.length - 1).filter(predicate).take(6).takeRight(4).take(2).takeRight().value(); - deepEqual(actual, [6]); - deepEqual(values, array.slice(0, -2)); + deepEqual(values, [1, 2, 3, 4, 5, 6, 7, 8]); + deepEqual(actual, _.takeRight(_.take(_.takeRight(_.take(_.filter(_.take(array, array.length - 1), predicate), 6), 4), 2))); } else { skipTest(6); @@ -4888,25 +4815,25 @@ test('should work in a lazy chain sequence', 6, function() { if (!isNpm) { - var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), values = [], predicate = function(value) { values.push(value); return value < 9; }, actual = _(array).takeRight(2).takeRight().value(); - deepEqual(actual, [10]); + deepEqual(actual, _.takeRight(_.takeRight(array))); actual = _(array).filter(predicate).takeRight(2).takeRight().value(); - deepEqual(actual, [8]); deepEqual(values, array); + deepEqual(actual, _.takeRight(_.takeRight(_.filter(array, predicate), 2))); actual = _(array).takeRight(6).take(4).takeRight(2).take().value(); - deepEqual(actual, [7]); + deepEqual(actual, _.take(_.takeRight(_.take(_.takeRight(array, 6), 4), 2))); values = []; actual = _(array).filter(predicate).takeRight(6).take(4).takeRight(2).take().value(); - deepEqual(actual, [5]); deepEqual(values, array); + deepEqual(actual, _.take(_.takeRight(_.take(_.takeRight(_.filter(array, predicate), 6), 4), 2))); } else { skipTest(6); @@ -4967,13 +4894,14 @@ test('should work in a lazy chain sequence', 3, function() { if (!isNpm) { - var wrapped = _(array).takeRightWhile(function(num) { - return num > 2; - }); + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + predicate = function(num) { return num > 2; }, + expected = _.takeRightWhile(array, predicate), + wrapped = _(array).takeRightWhile(predicate); - deepEqual(wrapped.value(), [3, 4]); - deepEqual(wrapped.reverse().value(), [4, 3]); - strictEqual(wrapped.last(), 4); + deepEqual(wrapped.value(), expected); + deepEqual(wrapped.reverse().value(), expected.slice().reverse()); + strictEqual(wrapped.last(), _.last(expected)); } else { skipTest(3); @@ -4983,13 +4911,14 @@ test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - expected = [16, 3, [1, 4, 9 , 16]]; + array = _.range(1, LARGE_ARRAY_SIZE + 1), + expected = [square(LARGE_ARRAY_SIZE), LARGE_ARRAY_SIZE - 1, _.map(array, square)]; _(array).takeRightWhile(function(value, index, array) { args = slice.call(arguments) }).value(); - deepEqual(args, [4, 3, array]); + deepEqual(args, [LARGE_ARRAY_SIZE, LARGE_ARRAY_SIZE - 1, array]); _(array).map(square).takeRightWhile(function(value, index, array) { args = slice.call(arguments) @@ -5007,7 +4936,7 @@ args = slice.call(arguments); }).value(); - deepEqual(args, [16]); + deepEqual(args, [square(LARGE_ARRAY_SIZE)]); _(array).map(square).takeRightWhile(function() { args = slice.call(arguments); @@ -5073,13 +5002,14 @@ test('should work in a lazy chain sequence', 3, function() { if (!isNpm) { - var wrapped = _(array).takeWhile(function(num) { - return num < 3; - }); + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + predicate = function(num) { return num < 3; }, + expected = _.takeWhile(array, predicate), + wrapped = _(array).takeWhile(predicate); - deepEqual(wrapped.value(), [1, 2]); - deepEqual(wrapped.reverse().value(), [2, 1]); - strictEqual(wrapped.last(), 2); + deepEqual(wrapped.value(), expected); + deepEqual(wrapped.reverse().value(), expected.slice().reverse()); + strictEqual(wrapped.last(), _.last(expected)); } else { skipTest(3); @@ -5088,6 +5018,8 @@ test('should work in a lazy chain sequence with `take`', 1, function() { if (!isNpm) { + var array = _.range(1, LARGE_ARRAY_SIZE + 1); + var actual = _(array) .takeWhile(function(num) { return num < 4; }) .take(2) @@ -5104,7 +5036,8 @@ test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - expected = [1, 0, [1, 4, 9, 16]]; + array = _.range(1, LARGE_ARRAY_SIZE + 1), + expected = [1, 0, _.map(array, square)]; _(array).takeWhile(function(value, index, array) { args = slice.call(arguments); @@ -6114,12 +6047,16 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [1, 2, 1, 3], - iteratee = function(value) { value.push(value[0]); return value; }, + var array = _.range(LARGE_ARRAY_SIZE).concat( + _.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE), + _.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZE) + ); + + var iteratee = function(value) { value.push(value[0]); return value; }, predicate = function(value) { return value[0] > 1; }, - actual = _(array).groupBy(_.identity).map(iteratee).filter(predicate).take().value(); + actual = _(array).groupBy().map(iteratee).filter(predicate).take().value(); - deepEqual(actual, [[2, 2]]); + deepEqual(actual, _.take(_.filter(_.map(_.groupBy(array), iteratee), predicate))); } else { skipTest(); @@ -6483,11 +6420,15 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [1, 2, 1, 3], - predicate = function(value) { return value > 2; }, - actual = _(array).indexBy(_.identity).map(square).filter(predicate).take().value(); + var array = _.range(LARGE_ARRAY_SIZE).concat( + _.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE), + _.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZE) + ); + + var predicate = function(value) { return value > 2; }, + actual = _(array).indexBy().map(square).filter(predicate).take().value(); - deepEqual(actual, [4]); + deepEqual(actual, _.take(_.filter(_.map(_.indexBy(array), square), predicate))); } else { skipTest(); @@ -6677,7 +6618,7 @@ test('should work in a lazy chain sequence', 4, function() { if (!isNpm) { - var array = [1, 2, 3], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), values = []; var actual = _(array).initial().filter(function(value) { @@ -6687,7 +6628,7 @@ .value(); deepEqual(actual, []); - deepEqual(values, [1, 2]); + deepEqual(values, _.initial(array)); values = []; @@ -9205,13 +9146,11 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [1, 2, 3, 4]; - - var wrapped = _(array).filter(function(value) { - return value % 2; - }); + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + predicate = function(value) { return value % 2; }, + wrapped = _(array).filter(predicate); - strictEqual(wrapped.last(), 3); + strictEqual(wrapped.last(), _.last(_.filter(array, predicate))); } else { skipTest(); @@ -9479,7 +9418,8 @@ test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - expected = [1, 0, [1, 4, 9]]; + array = _.range(1, LARGE_ARRAY_SIZE + 1), + expected = [1, 0, _.map(array, square)]; _(array).map(function(value, index, array) { args || (args = slice.call(arguments)); @@ -11333,10 +11273,11 @@ if (!isNpm) { _.mixin({ 'a': _.countBy, 'b': _.filter }); - var predicate = function(value) { return value > 2; }, - actual = _([1, 2, 1, 3]).a(_.identity).map(square).b(predicate).take().value(); + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + predicate = function(value) { return value > 2; }, + actual = _(array).a().map(square).b(predicate).take().value(); - deepEqual(actual, [4]); + deepEqual(actual, _.take(_.b(_.map(_.a(array), square), predicate))); delete _.a; delete _.prototype.a; @@ -12332,13 +12273,15 @@ test('should work in a lazy chain sequence', 2, function() { if (!isNpm) { - var array = [{ 'a': 1 }, null, { 'a': 3 }, { 'a': 4 }], - actual = _(array).pluck('a').value(); + var array = _.times(LARGE_ARRAY_SIZE, function(index) { + return index ? { 'a': index } : null; + }); - deepEqual(actual, [1, undefined, 3, 4]); + var actual = _(array).pluck('a').value(); + deepEqual(actual, _.pluck(array, 'a')); - actual = _(array).filter(Boolean).pluck('a').value(); - deepEqual(actual, [1, 3, 4]); + actual = _(array).filter().pluck('a').value(); + deepEqual(actual, _.pluck(_.filter(array), 'a')); } else { skipTest(2); @@ -13241,16 +13184,18 @@ test('`_.' + methodName + '` should work in a lazy chain sequence', 2, function() { if (!isNpm) { - var object = { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, - predicate = function(value) { return isFilter ? (value > 6) : (value < 6); }; - - var expected = [9, 16], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + predicate = function(value) { return isFilter ? (value > 6) : (value < 6); }, actual = _(array).map(square)[methodName](predicate).value(); - deepEqual(actual, expected); + deepEqual(actual, _[methodName](_.map(array, square), predicate)); + + var object = _.zipObject(_.times(LARGE_ARRAY_SIZE, function(index) { + return ['key' + index, index]; + })); actual = _(object).mapValues(square)[methodName](predicate).value(); - deepEqual(actual, expected); + deepEqual(actual, _[methodName](_.mapValues(object, square), predicate)); } else { skipTest(2); @@ -13260,7 +13205,8 @@ test('`_.' + methodName + '` should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - expected = [1, 0, [1, 4, 9, 16]]; + array = _.range(1, LARGE_ARRAY_SIZE + 1), + expected = [1, 0, _.map(array, square)]; _(array)[methodName](function(value, index, array) { args || (args = slice.call(arguments)); @@ -13629,7 +13575,7 @@ test('should work in a lazy chain sequence', 4, function() { if (!isNpm) { - var array = [1, 2, 3], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), values = []; var actual = _(array).rest().filter(function(value) { @@ -13639,7 +13585,7 @@ .value(); deepEqual(actual, []); - deepEqual(values, [2, 3]); + deepEqual(values, array.slice(1)); values = []; @@ -13650,7 +13596,7 @@ .rest() .value(); - deepEqual(actual, [3]); + deepEqual(actual, array.slice(2)); deepEqual(values, array); } else { @@ -13660,16 +13606,16 @@ test('should not execute subsequent iteratees on an empty array in a lazy chain sequence', 4, function() { if (!isNpm) { - var array = [1], + var array = _.range(1, LARGE_ARRAY_SIZE + 1), iteratee = function() { pass = false }, pass = true, - actual = _(array).rest().map(iteratee).value(); + actual = _(array).slice(0, 1).rest().map(iteratee).value(); ok(pass); deepEqual(actual, []); pass = true; - actual = _(array).filter(_.identity).rest().map(iteratee).value(); + actual = _(array).filter().slice(0, 1).rest().map(iteratee).value(); ok(pass); deepEqual(actual, []); @@ -14284,32 +14230,34 @@ test('should work in a lazy chain sequence', 38, function() { if (!isNpm) { - var wrapped = _(array); + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + length = array.length, + wrapped = _(array); _.each(['map', 'filter'], function(methodName) { - deepEqual(wrapped[methodName]().slice(0, -1).value(), [1, 2]); - deepEqual(wrapped[methodName]().slice(1).value(), [2, 3]); - deepEqual(wrapped[methodName]().slice(1, 3).value(), [2, 3]); - deepEqual(wrapped[methodName]().slice(-1).value(), [3]); - - deepEqual(wrapped[methodName]().slice(4).value(), []); - deepEqual(wrapped[methodName]().slice(3, 2).value(), []); - deepEqual(wrapped[methodName]().slice(0, -4).value(), []); - deepEqual(wrapped[methodName]().slice(0, null).value(), []); - - deepEqual(wrapped[methodName]().slice(0, 4).value(), array); - deepEqual(wrapped[methodName]().slice(-4).value(), array); - deepEqual(wrapped[methodName]().slice(null).value(), array); - - deepEqual(wrapped[methodName]().slice(0, 1).value(), [1]); - deepEqual(wrapped[methodName]().slice(NaN, '1').value(), [1]); - - deepEqual(wrapped[methodName]().slice(0.1, 1.1).value(), [1]); - deepEqual(wrapped[methodName]().slice('0', 1).value(), [1]); - deepEqual(wrapped[methodName]().slice(0, '1').value(), [1]); - deepEqual(wrapped[methodName]().slice('1').value(), [2, 3]); - deepEqual(wrapped[methodName]().slice(NaN, 1).value(), [1]); - deepEqual(wrapped[methodName]().slice(1, NaN).value(), []); + deepEqual(wrapped[methodName]().slice(0, -1).value(), array.slice(0, -1)); + deepEqual(wrapped[methodName]().slice(1).value(), array.slice(1)); + deepEqual(wrapped[methodName]().slice(1, 3).value(), array.slice(1, 3)); + deepEqual(wrapped[methodName]().slice(-1).value(), array.slice(-1)); + + deepEqual(wrapped[methodName]().slice(length).value(), array.slice(length)); + deepEqual(wrapped[methodName]().slice(3, 2).value(), array.slice(3, 2)); + deepEqual(wrapped[methodName]().slice(0, -length).value(), array.slice(0, -length)); + deepEqual(wrapped[methodName]().slice(0, null).value(), array.slice(0, null)); + + deepEqual(wrapped[methodName]().slice(0, length).value(), array.slice(0, length)); + deepEqual(wrapped[methodName]().slice(-length).value(), array.slice(-length)); + deepEqual(wrapped[methodName]().slice(null).value(), array.slice(null)); + + deepEqual(wrapped[methodName]().slice(0, 1).value(), array.slice(0, 1)); + deepEqual(wrapped[methodName]().slice(NaN, '1').value(), array.slice(NaN, '1')); + + deepEqual(wrapped[methodName]().slice(0.1, 1.1).value(), array.slice(0.1, 1.1)); + deepEqual(wrapped[methodName]().slice('0', 1).value(), array.slice('0', 1)); + deepEqual(wrapped[methodName]().slice(0, '1').value(), array.slice(0, '1')); + deepEqual(wrapped[methodName]().slice('1').value(), array.slice('1')); + deepEqual(wrapped[methodName]().slice(NaN, 1).value(), array.slice(NaN, 1)); + deepEqual(wrapped[methodName]().slice(1, NaN).value(), array.slice(1, NaN)); }); } else { @@ -15972,11 +15920,17 @@ test('should work in a lazy chain sequence', 2, function() { if (!isNpm) { - var actual = _([1, 2]).map(String).toArray().value(); - deepEqual(actual, ['1', '2']); + var array = _.range(1, LARGE_ARRAY_SIZE + 1), + actual = _(array).map(String).toArray().value(); + + deepEqual(actual, _.map(array, String)); - actual = _({ 'a': 1, 'b': 2 }).toArray().map(String).value(); - deepEqual(actual, ['1', '2']); + var object = _.zipObject(_.times(LARGE_ARRAY_SIZE, function(index) { + return ['key' + index, index]; + })); + + actual = _(object).toArray().map(String).value(); + deepEqual(actual, _.map(_.toArray(object), String)); } else { skipTest(2); @@ -16709,14 +16663,12 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [ - { 'a': 1 }, - { 'a': 3 }, - { 'a': 1, 'b': 2 } - ]; + var array = _.times(LARGE_ARRAY_SIZE, function(index) { + return index ? { 'a': 1, 'b': index } : { 'a': 3 }; + }); var actual = _(array).where({ 'a': 1 }).value(); - deepEqual(actual, [array[0], array[2]]); + deepEqual(actual, _.where(array, { 'a': 1 })); } else { skipTest(); @@ -16888,13 +16840,14 @@ test('should work when in a lazy chain sequence before `first` or `last`', 1, function() { if (!isNpm) { - var wrapped = _([1, 2]).slice().xor([2, 3]); + var array = _.range(0, LARGE_ARRAY_SIZE), + wrapped = _(array).slice(1).xor([LARGE_ARRAY_SIZE - 1, LARGE_ARRAY_SIZE]); var actual = _.map(['first', 'last'], function(methodName) { return wrapped[methodName](); }); - deepEqual(actual, [1, 3]); + deepEqual(actual, [1, LARGE_ARRAY_SIZE]); } else { skipTest(); @@ -16952,11 +16905,14 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = [['a', 1], ['b', 2]], - predicate = function(value) { return value > 2; }, + var array = _.times(LARGE_ARRAY_SIZE, function(index) { + return ['key' + index, index]; + }); + + var predicate = function(value) { return value > 2; }, actual = _(array).zipObject().map(square).filter(predicate).take().value(); - deepEqual(actual, [4]); + deepEqual(actual, _.take(_.filter(_.map(_.zipObject(array), square), predicate))); } else { skipTest(); @@ -17310,8 +17266,10 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var actual = _([1, 2, 3, null]).map(_.identity).reverse().value(); - deepEqual(actual, [null, 3, 2, 1]); + var array = _.range(0, LARGE_ARRAY_SIZE).concat(null), + actual = _(array).slice(1).reverse().value(); + + deepEqual(actual, array.slice(1).reverse()); } else { skipTest(); @@ -17327,12 +17285,13 @@ }; try { - var wrapped = _(['a', spy]).map(String).reverse(), + var array = _.range(1, LARGE_ARRAY_SIZE).concat(spy), + wrapped = _(array).map(String).reverse(), actual = wrapped.last(); } catch(e) {} ok(wrapped instanceof _); - strictEqual(actual, 'a'); + strictEqual(actual, '1'); } else { skipTest(2); From ba082b74a77f121bfc8491fbcfd8cb516d79572c Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 6 Jun 2015 15:30:56 -0700 Subject: [PATCH 048/107] Adjust lazy heuristic to punt if not using shortcut fusion. --- lodash.src.js | 2 +- test/test.js | 100 +++++++++++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 0388eef9dd..2a3c28b070 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1179,7 +1179,7 @@ resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); - if (!isArr || array.length < LARGE_ARRAY_SIZE || (iterLength < 2 && arrLength == length && takeCount == length)) { + if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) { return baseWrapperValue(isRight ? array.reverse() : array, this.__actions__); } var result = []; diff --git a/test/test.js b/test/test.js index 666c257b0c..e42eaa1966 100644 --- a/test/test.js +++ b/test/test.js @@ -4911,34 +4911,34 @@ test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - array = _.range(1, LARGE_ARRAY_SIZE + 1), - expected = [square(LARGE_ARRAY_SIZE), LARGE_ARRAY_SIZE - 1, _.map(array, square)]; + array = _.range(0, LARGE_ARRAY_SIZE + 1), + expected = [square(LARGE_ARRAY_SIZE), LARGE_ARRAY_SIZE - 1, _.map(array.slice(1), square)]; - _(array).takeRightWhile(function(value, index, array) { + _(array).slice(1).takeRightWhile(function(value, index, array) { args = slice.call(arguments) }).value(); - deepEqual(args, [LARGE_ARRAY_SIZE, LARGE_ARRAY_SIZE - 1, array]); + deepEqual(args, [LARGE_ARRAY_SIZE, LARGE_ARRAY_SIZE - 1, array.slice(1)]); - _(array).map(square).takeRightWhile(function(value, index, array) { + _(array).slice(1).map(square).takeRightWhile(function(value, index, array) { args = slice.call(arguments) }).value(); deepEqual(args, expected); - _(array).map(square).takeRightWhile(function(value, index) { + _(array).slice(1).map(square).takeRightWhile(function(value, index) { args = slice.call(arguments) }).value(); deepEqual(args, expected); - _(array).map(square).takeRightWhile(function(index) { + _(array).slice(1).map(square).takeRightWhile(function(index) { args = slice.call(arguments); }).value(); deepEqual(args, [square(LARGE_ARRAY_SIZE)]); - _(array).map(square).takeRightWhile(function() { + _(array).slice(1).map(square).takeRightWhile(function() { args = slice.call(arguments); }).value(); @@ -5036,34 +5036,34 @@ test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - array = _.range(1, LARGE_ARRAY_SIZE + 1), - expected = [1, 0, _.map(array, square)]; + array = _.range(0, LARGE_ARRAY_SIZE + 1), + expected = [1, 0, _.map(array.slice(1), square)]; - _(array).takeWhile(function(value, index, array) { + _(array).slice(1).takeWhile(function(value, index, array) { args = slice.call(arguments); }).value(); - deepEqual(args, [1, 0, array]); + deepEqual(args, [1, 0, array.slice(1)]); - _(array).map(square).takeWhile(function(value, index, array) { + _(array).slice(1).map(square).takeWhile(function(value, index, array) { args = slice.call(arguments); }).value(); deepEqual(args, expected); - _(array).map(square).takeWhile(function(value, index) { + _(array).slice(1).map(square).takeWhile(function(value, index) { args = slice.call(arguments); }).value(); deepEqual(args, expected); - _(array).map(square).takeWhile(function(value) { + _(array).slice(1).map(square).takeWhile(function(value) { args = slice.call(arguments); }).value(); deepEqual(args, [1]); - _(array).map(square).takeWhile(function() { + _(array).slice(1).map(square).takeWhile(function() { args = slice.call(arguments); }).value(); @@ -9418,38 +9418,38 @@ test('should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - array = _.range(1, LARGE_ARRAY_SIZE + 1), - expected = [1, 0, _.map(array, square)]; + array = _.range(0, LARGE_ARRAY_SIZE), + expected = [1, 0, _.map(array.slice(1), square)]; - _(array).map(function(value, index, array) { + _(array).slice(1).map(function(value, index, array) { args || (args = slice.call(arguments)); }).value(); - deepEqual(args, [1, 0, array]); + deepEqual(args, [1, 0, array.slice(1)]); args = null; - _(array).map(square).map(function(value, index, array) { + _(array).slice(1).map(square).map(function(value, index, array) { args || (args = slice.call(arguments)); }).value(); deepEqual(args, expected); args = null; - _(array).map(square).map(function(value, index) { + _(array).slice(1).map(square).map(function(value, index) { args || (args = slice.call(arguments)); }).value(); deepEqual(args, expected); args = null; - _(array).map(square).map(function(value) { + _(array).slice(1).map(square).map(function(value) { args || (args = slice.call(arguments)); }).value(); deepEqual(args, [1]); args = null; - _(array).map(square).map(function() { + _(array).slice(1).map(square).map(function() { args || (args = slice.call(arguments)); }).value(); @@ -12273,15 +12273,15 @@ test('should work in a lazy chain sequence', 2, function() { if (!isNpm) { - var array = _.times(LARGE_ARRAY_SIZE, function(index) { + var array = _.times(LARGE_ARRAY_SIZE + 1, function(index) { return index ? { 'a': index } : null; }); - var actual = _(array).pluck('a').value(); - deepEqual(actual, _.pluck(array, 'a')); + var actual = _(array).slice(1).pluck('a').value(); + deepEqual(actual, _.pluck(array.slice(1), 'a')); - actual = _(array).filter().pluck('a').value(); - deepEqual(actual, _.pluck(_.filter(array), 'a')); + actual = _(array).slice(1).filter().pluck('a').value(); + deepEqual(actual, _.pluck(_.filter(array.slice(1)), 'a')); } else { skipTest(2); @@ -13184,11 +13184,11 @@ test('`_.' + methodName + '` should work in a lazy chain sequence', 2, function() { if (!isNpm) { - var array = _.range(1, LARGE_ARRAY_SIZE + 1), + var array = _.range(0, LARGE_ARRAY_SIZE + 1), predicate = function(value) { return isFilter ? (value > 6) : (value < 6); }, - actual = _(array).map(square)[methodName](predicate).value(); + actual = _(array).slice(1).map(square)[methodName](predicate).value(); - deepEqual(actual, _[methodName](_.map(array, square), predicate)); + deepEqual(actual, _[methodName](_.map(array.slice(1), square), predicate)); var object = _.zipObject(_.times(LARGE_ARRAY_SIZE, function(index) { return ['key' + index, index]; @@ -13205,38 +13205,38 @@ test('`_.' + methodName + '` should provide the correct `predicate` arguments in a lazy chain sequence', 5, function() { if (!isNpm) { var args, - array = _.range(1, LARGE_ARRAY_SIZE + 1), - expected = [1, 0, _.map(array, square)]; + array = _.range(0, LARGE_ARRAY_SIZE + 1), + expected = [1, 0, _.map(array.slice(1), square)]; - _(array)[methodName](function(value, index, array) { + _(array).slice(1)[methodName](function(value, index, array) { args || (args = slice.call(arguments)); }).value(); - deepEqual(args, [1, 0, array]); + deepEqual(args, [1, 0, array.slice(1)]); args = null; - _(array).map(square)[methodName](function(value, index, array) { + _(array).slice(1).map(square)[methodName](function(value, index, array) { args || (args = slice.call(arguments)); }).value(); deepEqual(args, expected); args = null; - _(array).map(square)[methodName](function(value, index) { + _(array).slice(1).map(square)[methodName](function(value, index) { args || (args = slice.call(arguments)); }).value(); deepEqual(args, expected); args = null; - _(array).map(square)[methodName](function(value) { + _(array).slice(1).map(square)[methodName](function(value) { args || (args = slice.call(arguments)); }).value(); deepEqual(args, [1]); args = null; - _(array).map(square)[methodName](function() { + _(array).slice(1).map(square)[methodName](function() { args || (args = slice.call(arguments)); }).value(); @@ -15920,17 +15920,17 @@ test('should work in a lazy chain sequence', 2, function() { if (!isNpm) { - var array = _.range(1, LARGE_ARRAY_SIZE + 1), - actual = _(array).map(String).toArray().value(); + var array = _.range(0, LARGE_ARRAY_SIZE + 1), + actual = _(array).slice(1).map(String).toArray().value(); - deepEqual(actual, _.map(array, String)); + deepEqual(actual, _.map(array.slice(1), String)); var object = _.zipObject(_.times(LARGE_ARRAY_SIZE, function(index) { return ['key' + index, index]; })); - actual = _(object).toArray().map(String).value(); - deepEqual(actual, _.map(_.toArray(object), String)); + actual = _(object).toArray().slice(1).map(String).value(); + deepEqual(actual, _.map(_.toArray(object).slice(1), String)); } else { skipTest(2); @@ -16663,12 +16663,12 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { - var array = _.times(LARGE_ARRAY_SIZE, function(index) { + var array = _.times(LARGE_ARRAY_SIZE + 1, function(index) { return index ? { 'a': 1, 'b': index } : { 'a': 3 }; }); - var actual = _(array).where({ 'a': 1 }).value(); - deepEqual(actual, _.where(array, { 'a': 1 })); + var actual = _(array).slice(1).where({ 'a': 1 }).value(); + deepEqual(actual, _.where(array.slice(1), { 'a': 1 })); } else { skipTest(); @@ -17285,8 +17285,8 @@ }; try { - var array = _.range(1, LARGE_ARRAY_SIZE).concat(spy), - wrapped = _(array).map(String).reverse(), + var array = _.range(0, LARGE_ARRAY_SIZE).concat(spy), + wrapped = _(array).slice(1).map(String).reverse(), actual = wrapped.last(); } catch(e) {} From f8ec95d87252243fa459a240503d23077277176f Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 13:16:51 -0700 Subject: [PATCH 049/107] Switch `null` use for clearing vars to `undefined`. --- lodash.src.js | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 2a3c28b070..1bfdb52e67 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1857,7 +1857,7 @@ if (isObject(prototype)) { object.prototype = prototype; var result = new object; - object.prototype = null; + object.prototype = undefined; } return result || {}; }; @@ -1899,7 +1899,7 @@ var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, - cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, + cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : undefined, valuesLength = values.length; if (cache) { @@ -2462,7 +2462,7 @@ return object; } var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), - props = isSrcArr ? null : keys(source); + props = isSrcArr ? undefined : keys(source); arrayEach(props || source, function(srcValue, key) { if (props) { @@ -2775,7 +2775,7 @@ length = array.length, isCommon = indexOf == baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, - seen = isLarge ? createCache() : null, + seen = isLarge ? createCache() : undefined, result = []; if (seen) { @@ -3288,9 +3288,9 @@ function createCurry(flag) { function curryFunc(func, arity, guard) { if (guard && isIterateeCall(func, arity, guard)) { - arity = null; + arity = undefined; } - var result = createWrapper(func, flag, null, null, null, null, null, arity); + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curryFunc.placeholder; return result; } @@ -3308,7 +3308,7 @@ function createExtremum(comparator, exValue) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } iteratee = getCallback(iteratee, thisArg, 3); if (iteratee.length == 1) { @@ -3401,7 +3401,7 @@ func = funcs[index]; var funcName = getFuncName(func), - data = funcName == 'wrapper' ? getData(func) : null; + data = funcName == 'wrapper' ? getData(func) : undefined; if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); @@ -3521,7 +3521,7 @@ function createPartial(flag) { var partialFunc = restParam(function(func, partials) { var holders = replaceHolders(partials, partialFunc.placeholder); - return createWrapper(func, flag, null, partials, holders); + return createWrapper(func, flag, undefined, partials, holders); }); return partialFunc; } @@ -3567,7 +3567,7 @@ isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, - Ctor = isBindKey ? null : createCtorWrapper(func); + Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by @@ -3591,12 +3591,12 @@ length -= argsHolders.length; if (length < arity) { - var newArgPos = argPos ? arrayCopy(argPos) : null, + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), - newsHolders = isCurry ? argsHolders : null, - newHoldersRight = isCurry ? null : argsHolders, - newPartials = isCurry ? args : null, - newPartialsRight = isCurry ? null : args; + newsHolders = isCurry ? argsHolders : undefined, + newHoldersRight = isCurry ? undefined : argsHolders, + newPartials = isCurry ? args : undefined, + newPartialsRight = isCurry ? undefined : args; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); @@ -3739,16 +3739,16 @@ var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); - partials = holders = null; + partials = holders = undefined; } length -= (holders ? holders.length : 0); if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; - partials = holders = null; + partials = holders = undefined; } - var data = isBindKey ? null : getData(func), + var data = isBindKey ? undefined : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; if (data) { @@ -5093,7 +5093,7 @@ while (othIndex--) { var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; - caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null; + caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : undefined; } var array = arrays[0], index = -1, @@ -5698,7 +5698,7 @@ } if (isSorted != null && typeof isSorted != 'boolean') { thisArg = iteratee; - iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; isSorted = false; } var callback = getCallback(); @@ -6332,7 +6332,7 @@ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); @@ -6731,7 +6731,7 @@ result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); + var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; @@ -7131,7 +7131,7 @@ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); @@ -7192,7 +7192,7 @@ return []; } if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } var index = -1; iteratee = getCallback(iteratee, thisArg, 3); @@ -7288,7 +7288,7 @@ return []; } if (guard && isIterateeCall(iteratees, orders, guard)) { - orders = null; + orders = undefined; } if (!isArray(iteratees)) { iteratees = iteratees == null ? [] : [iteratees]; @@ -7413,10 +7413,10 @@ */ function ary(func, n, guard) { if (guard && isIterateeCall(func, n, guard)) { - n = null; + n = undefined; } n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); - return createWrapper(func, ARY_FLAG, null, null, null, null, n); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); } /** @@ -7451,7 +7451,7 @@ result = func.apply(this, arguments); } if (n <= 1) { - func = null; + func = undefined; } return result; }; @@ -7786,7 +7786,7 @@ lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; + args = thisArg = undefined; } } } else { @@ -7803,7 +7803,7 @@ lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; + args = thisArg = undefined; } } } @@ -7845,7 +7845,7 @@ result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = null; + args = thisArg = undefined; } return result; } @@ -8199,7 +8199,7 @@ * // => [3, 6, 9] */ var rearg = restParam(function(func, indexes) { - return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes)); + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); }); /** @@ -8371,7 +8371,7 @@ */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; - return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []); } /*------------------------------------------------------------------------*/ @@ -9296,7 +9296,7 @@ function create(prototype, properties, guard) { var result = baseCreate(prototype); if (guard && isIterateeCall(prototype, properties, guard)) { - properties = null; + properties = undefined; } return properties ? baseAssign(result, properties) : result; } @@ -9653,7 +9653,7 @@ */ function invert(object, multiValue, guard) { if (guard && isIterateeCall(object, multiValue, guard)) { - multiValue = null; + multiValue = undefined; } var index = -1, props = keys(object), @@ -9706,7 +9706,7 @@ * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object == null ? null : object.constructor; + var Ctor = object == null ? undefined : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object == 'function' ? lodash.support.enumPrototypes : isArrayLike(object))) { return shimKeys(object); @@ -10138,7 +10138,7 @@ if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : null); + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); } } else { accumulator = {}; @@ -10279,7 +10279,7 @@ */ function random(min, max, floating) { if (floating && isIterateeCall(min, max, floating)) { - max = floating = null; + max = floating = undefined; } var noMin = min == null, noMax = max == null; @@ -10833,7 +10833,7 @@ var settings = lodash.templateSettings; if (otherOptions && isIterateeCall(string, options, otherOptions)) { - options = otherOptions = null; + options = otherOptions = undefined; } string = baseToString(string); options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); @@ -11069,7 +11069,7 @@ */ function trunc(string, options, guard) { if (guard && isIterateeCall(string, options, guard)) { - options = null; + options = undefined; } var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; @@ -11164,7 +11164,7 @@ */ function words(string, pattern, guard) { if (guard && isIterateeCall(string, pattern, guard)) { - pattern = null; + pattern = undefined; } string = baseToString(string); return string.match(pattern || reWords) || []; @@ -11240,7 +11240,7 @@ */ function callback(func, thisArg, guard) { if (guard && isIterateeCall(func, thisArg, guard)) { - thisArg = null; + thisArg = undefined; } return isObjectLike(func) ? matches(func) @@ -11441,8 +11441,8 @@ function mixin(object, source, options) { if (options == null) { var isObj = isObject(source), - props = isObj ? keys(source) : null, - methodNames = (props && props.length) ? baseFunctions(source, props) : null; + props = isObj ? keys(source) : undefined, + methodNames = (props && props.length) ? baseFunctions(source, props) : undefined; if (!(methodNames ? methodNames.length : isObj)) { methodNames = false; @@ -11611,7 +11611,7 @@ */ function range(start, end, step) { if (step && isIterateeCall(start, end, step)) { - end = step = null; + end = step = undefined; } start = +start || 0; step = step == null ? 1 : (+step || 0); @@ -11857,7 +11857,7 @@ */ function sum(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } var callback = getCallback(), noIteratee = iteratee == null; @@ -12348,7 +12348,7 @@ } }); - realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': null }]; + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }]; // Add functions to the lazy wrapper. LazyWrapper.prototype.clone = lazyClone; From 746034a4fc54f39d2664400e4d1c8c34d19bd2cc Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 13:51:06 -0700 Subject: [PATCH 050/107] Simplified `bufferClone`. --- lodash.src.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 1bfdb52e67..0fb6bc29fc 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -748,7 +748,7 @@ ); /** Native method references. */ - var ArrayBuffer = getNative(context, 'ArrayBuffer'), + var ArrayBuffer = context.ArrayBuffer, ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, @@ -757,7 +757,7 @@ Set = getNative(context, 'Set'), setTimeout = context.setTimeout, splice = arrayProto.splice, - Uint8Array = getNative(context, 'Uint8Array'), + Uint8Array = context.Uint8Array, WeakMap = getNative(context, 'WeakMap'); /* Native method references for those with the same name as other `lodash` methods. */ @@ -799,7 +799,7 @@ ctorByTag[int8Tag] = context.Int8Array; ctorByTag[int16Tag] = context.Int16Array; ctorByTag[int32Tag] = context.Int32Array; - ctorByTag[uint8Tag] = context.Uint8Array; + ctorByTag[uint8Tag] = Uint8Array; ctorByTag[uint8ClampedTag] = context.Uint8ClampedArray; ctorByTag[uint16Tag] = context.Uint16Array; ctorByTag[uint32Tag] = context.Uint32Array; @@ -3001,13 +3001,13 @@ * @param {ArrayBuffer} buffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ - var bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { + function bufferClone(buffer) { var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); view.set(new Uint8Array(buffer)); return result; - }; + } /** * Creates an array that is the composition of partially applied arguments, From 7db606857dc4397c674b32dd33173722393ffa33 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 14:33:28 -0700 Subject: [PATCH 051/107] Adjust tabs to two spaces for html files. --- perf/index.html | 150 ++++++------ test/backbone.html | 246 +++++++++---------- test/index.html | 572 +++++++++++++++++++++---------------------- test/underscore.html | 466 +++++++++++++++++------------------ 4 files changed, 717 insertions(+), 717 deletions(-) diff --git a/perf/index.html b/perf/index.html index be070ef105..b5cd14fbef 100644 --- a/perf/index.html +++ b/perf/index.html @@ -1,82 +1,82 @@ - - - lodash Performance Suite - - - -
- - - - - - - - - - + + + + + + + + + - + // is the applet permitted? + if (!/[?&]nojava=true(?:&|$)/.test(location.search)) { + // is the applet really needed? + while (!(measured = new Date - begin)) {} + if (measured > 1 && !((perfNow = window.performance) && typeof (perfNow.now || perfNow.webkitNow) == 'function')) { + // load applet + document.write(''); + } + } + window.onload = init; + }()); + + diff --git a/test/backbone.html b/test/backbone.html index ff0179e52c..b01da499e1 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -1,133 +1,133 @@ - - - Backbone Test Suite - - - - - - - - - - - + + + + + + + - + - + if (ui.isModularize) { + window._ = lodash; + } + require(getConfig(), [ + 'test/setup/dom-setup', + 'test/setup/environment', + 'test/noconflict', + 'test/events', + 'test/model', + 'test/collection', + 'test/router', + 'test/view', + 'test/sync' + ], function() { + QUnit.start(); + }); + }); + }()); + + diff --git a/test/index.html b/test/index.html index 7d52d3249c..05ec942915 100644 --- a/test/index.html +++ b/test/index.html @@ -1,319 +1,319 @@ - - - lodash Test Suite - - - - - - - - - - - -
-
- + + + + + + +
+
+ - - + + - + // Set a more readable browser name. + window.onload = function() { + var timeoutId = setInterval(function() { + var ua = document.getElementById('qunit-userAgent'); + if (ua) { + ua.innerHTML = platform; + clearInterval(timeoutId); + } + }, 16); + }; + + diff --git a/test/underscore.html b/test/underscore.html index 07f599a2c7..53839884aa 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -1,242 +1,242 @@ - - - Underscore Test Suite - - - -
- - - - - - - + + + + + + - + - + require(getConfig(), [moduleId], function(lodash) { + if (ui.isModularize) { + window._ = lodash; + } + require(getConfig(), [ + 'test/collections', + 'test/arrays', + 'test/functions', + 'test/objects', + 'test/cross-document', + 'test/utility', + 'test/chaining' + ], function() { + QUnit.start(); + }); + }); + }()); + + From 288b6ea692fba2d9cc16b18abdadb1d9a207af48 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 15:24:53 -0700 Subject: [PATCH 052/107] Remove unnecessary `lodash` binding. --- lodash.src.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 0fb6bc29fc..befdfbfa27 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -6168,7 +6168,7 @@ wrapped = new LazyWrapper(this); } wrapped = wrapped.reverse(); - wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); return new LodashWrapper(wrapped, this.__chain__); } return this.thru(interceptor); @@ -12281,27 +12281,30 @@ iteratee = args[0], useLazy = isLazy || isArray(value); - var interceptor = function(value) { - return lodashFunc.apply(lodash, arrayPush([value], args)); - }; if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { // Avoid lazy use if the iteratee has a "length" value other than `1`. isLazy = useLazy = false; } - var onlyLazy = isLazy && !isHybrid; + var interceptor = function(value) { + return lodashFunc.apply(undefined, arrayPush([value], args)); + }; + + var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined }, + onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { if (onlyLazy) { value = value.clone(); - value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + value.__actions__.push(action); return func.call(value); } - return lodashFunc.call(lodash, this.value())[0]; + return lodashFunc.call(undefined, this.value())[0]; } if (useLazy) { value = onlyLazy ? value : new LazyWrapper(this); var result = func.apply(value, args); if (!retUnwrapped) { - result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + result.__actions__.push(action); } return new LodashWrapper(result, chainAll); } From 595eab26149b4781f54c38b4fc3adde12d8730bc Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 16:48:48 -0700 Subject: [PATCH 053/107] Rename license file to align with GitHub defaults. [ci skip] --- LICENSE.txt => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSE.txt => LICENSE (100%) diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE From df838c98e9e7d76d70691ebfdeeb7f6ff2268bd5 Mon Sep 17 00:00:00 2001 From: James Kyle Date: Sun, 7 Jun 2015 18:41:36 -0700 Subject: [PATCH 054/107] Add _.ceil/_.floor/_.round. --- lodash.src.js | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.js | 30 +++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index befdfbfa27..80c556e071 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3706,6 +3706,25 @@ }; } + /** + * Creates a `_.round`, `_.ceil`, or `_.floor` function. + * + * @private + * @param {String} type Specify the Math method to use when rounding. + */ + + function createRound(type) { + var roundFn = Math[type]; + return function(number, precision) { + if (precision) { + precision = Math.pow(10, precision); + return roundFn(number * precision) / precision; + } else { + return roundFn(number); + } + } + } + /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. @@ -11871,6 +11890,72 @@ : baseSum(collection, iteratee); } + /** + * Calculates the result of a number rounded to an optional precision. + * + * @static + * @memberOf _ + * @category Math + * @param {number} number The number to round. + * @param {number} [precision] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + + /** + * Calculates the result of a number rounded down to an optional precision. + * + * @static + * @memberOf _ + * @category Math + * @param {number} number The number to round down. + * @param {number} [precision] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + + /** + * Calculates the result of a number rounded up to an optional precision. + * + * @static + * @memberOf _ + * @category Math + * @param {number} number The number to round up. + * @param {number} [precision] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + /*------------------------------------------------------------------------*/ // Ensure wrappers are instances of `baseLodash`. @@ -12028,6 +12113,7 @@ lodash.attempt = attempt; lodash.camelCase = camelCase; lodash.capitalize = capitalize; + lodash.ceil = ceil; lodash.clone = clone; lodash.cloneDeep = cloneDeep; lodash.deburr = deburr; @@ -12043,6 +12129,7 @@ lodash.findLastKey = findLastKey; lodash.findWhere = findWhere; lodash.first = first; + lodash.floor = floor; lodash.get = get; lodash.gt = gt; lodash.gte = gte; @@ -12091,6 +12178,7 @@ lodash.reduceRight = reduceRight; lodash.repeat = repeat; lodash.result = result; + lodash.round = round; lodash.runInContext = runInContext; lodash.size = size; lodash.snakeCase = snakeCase; diff --git a/test/test.js b/test/test.js index e42eaa1966..869a0ce9d6 100644 --- a/test/test.js +++ b/test/test.js @@ -13686,6 +13686,34 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.round, lodash.floor, and lodash.ceil'); + + _.each(['round', 'floor', 'ceil'], function(methodName) { + var func = _[methodName]; + + test('`_.' + methodName + '` should return a rounded number without a precision', 1, function() { + var actual = func(4.006); + equal(actual, methodName === 'ceil' ? 5 : 4); + }); + + test('`_.' + methodName + '` should return a rounded number with a precision of 0', 1, function() { + var actual = func(4.006, 0); + equal(actual, methodName === 'ceil' ? 5 : 4); + }); + + test('`_.' + methodName + '` should return a rounded number with a positive precision', 1, function() { + var actual = func(4.016, 2); + equal(actual, methodName === 'floor' ? 4.01 : 4.02); + }); + + test('`_.' + methodName + '` should return a rounded number with a negative precision', 1, function() { + var actual = func(4160, -2); + equal(actual, methodName === 'floor' ? 4100 : 4200); + }); + }); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.runInContext'); (function() { @@ -17863,7 +17891,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 225, function() { + test('should accept falsey arguments', 228, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From c8b818f011257b09f98d12fabde92ba5a77a43d3 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 21:27:00 -0700 Subject: [PATCH 055/107] Cleanup `_.ceil`, `_.floor`, & `_.round`. --- lodash.src.js | 201 +++++++++++++++++++++++++------------------------- test/test.js | 18 +++-- 2 files changed, 111 insertions(+), 108 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 80c556e071..559281f28c 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -749,10 +749,9 @@ /** Native method references. */ var ArrayBuffer = context.ArrayBuffer, - ceil = Math.ceil, clearTimeout = context.clearTimeout, - floor = Math.floor, parseFloat = context.parseFloat, + pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, 'Set'), setTimeout = context.setTimeout, @@ -761,7 +760,9 @@ WeakMap = getNative(context, 'WeakMap'); /* Native method references for those with the same name as other `lodash` methods. */ - var nativeCreate = getNative(Object, 'create'), + var nativeCeil = Math.ceil, + nativeCreate = getNative(Object, 'create'), + nativeFloor = Math.floor, nativeIsArray = getNative(Array, 'isArray'), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, 'keys'), @@ -2608,7 +2609,7 @@ * @returns {number} Returns the random number. */ function baseRandom(min, max) { - return min + floor(nativeRandom() * (max - min + 1)); + return min + nativeFloor(nativeRandom() * (max - min + 1)); } /** @@ -2933,7 +2934,7 @@ valIsUndef = value === undefined; while (low < high) { - var mid = floor((low + high) / 2), + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; @@ -3650,7 +3651,7 @@ } var padLength = length - strLength; chars = chars == null ? ' ' : (chars + ''); - return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); } /** @@ -3690,6 +3691,25 @@ return wrapper; } + /** + * Creates a `_.ceil`, `_.floor`, or `_.round` function. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : (+precision || 0); + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + /** * Creates a `_.sortedIndex` or `_.sortedLastIndex` function. * @@ -3706,25 +3726,6 @@ }; } - /** - * Creates a `_.round`, `_.ceil`, or `_.floor` function. - * - * @private - * @param {String} type Specify the Math method to use when rounding. - */ - - function createRound(type) { - var roundFn = Math[type]; - return function(number, precision) { - if (precision) { - precision = Math.pow(10, precision); - return roundFn(number * precision) / precision; - } else { - return roundFn(number); - } - } - } - /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. @@ -4572,12 +4573,12 @@ if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { - size = nativeMax(floor(size) || 1, 1); + size = nativeMax(nativeFloor(size) || 1, 1); } var index = 0, length = array ? array.length : 0, resIndex = -1, - result = Array(ceil(length / size)); + result = Array(nativeCeil(length / size)); while (index < length) { result[++resIndex] = baseSlice(array, index, (index += size)); @@ -10260,7 +10261,7 @@ */ function inRange(value, start, end) { start = +start || 0; - if (typeof end === 'undefined') { + if (end === undefined) { end = start; start = 0; } else { @@ -10543,8 +10544,8 @@ return string; } var mid = (length - strLength) / 2, - leftLength = floor(mid), - rightLength = ceil(mid); + leftLength = nativeFloor(mid), + rightLength = nativeCeil(mid); chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; @@ -10667,7 +10668,7 @@ if (n % 2) { result += string; } - n = floor(n / 2); + n = nativeFloor(n / 2); string += string; } while (n); @@ -11644,7 +11645,7 @@ // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. var index = -1, - length = nativeMax(ceil((end - start) / (step || 1)), 0), + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (++index < length) { @@ -11682,7 +11683,7 @@ * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { - n = floor(n); + n = nativeFloor(n); // Exit early to avoid a JSC JIT bug in Safari 8 // where `Array(0)` is treated as `Array(1)`. @@ -11744,6 +11745,50 @@ return (+augend || 0) + (+addend || 0); } + /** + * Calculates `n` rounded up to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + + /** + * Calculates `n` rounded down to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + /** * Gets the maximum value of `collection`. If `collection` is empty or falsey * `-Infinity` is returned. If an iteratee function is provided it is invoked @@ -11842,6 +11887,28 @@ */ var min = createExtremum(lt, POSITIVE_INFINITY); + /** + * Calculates `n` rounded to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round. + * @param {number} [precision=0] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + /** * Gets the sum of the values in `collection`. * @@ -11890,72 +11957,6 @@ : baseSum(collection, iteratee); } - /** - * Calculates the result of a number rounded to an optional precision. - * - * @static - * @memberOf _ - * @category Math - * @param {number} number The number to round. - * @param {number} [precision] The precision to round to. - * @returns {number} Returns the rounded number. - * @example - * - * _.round(4.006); - * // => 4 - * - * _.round(4.006, 2); - * // => 4.01 - * - * _.round(4060, -2); - * // => 4100 - */ - var round = createRound('round'); - - /** - * Calculates the result of a number rounded down to an optional precision. - * - * @static - * @memberOf _ - * @category Math - * @param {number} number The number to round down. - * @param {number} [precision] The precision to round down to. - * @returns {number} Returns the rounded down number. - * @example - * - * _.floor(4.006); - * // => 4 - * - * _.floor(0.046, 2); - * // => 0.04 - * - * _.floor(4060, -2); - * // => 4000 - */ - var floor = createRound('floor'); - - /** - * Calculates the result of a number rounded up to an optional precision. - * - * @static - * @memberOf _ - * @category Math - * @param {number} number The number to round up. - * @param {number} [precision] The precision to round up to. - * @returns {number} Returns the rounded up number. - * @example - * - * _.ceil(4.006); - * // => 5 - * - * _.ceil(6.004, 2); - * // => 6.01 - * - * _.ceil(6040, -2); - * // => 6100 - */ - var ceil = createRound('ceil'); - /*------------------------------------------------------------------------*/ // Ensure wrappers are instances of `baseLodash`. @@ -12256,7 +12257,7 @@ if (filtered && !index) { return new LazyWrapper(this); } - n = n == null ? 1 : nativeMax(floor(n) || 0, 0); + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); var result = this.clone(); if (filtered) { diff --git a/test/test.js b/test/test.js index 869a0ce9d6..eb59453cbe 100644 --- a/test/test.js +++ b/test/test.js @@ -13686,29 +13686,31 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.round, lodash.floor, and lodash.ceil'); + QUnit.module('round methods'); - _.each(['round', 'floor', 'ceil'], function(methodName) { - var func = _[methodName]; + _.each(['ceil', 'floor', 'round'], function(methodName) { + var func = _[methodName], + isCeil = methodName == 'ceil', + isFloor = methodName == 'floor'; test('`_.' + methodName + '` should return a rounded number without a precision', 1, function() { var actual = func(4.006); - equal(actual, methodName === 'ceil' ? 5 : 4); + strictEqual(actual, isCeil ? 5 : 4); }); - test('`_.' + methodName + '` should return a rounded number with a precision of 0', 1, function() { + test('`_.' + methodName + '` should return a rounded number with a precision of `0`', 1, function() { var actual = func(4.006, 0); - equal(actual, methodName === 'ceil' ? 5 : 4); + strictEqual(actual, isCeil ? 5 : 4); }); test('`_.' + methodName + '` should return a rounded number with a positive precision', 1, function() { var actual = func(4.016, 2); - equal(actual, methodName === 'floor' ? 4.01 : 4.02); + strictEqual(actual, isFloor ? 4.01 : 4.02); }); test('`_.' + methodName + '` should return a rounded number with a negative precision', 1, function() { var actual = func(4160, -2); - equal(actual, methodName === 'floor' ? 4100 : 4200); + strictEqual(actual, isFloor ? 4100 : 4200); }); }); From 22743e06d5b330b1c035edff14c8ca82d6d37dab Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 8 Jun 2015 08:27:52 -0700 Subject: [PATCH 056/107] Add round test for `NaN` precision params. --- test/test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test.js b/test/test.js index eb59453cbe..3109cbbce4 100644 --- a/test/test.js +++ b/test/test.js @@ -13703,6 +13703,14 @@ strictEqual(actual, isCeil ? 5 : 4); }); + test('`_.' + methodName + '` should coerce `precision` values to numbers and `NaN` to `0`', 2, function() { + var actual = func(4.006, NaN); + strictEqual(actual, isCeil ? 5 : 4); + + actual = func(4.016, '+2'); + strictEqual(actual, isFloor ? 4.01 : 4.02); + }); + test('`_.' + methodName + '` should return a rounded number with a positive precision', 1, function() { var actual = func(4.016, 2); strictEqual(actual, isFloor ? 4.01 : 4.02); From 058196e42a1dd9864982b81ab337245561bcbdb9 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 10 Jun 2015 07:22:36 -0700 Subject: [PATCH 057/107] Rename vendor/benchmark.js license. [ci skip] --- vendor/benchmark.js/{LICENSE.txt => LICENSE} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vendor/benchmark.js/{LICENSE.txt => LICENSE} (100%) diff --git a/vendor/benchmark.js/LICENSE.txt b/vendor/benchmark.js/LICENSE similarity index 100% rename from vendor/benchmark.js/LICENSE.txt rename to vendor/benchmark.js/LICENSE From 9b54891474803d506cc8cbb331b014c7e0e62fd3 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 10 Jun 2015 07:57:39 -0700 Subject: [PATCH 058/107] Add `ceil`, `floor`, and `round` to `lodash` doc block. [ci skip] --- lodash.src.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 559281f28c..184c437335 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -874,19 +874,20 @@ * `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`, - * `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, - * `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, - * `isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, - * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, - * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`, - * `max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`, - * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, - * `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, - * `sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`, - * `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words` + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, + * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, + * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, + * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, + * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, + * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, + * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, + * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, + * `unescape`, `uniqueId`, `value`, and `words` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. From 9121b140098f7867ce8bab620beb22434433c717 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 10 Jun 2015 08:17:39 -0700 Subject: [PATCH 059/107] Cleanup `_.mixin` test. --- test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 3109cbbce4..a281cc43ae 100644 --- a/test/test.js +++ b/test/test.js @@ -11171,11 +11171,11 @@ delete Wrapper.prototype.b; }); - test('should not assign inherited `source` properties', 1, function() { + test('should not assign inherited `source` methods', 1, function() { function Foo() {} Foo.prototype.a = _.noop; - deepEqual(_.mixin({}, new Foo, {}), {}); + deepEqual(_.mixin({}, new Foo), {}); }); test('should accept an `options` argument', 16, function() { From 6b8ffb2a85e5216aa59caf2715859924c62a2e2e Mon Sep 17 00:00:00 2001 From: Kevin Kirsche Date: Wed, 10 Jun 2015 18:32:48 -0400 Subject: [PATCH 060/107] Remove moot `version` property from bower.json Per bower/bower.json-spec@a325da3 --- bower.json | 1 - 1 file changed, 1 deletion(-) diff --git a/bower.json b/bower.json index 8804a04198..23c390577d 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,5 @@ { "name": "lodash", - "version": "3.9.3", "main": "lodash.js", "ignore": [ ".*", From 1a28ef32442a26f3d5c301f38e12aa753ef213f5 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 10 Jun 2015 18:37:09 -0700 Subject: [PATCH 061/107] Ensure `_.includes` matches an empty string on empty strings. [closes #1275] --- lodash.src.js | 7 ++----- test/test.js | 6 ++++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 184c437335..1167f0748d 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -6660,17 +6660,14 @@ collection = values(collection); length = collection.length; } - if (!length) { - return false; - } if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { fromIndex = 0; } else { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) - ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) - : (getIndexOf(collection, target, fromIndex) > -1); + ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) + : (!!length && getIndexOf(collection, target, fromIndex) > -1); } /** diff --git a/test/test.js b/test/test.js index a281cc43ae..27d7d56c69 100644 --- a/test/test.js +++ b/test/test.js @@ -6244,7 +6244,9 @@ 'a string': '1234' }, function(collection, key) { - var values = _.toArray(collection); + var isStr = typeof collection == 'string', + values = _.toArray(collection), + length = values.length; test('should work with ' + key + ' and return `true` for matched values', 1, function() { strictEqual(_.includes(collection, 3), true); @@ -6263,7 +6265,7 @@ _.each([4, 6, Math.pow(2, 32), Infinity], function(fromIndex) { strictEqual(_.includes(collection, 1, fromIndex), false); strictEqual(_.includes(collection, undefined, fromIndex), false); - strictEqual(_.includes(collection, '', fromIndex), false); + strictEqual(_.includes(collection, '', fromIndex), (isStr && fromIndex == length)); }); }); From 419fb082669e6bfde90c81177ecc29c55e7e4231 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 11 Jun 2015 07:31:36 -0700 Subject: [PATCH 062/107] Simplify `createCache`. --- lodash.src.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 1167f0748d..2011db9da1 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1901,7 +1901,7 @@ var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, - cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : undefined, + cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, valuesLength = values.length; if (cache) { @@ -2777,7 +2777,7 @@ length = array.length, isCommon = indexOf == baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, - seen = isLarge ? createCache() : undefined, + seen = isLarge ? createCache() : null, result = []; if (seen) { @@ -3223,9 +3223,9 @@ * @param {Array} [values] The values to cache. * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. */ - var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { - return new SetCache(values); - }; + function createCache(values) { + return (nativeCreate && Set) ? new SetCache(values) : null; + } /** * Creates a function that produces compound words out of the words in a @@ -5114,7 +5114,7 @@ while (othIndex--) { var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; - caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : undefined; + caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null; } var array = arrays[0], index = -1, From 028ecf556114fb3c6ab1c625f346a748a1f0c60f Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 11 Jun 2015 08:30:18 -0700 Subject: [PATCH 063/107] Allow `_.modArgs` to accept an array of transforms. --- lodash.src.js | 4 +++- test/test.js | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 2011db9da1..313aa52dc1 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -8036,7 +8036,8 @@ * @memberOf _ * @category Function * @param {Function} func The function to wrap. - * @param {...Function} [transforms] The function to transform the corresponding argument. + * @param {...(Function|Function[])} [transforms] The functions to transform + * arguments, specified as individual functions or arrays of functions. * @returns {Function} Returns the new function. * @example * @@ -8059,6 +8060,7 @@ * // => [25, 20] */ var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) { throw new TypeError(FUNC_ERROR_TEXT); } diff --git a/test/test.js b/test/test.js index 27d7d56c69..83d23bb827 100644 --- a/test/test.js +++ b/test/test.js @@ -11306,6 +11306,11 @@ deepEqual(modded(5, 10), [10, 100]); }); + test('should flatten transforms', 1, function() { + var modded = _.modArgs(fn, [doubled, square]); + deepEqual(modded(5, 10), [10, 100]); + }); + test('should not transform any argument greater than the number of transforms', 1, function() { var modded = _.modArgs(fn, doubled, square); deepEqual(modded(5, 10, 18), [10, 100, 18]); From 51c9f4f9888b83252a5c01a25623417d87e2e486 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 11 Jun 2015 08:33:11 -0700 Subject: [PATCH 064/107] Cleanup `_.omit`, `_.modArgs`, & `_.pick` tests. --- test/test.js | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/test/test.js b/test/test.js index 83d23bb827..77dc7559bd 100644 --- a/test/test.js +++ b/test/test.js @@ -11306,9 +11306,9 @@ deepEqual(modded(5, 10), [10, 100]); }); - test('should flatten transforms', 1, function() { - var modded = _.modArgs(fn, [doubled, square]); - deepEqual(modded(5, 10), [10, 100]); + test('should flatten `transforms`', 1, function() { + var modded = _.modArgs(fn, [doubled, square], String); + deepEqual(modded(5, 10, 15), [10, 100, '15']); }); test('should not transform any argument greater than the number of transforms', 1, function() { @@ -11417,20 +11417,16 @@ (function() { var args = arguments, - object = { 'a': 1, 'b': 2, 'c': 3 }, - expected = { 'b': 2 }; + object = { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, + expected = { 'b': 2, 'd': 4 }; test('should create an object with omitted properties', 2, function() { - deepEqual(_.omit(object, 'a'), { 'b': 2, 'c': 3 }); + deepEqual(_.omit(object, 'a'), { 'b': 2, 'c': 3, 'd': 4 }); deepEqual(_.omit(object, 'a', 'c'), expected); }); - test('should support picking an array of properties', 1, function() { - deepEqual(_.omit(object, ['a', 'c']), expected); - }); - - test('should support picking an array of properties and individual properties', 1, function() { - deepEqual(_.omit(object, ['a'], 'c'), expected); + test('should flatten `props`', 1, function() { + deepEqual(_.omit(object, ['a', 'd'], 'c'), { 'b': 2 }); }); test('should iterate over inherited properties', 1, function() { @@ -11466,15 +11462,15 @@ delete stringProto.b; }); - test('should work with a `predicate` argument', 1, function() { + test('should work with a predicate argument', 1, function() { var actual = _.omit(object, function(num) { - return num != 2; + return num != 2 && num != 4; }); deepEqual(actual, expected); }); - test('should provide the correct `predicate` arguments', 1, function() { + test('should provide the correct predicate arguments', 1, function() { var args, object = { 'a': 1, 'b': 2 }, lastKey = _.keys(object).pop(); @@ -11492,8 +11488,8 @@ test('should set the `this` binding', 1, function() { var actual = _.omit(object, function(num) { - return num != this.b; - }, { 'b': 2 }); + return num != this.b && num != this.d; + }, { 'b': 2, 'd': 4 }); deepEqual(actual, expected); }); @@ -12152,7 +12148,7 @@ (function() { var args = arguments, - object = { 'a': 1, 'b': 2, 'c': 3 }, + object = { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, expected = { 'a': 1, 'c': 3 }; test('should create an object of picked properties', 2, function() { @@ -12160,12 +12156,8 @@ deepEqual(_.pick(object, 'a', 'c'), expected); }); - test('should support picking an array of properties', 1, function() { - deepEqual(_.pick(object, ['a', 'c']), expected); - }); - - test('should support picking an array of properties and individual properties', 1, function() { - deepEqual(_.pick(object, ['a'], 'c'), expected); + test('should flatten `props`', 1, function() { + deepEqual(_.pick(object, ['a', 'd'], 'c'), { 'a': 1, 'c': 3, 'd': 4 }); }); test('should iterate over inherited properties', 1, function() { @@ -12193,15 +12185,15 @@ deepEqual(_.pick('', 'slice'), { 'slice': ''.slice }); }); - test('should work with a `predicate` argument', 1, function() { + test('should work with a predicate argument', 1, function() { var actual = _.pick(object, function(num) { - return num != 2; + return num == 1 || num == 3; }); deepEqual(actual, expected); }); - test('should provide the correct `predicate` arguments', 1, function() { + test('should provide the correct predicate arguments', 1, function() { var args, object = { 'a': 1, 'b': 2 }, lastKey = _.keys(object).pop(); @@ -12219,8 +12211,8 @@ test('should set the `this` binding', 1, function() { var actual = _.pick(object, function(num) { - return num != this.b; - }, { 'b': 2 }); + return num == this.a || num == this.c; + }, { 'a': 1, 'c': 3 }); deepEqual(actual, expected); }); From 3404dc0b754bde2f5c4453bccc6eba4f45864a27 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 12 Jun 2015 00:24:35 -0700 Subject: [PATCH 065/107] Update tested browsers for saucelabs. --- test/saucelabs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/saucelabs.js b/test/saucelabs.js index f2f2e38577..72b9d46ab6 100644 --- a/test/saucelabs.js +++ b/test/saucelabs.js @@ -105,11 +105,11 @@ var platforms = [ ['Linux', 'android', '5.0'], ['Linux', 'android', '4.4'], ['Linux', 'android', '4.0'], + ['Windows 8.1', 'firefox', '38'], ['Windows 8.1', 'firefox', '37'], - ['Windows 8.1', 'firefox', '36'], ['Windows 8.1', 'firefox', '20'], + ['Windows 8.1', 'chrome', '43'], ['Windows 8.1', 'chrome', '42'], - ['Windows 8.1', 'chrome', '41'], ['Windows 8.1', 'internet explorer', '11'], ['Windows 8', 'internet explorer', '10'], ['Windows 7', 'internet explorer', '9'], From f79de23be5fbf12b77a70b63a0a4a14406a858d7 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 12 Jun 2015 18:03:26 -0700 Subject: [PATCH 066/107] Remove unneeded pattern sub in travis.yml. --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 38e11bc973..a2c0b8ec09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,7 @@ node_js: - "0.12" env: global: - - PATTERN1="s|^.+?!support\.funcNames\b[\s\S]+?\.name\b[\s\S]+?\}\n||m" - - PATTERN2="s|\s*else\s*\{\s*iteratee\(index\);\s*\}||" + - PATTERN1="s|\s*else\s*\{\s*iteratee\(index\);\s*\}||" - BIN="node" BUILD="compat" ISTANBUL=false OPTION="" - NPM_VERSION="^2.0.0" SAUCE_LABS=false SAUCE_USERNAME="lodash" - secure: "tg1JFsIFnxzLaTboFPOnm+aJCuMm5+JdhLlESlqg9x3fwro++7KCnwHKLNovhchaPe4otC43ZMB/nfWhDnDm11dKbm/V6HlTkED+dadTsaLxVDg6J+7yK41QhokBPJOxLV78iDaNaAQVYEirAgZ0yn8kFubxmNKV+bpCGQNc9yU=" @@ -57,11 +56,11 @@ before_install: - "[ $BIN != 'ringo' ] || (wget --no-check-certificate https://lodash.com/_travis/ringojs-0.11.zip && sudo unzip ringojs-0.11 -d /opt && rm ringojs-0.11.zip)" - "[ $BIN != 'ringo' ] || (sudo ln -s /opt/ringojs-0.11/bin/ringo /usr/local/bin/ringo && sudo chmod +x $_)" - "perl -pi -e 's|\"lodash\"|\"lodash-compat\"|' ./package.json" - - "git clone --depth=10 --branch=master git://github.com/lodash/lodash-cli.git ./node_modules/lodash-cli && mkdir $_/node_modules && cd $_ && ln -s ../../../ ./lodash-compat && cd ../ && npm i && cd ../../" + - "git clone --depth=10 --branch=master git://github.com/lodash/lodash-cli ./node_modules/lodash-cli && mkdir $_/node_modules && cd $_ && ln -s ../../../ ./lodash-compat && cd ../ && npm i && cd ../../" - "node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./lodash.$BUILD.js" script: - "[ $ISTANBUL == false ] || cp ./lodash.$BUILD.js ./lodash.js" - - "[ $ISTANBUL == false ] || perl -0pi -e \"$PATTERN1\" ./lodash.js && perl -0pi -e \"$PATTERN2\" $_" + - "[ $ISTANBUL == false ] || perl -0pi -e \"$PATTERN\" ./lodash.js" - "[ $ISTANBUL == false ] || node ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./lodash.js" - "[ $ISTANBUL == false ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || (cat ./coverage/lcov.info | coveralls)" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || cd ./test" From 804e00cc26b2c2197cae81d8648d5356c208bab0 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 12 Jun 2015 18:06:20 -0700 Subject: [PATCH 067/107] Ensure bound `Date` can be instantiated with all 7 params. --- lodash.src.js | 2 ++ test/test.js | 33 +++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 313aa52dc1..d03a034931 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3270,6 +3270,8 @@ case 3: return new Ctor(args[0], args[1], args[2]); case 4: return new Ctor(args[0], args[1], args[2], args[3]); case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); } var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); diff --git a/test/test.js b/test/test.js index 77dc7559bd..495aece393 100644 --- a/test/test.js +++ b/test/test.js @@ -1365,9 +1365,10 @@ } var bound = _.bind(Foo, { 'a': 1 }), - expected = _.times(7, _.constant(undefined)); + count = 9, + expected = _.times(count, _.constant(undefined)); - var actual = _.times(7, function(index) { + var actual = _.times(count, function(index) { try { switch (index) { case 0: return (new bound).a; @@ -1377,6 +1378,8 @@ case 4: return (new bound(1, 2, 3, 4)).a; case 5: return (new bound(1, 2, 3, 4, 5)).a; case 6: return (new bound(1, 2, 3, 4, 5, 6)).a; + case 7: return (new bound(1, 2, 3, 4, 5, 6, 7)).a; + case 8: return (new bound(1, 2, 3, 4, 5, 6, 7, 8)).a; } } catch(e) {} }); @@ -1417,14 +1420,34 @@ deepEqual(bound3(), [object1, 'b']); }); + test('should not error when instantiating bound built-ins', 2, function() { + var Ctor = _.bind(Date, null), + expected = new Date(2012, 4, 23, 0, 0, 0, 0); + + try { + var actual = new Ctor(2012, 4, 23, 0, 0, 0, 0); + } catch(e) {} + + deepEqual(actual, expected); + + Ctor = _.bind(Date, null, 2012, 4, 23); + + try { + actual = new Ctor(0, 0, 0, 0); + } catch(e) {} + + deepEqual(actual, expected); + }); + test('should not error when calling bound class constructors with the `new` operator', 1, function() { var createCtor = _.attempt(Function, '"use strict";return class A{}'); if (typeof createCtor == 'function') { var bound = _.bind(createCtor()), - expected = _.times(6, _.constant(true)); + count = 8, + expected = _.times(count, _.constant(true)); - var actual = _.times(6, function(index) { + var actual = _.times(count, function(index) { try { switch (index) { case 0: return !!(new bound); @@ -1433,6 +1456,8 @@ case 3: return !!(new bound(1, 2, 3)); case 4: return !!(new bound(1, 2, 3, 4)); case 5: return !!(new bound(1, 2, 3, 4, 5)); + case 6: return !!(new bound(1, 2, 3, 4, 5, 6)); + case 7: return !!(new bound(1, 2, 3, 4, 5, 6, 7)); } } catch(e) {} }); From ce13b6abfd45ca3b7edf90636afff8eeb70308af Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 13 Jun 2015 10:09:27 -0700 Subject: [PATCH 068/107] Make test labels more consistent. --- test/test.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/test.js b/test/test.js index 495aece393..76b7ef417c 100644 --- a/test/test.js +++ b/test/test.js @@ -829,7 +829,7 @@ var values = empties.concat(true, 1, 'a'), expected = _.map(values, _.constant(true)); - test('creates a new instance when called without the `new` operator', 1, function() { + test('should create a new instance when called without the `new` operator', 1, function() { if (!isNpm) { var actual = _.map(values, function(value) { return _(value) instanceof _; @@ -1387,7 +1387,7 @@ deepEqual(actual, expected); }); - test('ensure `new bound` is an instance of `func`', 2, function() { + test('should ensure `new bound` is an instance of `func`', 2, function() { function Foo(value) { return value && object; } @@ -3199,7 +3199,7 @@ }); }); - test('ensure `new curried` is an instance of `func`', 2, function() { + test('should ensure `new curried` is an instance of `func`', 2, function() { var Foo = function(value) { return value && object; }; @@ -3302,7 +3302,7 @@ }); }); - test('ensure `new curried` is an instance of `func`', 2, function() { + test('should ensure `new curried` is an instance of `func`', 2, function() { var Foo = function(value) { return value && object; }; @@ -5273,7 +5273,7 @@ _.each(['forOwn', 'forOwnRight'], function(methodName) { var func = _[methodName]; - test('iterates over the `length` property', 1, function() { + test('should iterate over `length` properties', 1, function() { var object = { '0': 'zero', '1': 'one', 'length': 2 }, props = []; @@ -7214,11 +7214,11 @@ strictEqual(_.isEmpty({ 'length': '0' }), false); }); - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + test('should fix the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { strictEqual(_.isEmpty(shadowObject), 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() { + test('should skip 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; @@ -7636,7 +7636,7 @@ strictEqual(_.isEqual(36, '36'), false); }); - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + test('should fix the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { strictEqual(_.isEqual(shadowObject, {}), false); }); @@ -10818,7 +10818,7 @@ QUnit.module('lodash.methodOf'); (function() { - test('hould create a function that calls a method of a given key', 4, function() { + test('should create a function that calls a method of a given key', 4, function() { var object = { 'a': _.constant(1) }; _.each(['a', ['a']], function(path) { @@ -11930,7 +11930,7 @@ ph3 = _.partial.placeholder, ph4 = _.partialRight.placeholder; - test('combinations of partial functions should work', 1, function() { + test('should work with combinations of partial functions', 1, function() { var a = _.partial(fn), b = _.partialRight(a, 3), c = _.partial(b, 1); @@ -11938,7 +11938,7 @@ deepEqual(c(2), [1, 2, 3]); }); - test('combinations of bound and partial functions should work', 3, function() { + test('should work with combinations of bound and partial functions', 3, function() { var fn = function() { var result = [this.a]; push.apply(result, arguments); @@ -11967,7 +11967,7 @@ deepEqual(c(3), expected); }); - test('combinations of functions with placeholders should work', 3, function() { + test('should work with combinations of functions with placeholders', 3, function() { var expected = [1, 2, 3, 4, 5, 6], object = { 'fn': fn }; @@ -11990,7 +11990,7 @@ deepEqual(c(3, 5), expected); }); - test('combinations of functions with overlaping placeholders should work', 3, function() { + test('should work with combinations of functions with overlaping placeholders', 3, function() { var expected = [1, 2, 3, 4], object = { 'fn': fn }; @@ -12013,7 +12013,7 @@ deepEqual(c(1), expected); }); - test('recursively bound functions should work', 1, function() { + test('should work with recursively bound functions', 1, function() { var fn = function() { return this.a; }; @@ -14175,7 +14175,7 @@ strictEqual(_.size({ 'length': '0' }), 1); }); - test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { + test('should fix the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() { strictEqual(_.size(shadowObject), 7); }); From 0a165675cea91ba12d24da8176cbf182c4e022f9 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 14 Jun 2015 07:41:07 -0700 Subject: [PATCH 069/107] Allow coveralls service to fail. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a2c0b8ec09..c44b822cd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,7 +62,7 @@ script: - "[ $ISTANBUL == false ] || cp ./lodash.$BUILD.js ./lodash.js" - "[ $ISTANBUL == false ] || perl -0pi -e \"$PATTERN\" ./lodash.js" - "[ $ISTANBUL == false ] || node ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./lodash.js" - - "[ $ISTANBUL == false ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || (cat ./coverage/lcov.info | coveralls)" + - "[ $ISTANBUL == false ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || (cat ./coverage/lcov.info | coveralls) || true" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || cd ./test" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || $BIN $OPTION ./test.js ../lodash.$BUILD.js" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || $BIN $OPTION ./test.js ../lodash.$BUILD.min.js" From 958381d3ddeba8c2c6c0caef5a1817da7cce8b87 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 14 Jun 2015 18:00:22 -0700 Subject: [PATCH 070/107] Tweak `_.modArgs` docs. [ci skip] --- lodash.src.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index d03a034931..d36c1c8f7a 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -8032,7 +8032,8 @@ } /** - * Creates a function that runs each argument through a transform function. + * Creates a function that runs each argument through a corresponding + * transform function. * * @static * @memberOf _ @@ -8052,7 +8053,7 @@ * } * * var modded = _.modArgs(function(x, y) { - * return [x , y]; + * return [x, y]; * }, square, doubled); * * modded(1, 2); From dbb342da813fe132af0b0ab89e883da2a7e15e12 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 14 Jun 2015 18:01:02 -0700 Subject: [PATCH 071/107] Minor comment tweak in `baseClone`. [ci skip] --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index d36c1c8f7a..20fc01e77e 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1824,7 +1824,7 @@ : (object ? value : {}); } } - // Check for circular references and return corresponding clone. + // Check for circular references and return its corresponding clone. stackA || (stackA = []); stackB || (stackB = []); From e95ae66af04533c9320af4ebb8dea08786cfd55b Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 14 Jun 2015 22:48:30 -0700 Subject: [PATCH 072/107] Update instanbul in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c44b822cd8..213a015a03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ before_install: - "npm config set loglevel error" - "npm i -g npm@\"$NPM_VERSION\"" - "[ $SAUCE_LABS == false ] || npm i chalk@\"^1.0.0\" ecstatic@\"0.8.0\" request@\"^2.0.0\" sauce-tunnel@\"2.2.3\"" - - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.14\")" + - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.15\")" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7.6 && sudo wget --no-check-certificate -O $_/js.jar https://lodash.com/_travis/rhino-1.7.6.jar)" - "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7.6/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)" - "[ $BIN != 'ringo' ] || (wget --no-check-certificate https://lodash.com/_travis/ringojs-0.11.zip && sudo unzip ringojs-0.11 -d /opt && rm ringojs-0.11.zip)" From 56cd679bcdd428575587b2ee4fec2c25096ebfa2 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 17 Jun 2015 22:35:53 -0700 Subject: [PATCH 073/107] Improve perf of `max` and `min` common case with arrays. --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 20fc01e77e..3d7add2771 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3316,7 +3316,7 @@ } iteratee = getCallback(iteratee, thisArg, 3); if (iteratee.length == 1) { - collection = toIterable(collection); + collection = isArray(collection) ? collection : toIterable(collection); var result = arrayExtremum(collection, iteratee, comparator, exValue); if (!(collection.length && result === exValue)) { return result; From 535eec53666611df680df8ae7b49d1d695b87270 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 18 Jun 2015 07:51:43 -0700 Subject: [PATCH 074/107] Add `_.sum` benchmark. --- perf/perf.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/perf/perf.js b/perf/perf.js index f1ee17006e..da375fbb7a 100644 --- a/perf/perf.js +++ b/perf/perf.js @@ -1881,6 +1881,18 @@ /*--------------------------------------------------------------------------*/ + suites.push( + Benchmark.Suite('`_.sum`') + .add(buildName, '\ + lodash.sum(numbers)' + ) + .add(otherName, '\ + _.sum(numbers)' + ) + ); + + /*--------------------------------------------------------------------------*/ + suites.push( Benchmark.Suite('`_.template` (slow path)') .add(buildName, { From 4bcb99a6b9d77a0364788d7bd85ff0faa8efa4e9 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 18 Jun 2015 07:45:03 -0700 Subject: [PATCH 075/107] Simplify `_.sum`. --- lodash.src.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 3d7add2771..2634141b5a 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1606,18 +1606,20 @@ } /** - * A specialized version of `_.sum` for arrays without support for iteratees. + * A specialized version of `_.sum` for arrays without support for callback + * shorthands and `this` binding.. * * @private * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. * @returns {number} Returns the sum. */ - function arraySum(array) { + function arraySum(array, iteratee) { var length = array.length, result = 0; while (length--) { - result += +array[length] || 0; + result += +iteratee(array[length]) || 0; } return result; } @@ -11948,15 +11950,9 @@ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { iteratee = undefined; } - var callback = getCallback(), - noIteratee = iteratee == null; - - if (!(noIteratee && callback === baseCallback)) { - noIteratee = false; - iteratee = callback(iteratee, thisArg, 3); - } - return noIteratee - ? arraySum(isArray(collection) ? collection : toIterable(collection)) + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 + ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); } From 4896c725b63ce8e955d6a5e042fc414456dad2ea Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 19 Jun 2015 10:53:02 -0700 Subject: [PATCH 076/107] Ensure `_.escapeRegExp` handles empty strings in a way to work with compilation. --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 2634141b5a..e7d242ef7a 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -10492,7 +10492,7 @@ string = baseToString(string); return (string && reHasRegExpChars.test(string)) ? string.replace(reRegExpChars, '\\$&') - : string; + : (string || '(?:)'); } /** From 192667d65f4efe32215ac51353d6e7705ff931d3 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 19 Jun 2015 22:04:36 -0700 Subject: [PATCH 077/107] Ensure `_.escapeRegExp` escapes line terminators. --- lodash.src.js | 9 ++++----- test/test.js | 29 +++++++++++++++-------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index e7d242ef7a..69b0acd020 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -94,11 +94,10 @@ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; /** - * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). - * In addition to special characters the forward slash is escaped to allow for - * easier `eval` use and `Function` compilation. + * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) + * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). */ - var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, + var reRegExpChars = /[\/^$\\.*+?()[\]{}|\n\r\u2028\u2029]/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ @@ -10491,7 +10490,7 @@ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, '\\$&') + ? string.replace(reRegExpChars, function(chr) { return '\\' + (stringEscapes[chr] || chr); }) : (string || '(?:)'); } diff --git a/test/test.js b/test/test.js index 76b7ef417c..76b02c574e 100644 --- a/test/test.js +++ b/test/test.js @@ -4222,29 +4222,31 @@ QUnit.module('lodash.escapeRegExp'); (function() { - test('should escape values', 1, function() { - var escaped = '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\/\\\\', - unescaped = '.*+?^${}()|[\]\/\\'; - - escaped += escaped; - unescaped += unescaped; + var escaped = '\\/\\^\\$\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\n\\r\\u2028\\u2029\\\\', + unescaped = '/^$.*+?()[]{}|\n\r\u2028\u2029\\'; - strictEqual(_.escapeRegExp(unescaped), escaped); + test('should escape values', 1, function() { + strictEqual(_.escapeRegExp(unescaped + unescaped), escaped + escaped); }); test('should handle strings with nothing to escape', 1, function() { strictEqual(_.escapeRegExp('abc'), 'abc'); }); + test('should return `"(?:)"` when provided nullish or empty string values', 3, function() { + strictEqual(_.escapeRegExp(null), '(?:)'); + strictEqual(_.escapeRegExp(undefined), '(?:)'); + strictEqual(_.escapeRegExp(''), '(?:)'); + }); + test('should work with `eval` and `Function`', 2, function() { - var string = '[lodash](https://lodash.com/)', - escaped = _.escapeRegExp(string), - regexp = eval('(/' + escaped + '/)'); + var actual = _.escapeRegExp(unescaped), + regexp = eval('(/' + actual + '/)'); - ok(regexp.test(string)); + ok(regexp.test(unescaped)); - regexp = Function('return /' + escaped + '/')(); - ok(regexp.test(string)); + regexp = Function('return /' + actual + '/')(); + ok(regexp.test(unescaped)); }); }()); @@ -17819,7 +17821,6 @@ 'camelCase', 'capitalize', 'escape', - 'escapeRegExp', 'kebabCase', 'pad', 'padLeft', From 660bc2eb214d520215e853f50924accdc8382064 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 20 Jun 2015 08:20:51 -0700 Subject: [PATCH 078/107] Use `escapeStringChar` in `_.escapeRegExp`. --- lodash.src.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 69b0acd020..e496ed38af 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -497,7 +497,7 @@ * @returns {string} Returns the escaped character. */ function escapeStringChar(chr) { - return '\\' + stringEscapes[chr]; + return '\\' + (stringEscapes[chr] || chr); } /** @@ -10490,7 +10490,7 @@ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, function(chr) { return '\\' + (stringEscapes[chr] || chr); }) + ? string.replace(reRegExpChars, escapeStringChar) : (string || '(?:)'); } From 889c184ba373354aa10cf79bf77181d4d59eb402 Mon Sep 17 00:00:00 2001 From: Graeme Yeates Date: Sat, 20 Jun 2015 19:42:16 -0400 Subject: [PATCH 079/107] Ensure `_.debounce` and `_.throttle` reset `lastCall` after cancelling. --- lodash.src.js | 1 + test/test.js | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lodash.src.js b/lodash.src.js index e496ed38af..dd50ea0281 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7792,6 +7792,7 @@ if (maxTimeoutId) { clearTimeout(maxTimeoutId); } + lastCalled = 0; maxTimeoutId = timeoutId = trailingCall = undefined; } diff --git a/test/test.js b/test/test.js index 76b02c574e..f861695ddd 100644 --- a/test/test.js +++ b/test/test.js @@ -15889,6 +15889,29 @@ QUnit.start(); } }); + + asyncTest('_.' + methodName + ' should reset `lastCalled` after cancelling', 3, function() { + if (!(isRhino && isModularize)) { + var callCount = 0; + + var funced = func(function() { + return ++callCount; + }, 32, { 'leading': true }); + + strictEqual(funced(), 1); + funced.cancel(); + strictEqual(funced(), 2); + + setTimeout(function() { + strictEqual(callCount, 2); + QUnit.start(); + }, 64); + } + else { + skipTest(3); + QUnit.start(); + } + }); }); /*--------------------------------------------------------------------------*/ From 85ddabd763b07ece4158f5a3cd8581067943ff36 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 20 Jun 2015 09:27:08 -0700 Subject: [PATCH 080/107] Cleanup docs for `baseMerge`, `baseMergeDeep`, `createAggregator`, & `createAssigner`. [ci skip] --- lodash.src.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index dd50ea0281..06cd1926bc 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -2455,7 +2455,7 @@ * @private * @param {Object} object The destination object. * @param {Object} source The source object. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns `object`. @@ -2504,7 +2504,7 @@ * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. @@ -3075,12 +3075,7 @@ } /** - * Creates a function that aggregates a collection, creating an accumulator - * object composed from the results of running each element in the collection - * through an iteratee. - * - * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, - * and `_.partition`. + * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. @@ -3110,10 +3105,7 @@ } /** - * Creates a function that assigns properties of source object(s) to a given - * destination object. - * - * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. + * Creates a `_.assign`, `_.defaults`, or `_.merge` function. * * @private * @param {Function} assigner The function to assign values. From 134bf612054e8aef7643562e8aa59342a238b717 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 20 Jun 2015 09:27:22 -0700 Subject: [PATCH 081/107] Add `_.defaultsDeep`. --- lodash.src.js | 161 ++++++++++++++++++++++++++++++++------------------ test/test.js | 2 +- 2 files changed, 104 insertions(+), 59 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 06cd1926bc..109a4e4978 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3294,6 +3294,25 @@ return curryFunc; } + /** + * Creates a `_.defaults` or `_.defaultsDeep` function. + * + * @private + * @param {Function} assigner The function to assign values. + * @param {Function} customizer The function to customize assigned values. + * @returns {Function} Returns the new defaults function. + */ + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + /** * Creates a `_.max` or `_.min` function. * @@ -4344,6 +4363,18 @@ return data; } + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + /** * A specialized version of `_.pick` which picks `object` properties specified * by `props`. @@ -9238,6 +9269,56 @@ /*------------------------------------------------------------------------*/ + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined` into the destination object. Subsequent sources + * overwrite property assignments of previous sources. If `customizer` is + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled + * by the method instead. The `customizer` is bound to `thisArg` and invoked + * with five arguments: (objectValue, sourceValue, key, object, source). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. + * @example + * + * var users = { + * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * }; + * + * var ages = { + * 'data': [{ 'age': 36 }, { 'age': 40 }] + * }; + * + * _.merge(users, ages); + * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } + * + * // using a customizer callback + * var object = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var other = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(object, other, function(a, b) { + * if (_.isArray(a)) { + * return a.concat(b); + * } + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } + */ + var merge = createAssigner(baseMerge); + /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. @@ -9336,14 +9417,27 @@ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ - var defaults = restParam(function(args) { - var object = args[0]; - if (object == null) { - return object; - } - args.push(assignDefaults); - return assign.apply(undefined, args); - }); + var defaults = createDefaults(assign, assignDefaults); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); + * // => { 'user': { 'name': 'barney', 'age': 36 } } + * + */ + var defaultsDeep = createDefaults(merge, mergeDefaults); /** * This method is like `_.find` except that it returns the key of the first @@ -9875,56 +9969,6 @@ */ var mapValues = createObjectMapper(); - /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * overwrite property assignments of previous sources. If `customizer` is - * provided it is invoked to produce the merged values of the destination and - * source properties. If `customizer` returns `undefined` merging is handled - * by the method instead. The `customizer` is bound to `thisArg` and invoked - * with five arguments: (objectValue, sourceValue, key, object, source). - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {Object} Returns `object`. - * @example - * - * var users = { - * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] - * }; - * - * var ages = { - * 'data': [{ 'age': 36 }, { 'age': 40 }] - * }; - * - * _.merge(users, ages); - * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } - * - * // using a customizer callback - * var object = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var other = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(object, other, function(a, b) { - * if (_.isArray(a)) { - * return a.concat(b); - * } - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } - */ - var merge = createAssigner(baseMerge); - /** * The opposite of `_.pick`; this method creates an object composed of the * own and inherited enumerable properties of `object` that are not omitted. @@ -11991,6 +12035,7 @@ lodash.curryRight = curryRight; lodash.debounce = debounce; lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; diff --git a/test/test.js b/test/test.js index f861695ddd..a06fabc2bc 100644 --- a/test/test.js +++ b/test/test.js @@ -17949,7 +17949,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 228, function() { + test('should accept falsey arguments', 229, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From 71ed48bb76dd771b66997cf598297027c6cc1c7f Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 21 Jun 2015 17:29:16 -0700 Subject: [PATCH 082/107] Ensure `leading` and `trailing` debounce options are coerced to booleans. --- lodash.src.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 109a4e4978..fa0a20416b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7803,9 +7803,9 @@ var leading = true; trailing = false; } else if (isObject(options)) { - leading = options.leading; + leading = !!options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); - trailing = 'trailing' in options ? options.trailing : trailing; + trailing = 'trailing' in options ? !!options.trailing : trailing; } function cancel() { From 7480e481fc050ebfc7febceb345b2d5f88c32366 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 22 Jun 2015 10:26:23 -0700 Subject: [PATCH 083/107] Add `_.defaultsDeep` tests. --- test/test.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/test.js b/test/test.js index a06fabc2bc..7e0f863988 100644 --- a/test/test.js +++ b/test/test.js @@ -3668,6 +3668,47 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.defaultsDeep'); + + (function() { + test('should deep assign properties of a source object if missing on the destination object', 1, function() { + var object = { 'a': { 'b': 2 }, 'd': 4 }, + source = { 'a': { 'b': 1, 'c': 3 }, 'e': 5 }, + expected = { 'a': { 'b': 2, 'c': 3 }, 'd': 4, 'e': 5 }; + + deepEqual(_.defaultsDeep(object, source), expected); + }); + + test('should accept multiple source objects', 2, function() { + var source1 = { 'a': { 'b': 3 } }, + source2 = { 'a': { 'c': 3 } }, + source3 = { 'a': { 'b': 3, 'c': 3 } }, + source4 = { 'a': { 'c': 4 } }, + expected = { 'a': { 'b': 2, 'c': 3 } }; + + deepEqual(_.defaultsDeep({ 'a': { 'b': 2 } }, source1, source2), expected); + deepEqual(_.defaultsDeep({ 'a': { 'b': 2 } }, source3, source4), expected); + }); + + test('should not overwrite `null` values', 1, function() { + var object = { 'a': { 'b': null } }, + source = { 'a': { 'b': 2 } }, + actual = _.defaultsDeep(object, source); + + strictEqual(actual.a.b, null); + }); + + test('should overwrite `undefined` values', 1, function() { + var object = { 'a': { 'b': undefined } }, + source = { 'a': { 'b': 2 } }, + actual = _.defaultsDeep(object, source); + + strictEqual(actual.a.b, 2); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.defer'); (function() { From bc34d809499e5166b30a35b14ea97b195ac935ad Mon Sep 17 00:00:00 2001 From: Graeme Yeates Date: Mon, 22 Jun 2015 20:55:45 -0400 Subject: [PATCH 084/107] Clarify shortcut fusion docs. [ci skip] --- lodash.src.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index fa0a20416b..bc555ee177 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -832,8 +832,9 @@ * called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut - * fusion is an optimization that merges iteratees to avoid creating intermediate - * arrays and reduce the number of iteratee executions. + * fusion is an optimization strategy which merge iteratee calls; this can help + * to avoid the creation of intermediate data structures and greatly reduce the + * number of iteratee executions. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. From f59551b89e10709d026034897f5791f08395738c Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Tue, 23 Jun 2015 15:59:11 +0200 Subject: [PATCH 085/107] Link to the final ES6 spec. [ci skip] --- lodash.src.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index bc555ee177..d7608602b6 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -106,7 +106,7 @@ /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; - /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ + /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ @@ -732,7 +732,7 @@ var idCounter = 0; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; @@ -781,7 +781,7 @@ HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; /** - * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) * of an array-like value. */ var MAX_SAFE_INTEGER = 9007199254740991; @@ -3254,7 +3254,7 @@ function createCtorWrapper(Ctor) { return function() { // Use a `switch` statement to work with class constructors. - // See https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist + // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { @@ -4272,7 +4272,7 @@ /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @private * @param {*} value The value to check. @@ -4645,7 +4645,7 @@ /** * Creates an array of unique `array` values not included in the other - * provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5055,7 +5055,7 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `array`. If `array` is sorted providing `true` for `fromIndex` * performs a faster binary search. @@ -5119,7 +5119,7 @@ /** * Creates an array of unique values that are included in all of the provided - * arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5240,7 +5240,7 @@ /** * Removes all provided values from `array` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. @@ -5673,7 +5673,7 @@ /** * Creates an array of unique values, in order, from all of the provided arrays - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5692,7 +5692,7 @@ /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurence of each element * is kept. Providing `true` for `isSorted` performs a faster search algorithm * for sorted arrays. If an iteratee function is provided it is invoked for @@ -5833,7 +5833,7 @@ /** * Creates an array excluding all provided values using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -6654,7 +6654,7 @@ /** * Checks if `value` is in `collection` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `collection`. * @@ -7996,7 +7996,7 @@ * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) * method interface of `get`, `has`, and `set`. * * @static @@ -8802,7 +8802,7 @@ /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). + * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite). * * @static * @memberOf _ @@ -9328,7 +9328,7 @@ * (objectValue, sourceValue, key, object, source). * * **Note:** This method mutates `object` and is based on - * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign). + * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign). * * @static * @memberOf _ @@ -9794,7 +9794,7 @@ * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) * for more details. * * @static From 04701cd69eae6ef580045f0363e64c603810c50e Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 23 Jun 2015 07:06:23 -0700 Subject: [PATCH 086/107] Add `defaultsDeep` references to `lodash` and `_.reduce` doc notes. [ci skip] --- lodash.src.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index d7608602b6..7624354641 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -857,21 +857,21 @@ * The chainable wrapper methods are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, - * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, - * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, - * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, - * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, - * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, - * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `modArgs`, `negate`, - * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, - * `plant`, `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, - * `rearg`, `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, - * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, - * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, - * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, - * `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`, - * `wrap`, `xor`, `zip`, `zipObject`, `zipWith` + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, + * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, + * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, + * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, + * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, + * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, + * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, + * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, + * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, + * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, + * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, + * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, @@ -6946,7 +6946,8 @@ * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: - * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`, + * and `sortByOrder` * * @static * @memberOf _ From 1fcaa481be5d839e482a25587527863f8733f335 Mon Sep 17 00:00:00 2001 From: Graeme Yeates Date: Tue, 23 Jun 2015 13:04:31 -0400 Subject: [PATCH 087/107] Reduce debounce redundancy for executing bound function --- lodash.src.js | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 7624354641..0cd5c13d2c 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7821,38 +7821,31 @@ maxTimeoutId = timeoutId = trailingCall = undefined; } + function executeBoundFunction(shouldExecute, clearTimeoutId) { + if (clearTimeoutId) { + clearTimeout(clearTimeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (shouldExecute) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = undefined; - } - } + executeBoundFunction(trailingCall, maxTimeoutId); } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { - if (timeoutId) { - clearTimeout(timeoutId); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (trailing || (maxWait !== wait)) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = undefined; - } - } + executeBoundFunction(trailing || (maxWait !== wait), timeoutId); } function debounced() { From 91849e4cd1c2569b81ad7a6057bd39b719d0137d Mon Sep 17 00:00:00 2001 From: Graeme Yeates Date: Tue, 23 Jun 2015 13:51:03 -0400 Subject: [PATCH 088/107] Test coverage for re-entrant debounced functions --- test/test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/test.js b/test/test.js index 7e0f863988..f2744730a4 100644 --- a/test/test.js +++ b/test/test.js @@ -15953,6 +15953,35 @@ QUnit.start(); } }); + + asyncTest('_.' + methodName + ' should support re-entrant calls', 2, function() { + if (!(isRhino && isModularize)) { + var sequence = [ + ['b1', 'b2'] + ]; + var value = ''; + var append = function(arg){ + value += this + arg; + var args = sequence.pop(); + if (args) { + debouncedAppend.call(args[0], args[1]); + } + }; + + var debouncedAppend = _.debounce(append, 32); + debouncedAppend.call('a1', 'a2'); + equal(value, ''); + + setTimeout(function(){ + equal(value, 'a1a2b1b2', 'append was debounced successfully'); + QUnit.start(); + }, 100); + } + else { + skipTest(2); + QUnit.start(); + } + }); }); /*--------------------------------------------------------------------------*/ From 6921fb66d54207d6a6b8327229c1f77859e0b84e Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 24 Jun 2015 23:00:57 -0700 Subject: [PATCH 089/107] Add `_.noConflict` test. --- test/test.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index f2744730a4..a5ea822f0d 100644 --- a/test/test.js +++ b/test/test.js @@ -11446,13 +11446,31 @@ test('should return the `lodash` function', 1, function() { if (!isModularize) { var oldDash = root._; - strictEqual(_.noConflict(), _); + strictEqual(_.noConflict(), oldDash); root._ = oldDash; } else { skipTest(); } }); + + test('should work with a `context` of `this`', 2, function() { + if (!isModularize && !document && _._object) { + var fs = require('fs'), + vm = require('vm'), + expected = {}, + context = vm.createContext({ '_': expected }), + source = fs.readFileSync(filePath); + + vm.runInContext(source + '\nthis.lodash = this._.noConflict()', context); + + strictEqual(context._, expected); + ok(!!context.lodash); + } + else { + skipTest(2); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -15967,11 +15985,11 @@ debouncedAppend.call(args[0], args[1]); } }; - + var debouncedAppend = _.debounce(append, 32); debouncedAppend.call('a1', 'a2'); equal(value, ''); - + setTimeout(function(){ equal(value, 'a1a2b1b2', 'append was debounced successfully'); QUnit.start(); From 9f3d284c68bfc2840534383779de12e7eaec8b41 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 24 Jun 2015 23:25:50 -0700 Subject: [PATCH 090/107] Remove `isExposed` check from test.js. --- test/test.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/test.js b/test/test.js index a5ea822f0d..032e5ce390 100644 --- a/test/test.js +++ b/test/test.js @@ -18039,7 +18039,6 @@ test('should accept falsey arguments', 229, function() { var emptyArrays = _.map(falsey, _.constant([])), - isExposed = '_' in root, oldDash = root._; _.each(acceptFalsey, function(methodName) { @@ -18056,11 +18055,7 @@ }); if (methodName == 'noConflict') { - if (isExposed) { - root._ = oldDash; - } else { - delete root._; - } + root._ = oldDash; } else if (methodName == 'pull') { expected = falsey; From 1881f5cb39810a7e2eb9ed655fbb187c38d54ff0 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 25 Jun 2015 08:03:38 -0700 Subject: [PATCH 091/107] Ensure `_.noConflict` operates on `root` and not `context`. --- lodash.src.js | 4 ++-- test/test.js | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 0cd5c13d2c..2692c43ec6 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -738,7 +738,7 @@ var objToString = objectProto.toString; /** Used to restore the original `_` reference in `_.noConflict`. */ - var oldDash = context._; + var oldDash = root._; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + @@ -11558,7 +11558,7 @@ * var lodash = _.noConflict(); */ function noConflict() { - context._ = oldDash; + root._ = oldDash; return this; } diff --git a/test/test.js b/test/test.js index 032e5ce390..8f4fd1a161 100644 --- a/test/test.js +++ b/test/test.js @@ -11443,23 +11443,30 @@ QUnit.module('lodash.noConflict'); (function() { - test('should return the `lodash` function', 1, function() { + test('should return the `lodash` function', 2, function() { if (!isModularize) { var oldDash = root._; strictEqual(_.noConflict(), oldDash); + + if (!(isRhino && typeof require == 'function')) { + notStrictEqual(root._, oldDash); + } + else { + skipTest(); + } root._ = oldDash; } else { - skipTest(); + skipTest(2); } }); - test('should work with a `context` of `this`', 2, function() { + test('should work with a `root` of `this`', 2, function() { if (!isModularize && !document && _._object) { var fs = require('fs'), vm = require('vm'), expected = {}, - context = vm.createContext({ '_': expected }), + context = vm.createContext({ '_': expected, 'console': console }), source = fs.readFileSync(filePath); vm.runInContext(source + '\nthis.lodash = this._.noConflict()', context); From 67359c22d5d008226e31d780dfb15fea32b292ad Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 25 Jun 2015 11:16:24 -0700 Subject: [PATCH 092/107] Remove duplicate `_.debounce` and `_.throttle` test. --- test/test.js | 40 +++++----------------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/test/test.js b/test/test.js index 8f4fd1a161..f91e09f77a 100644 --- a/test/test.js +++ b/test/test.js @@ -15870,9 +15870,8 @@ asyncTest('_.' + methodName + ' supports recursive calls', 2, function() { if (!(isRhino && isModularize)) { var actual = [], - args = _.map(['a', 'b', 'c'], function(chr) { return [{}, chr]; }), - length = isDebounce ? 1 : 2, - expected = args.slice(0, length), + args = _.map(['a', 'b', 'c'], function(chr) { return [{ 'a': 1 }, chr]; }), + expected = args.slice(), queue = args.slice(); var funced = func(function() { @@ -15888,12 +15887,12 @@ var next = queue.shift(); funced.call(next[0], next[1]); - deepEqual(actual, expected.slice(0, length - 1)); + deepEqual(actual, expected.slice(0, isDebounce ? 0 : 1)); setTimeout(function() { - deepEqual(actual, expected); + deepEqual(actual, expected.slice(0, isDebounce ? 2 : 3)); QUnit.start(); - }, 96); + }, 192); } else { skipTest(2); @@ -15978,35 +15977,6 @@ QUnit.start(); } }); - - asyncTest('_.' + methodName + ' should support re-entrant calls', 2, function() { - if (!(isRhino && isModularize)) { - var sequence = [ - ['b1', 'b2'] - ]; - var value = ''; - var append = function(arg){ - value += this + arg; - var args = sequence.pop(); - if (args) { - debouncedAppend.call(args[0], args[1]); - } - }; - - var debouncedAppend = _.debounce(append, 32); - debouncedAppend.call('a1', 'a2'); - equal(value, ''); - - setTimeout(function(){ - equal(value, 'a1a2b1b2', 'append was debounced successfully'); - QUnit.start(); - }, 100); - } - else { - skipTest(2); - QUnit.start(); - } - }); }); /*--------------------------------------------------------------------------*/ From 6b7c1ad6cf1b1f48dbc119f87808ea9879a0bb64 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 25 Jun 2015 14:34:04 -0700 Subject: [PATCH 093/107] Ensure `_.indexOf` and `_.lastIndexOf` return `-1` when performing a binary search for `undefined` and it's not found. [closes #1303] --- lodash.src.js | 7 +++---- test/test.js | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 2692c43ec6..5d8510da8f 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -5089,10 +5089,9 @@ if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; } else if (fromIndex) { - var index = binaryIndex(array, value), - other = array[index]; - - if (value === value ? (value === other) : (other !== other)) { + var index = binaryIndex(array, value); + if (index < length && + (value === value ? (value === array[index]) : (array[index] !== array[index]))) { return index; } return -1; diff --git a/test/test.js b/test/test.js index f91e09f77a..5d9f223f63 100644 --- a/test/test.js +++ b/test/test.js @@ -9354,12 +9354,13 @@ deepEqual(actual, expected); }); - test('`_.' + methodName + '` should return `-1` for an unmatched value', 4, function() { + test('`_.' + methodName + '` should return `-1` for an unmatched value', 5, function() { var array = [1, 2, 3], empty = []; strictEqual(func(array, 4), -1); strictEqual(func(array, 4, true), -1); + strictEqual(func(array, undefined, true), -1); strictEqual(func(empty, undefined), -1); strictEqual(func(empty, undefined, true), -1); From f57dadc3629a3319250a3589dd0bfb35794439c7 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 26 Jun 2015 00:57:51 -0700 Subject: [PATCH 094/107] Adjust recursive test for older VMs. --- test/test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test.js b/test/test.js index 5d9f223f63..eb93d5544b 100644 --- a/test/test.js +++ b/test/test.js @@ -15871,7 +15871,7 @@ asyncTest('_.' + methodName + ' supports recursive calls', 2, function() { if (!(isRhino && isModularize)) { var actual = [], - args = _.map(['a', 'b', 'c'], function(chr) { return [{ 'a': 1 }, chr]; }), + args = _.map(['a', 'b', 'c'], function(chr) { return [{}, chr]; }), expected = args.slice(), queue = args.slice(); @@ -15884,16 +15884,16 @@ if (next) { funced.call(next[0], next[1]); } - }, 64); + }, 32); var next = queue.shift(); funced.call(next[0], next[1]); deepEqual(actual, expected.slice(0, isDebounce ? 0 : 1)); setTimeout(function() { - deepEqual(actual, expected.slice(0, isDebounce ? 2 : 3)); + deepEqual(actual, expected.slice(0, actual.length)); QUnit.start(); - }, 192); + }, 256); } else { skipTest(2); From a8c8bd811340337bcf9bc9e787adde4d1fa08ce5 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 26 Jun 2015 07:00:17 -0700 Subject: [PATCH 095/107] Adjust timeouts on async tests. --- test/test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test.js b/test/test.js index eb93d5544b..9366ba616c 100644 --- a/test/test.js +++ b/test/test.js @@ -3720,7 +3720,7 @@ setTimeout(function() { ok(pass); QUnit.start(); - }, 128); + }, 32); } else { skipTest(); @@ -3739,7 +3739,7 @@ setTimeout(function() { deepEqual(args, [1, 2]); QUnit.start(); - }, 128); + }, 32); } else { skipTest(); @@ -3760,7 +3760,7 @@ setTimeout(function() { ok(pass); QUnit.start(); - }, 128); + }, 32); } else { skipTest(); @@ -3777,16 +3777,16 @@ asyncTest('should delay `func` execution', 2, function() { if (!(isRhino && isModularize)) { var pass = false; - _.delay(function() { pass = true; }, 96); + _.delay(function() { pass = true; }, 32); setTimeout(function() { ok(!pass); - }, 32); + }, 1); setTimeout(function() { ok(pass); QUnit.start(); - }, 160); + }, 64); } else { skipTest(2); @@ -3805,7 +3805,7 @@ setTimeout(function() { deepEqual(args, [1, 2]); QUnit.start(); - }, 128); + }, 64); } else { skipTest(); @@ -3826,7 +3826,7 @@ setTimeout(function() { ok(pass); QUnit.start(); - }, 128); + }, 64); } else { skipTest(); @@ -15712,7 +15712,7 @@ setTimeout(function() { strictEqual(callCount, 2); QUnit.start(); - }, 256); + }, 128); } else { skipTest(3); From ec7dce7d5bb9ed0a100d85096ee1f67fa5dcf4a1 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 26 Jun 2015 08:21:27 -0700 Subject: [PATCH 096/107] Rename `_.debounce` helper `executeBoundFunction` to `complete`. --- lodash.src.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 5d8510da8f..188145bd0e 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7820,12 +7820,12 @@ maxTimeoutId = timeoutId = trailingCall = undefined; } - function executeBoundFunction(shouldExecute, clearTimeoutId) { - if (clearTimeoutId) { - clearTimeout(clearTimeoutId); + function complete(isCalled, id) { + if (id) { + clearTimeout(id); } maxTimeoutId = timeoutId = trailingCall = undefined; - if (shouldExecute) { + if (isCalled) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { @@ -7837,14 +7837,14 @@ function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { - executeBoundFunction(trailingCall, maxTimeoutId); + complete(trailingCall, maxTimeoutId); } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { - executeBoundFunction(trailing || (maxWait !== wait), timeoutId); + complete(trailing || (maxWait !== wait), timeoutId); } function debounced() { From 116dbfd123fad5b489adc1cdb2ec1fb402ddd7eb Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 26 Jun 2015 08:26:27 -0700 Subject: [PATCH 097/107] Remove unneeded `maxWait` guard from `maxDelayed`. --- lodash.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 188145bd0e..e6004a6d4e 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7844,7 +7844,7 @@ } function maxDelayed() { - complete(trailing || (maxWait !== wait), timeoutId); + complete(trailing, timeoutId); } function debounced() { From 10c2232c398e095ff52f2306df08f0a0e0350285 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 27 Jun 2015 13:22:21 -0700 Subject: [PATCH 098/107] Make `_.escapeRegExp` escape characters that could cause problems for escape sequences and other edge cases. --- lodash.src.js | 36 +++++++++++++++++++++++++++++++----- test/test.js | 44 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index e6004a6d4e..2cb0f51bf8 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -97,7 +97,7 @@ * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). */ - var reRegExpChars = /[\/^$\\.*+?()[\]{}|\n\r\u2028\u2029]/g, + var reRegExpChars = /^[:!,]|[\/^$\\.*+?()[\]{}|]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ @@ -233,6 +233,15 @@ 'object': true }; + /** Used to escape characters for inclusion in compiled regexes. */ + var regexpEscapes = { + '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34', + '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39', + 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46', + 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66', + 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78' + }; + /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', @@ -489,15 +498,32 @@ } /** - * Used by `_.template` to escape characters for inclusion in compiled - * string literals. + * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes. + * + * @private + * @param {string} chr The matched character to escape. + * @param {string} leadingChar The capture group for a leading character. + * @param {string} whitespaceChar The capture group for a whitespace character. + * @returns {string} Returns the escaped character. + */ + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return '\\' + chr; + } + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeStringChar(chr) { - return '\\' + (stringEscapes[chr] || chr); + return '\\' + stringEscapes[chr]; } /** @@ -10521,7 +10547,7 @@ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, escapeStringChar) + ? string.replace(reRegExpChars, escapeRegExpChar) : (string || '(?:)'); } diff --git a/test/test.js b/test/test.js index 9366ba616c..dd86c936e8 100644 --- a/test/test.js +++ b/test/test.js @@ -285,6 +285,15 @@ new URIError ]; + /** Used to check escaped regexp characters. */ + var regexpEscapes = { + '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34', + '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39', + 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46', + 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66', + 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78' + }; + /** Used to check problem JScript properties (a.k.a. the `[[DontEnum]]` bug). */ var shadowProps = [ 'constructor', @@ -4270,14 +4279,39 @@ strictEqual(_.escapeRegExp(unescaped + unescaped), escaped + escaped); }); + test('should escape special characters at the start of a string', 1, function() { + var chars = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', + 'A', 'B', 'C', 'D', 'E', 'F', + 'n', 'r', 't', 'u', 'v', 'x', + ':', '!', ',' + ]; + + var expected = _.map(chars, function(chr) { + return ['\\' + (regexpEscapes[chr] || chr) + 'z', 'z' + chr]; + }); + + var actual = _.map(chars, function(chr) { + return [_.escapeRegExp(chr + 'z'), _.escapeRegExp('z' + chr)]; + }); + + deepEqual(actual, expected); + }); + test('should handle strings with nothing to escape', 1, function() { - strictEqual(_.escapeRegExp('abc'), 'abc'); + strictEqual(_.escapeRegExp('ghi'), 'ghi'); }); - test('should return `"(?:)"` when provided nullish or empty string values', 3, function() { - strictEqual(_.escapeRegExp(null), '(?:)'); - strictEqual(_.escapeRegExp(undefined), '(?:)'); - strictEqual(_.escapeRegExp(''), '(?:)'); + test('should return `"(?:)"` when provided nullish or empty string values', 1, function() { + var values = [, null, undefined, ''], + expected = _.map(values, _.constant('(?:)')); + + var actual = _.map(values, function(value, index) { + return index ? _.escapeRegExp(value) : _.escapeRegExp(); + }); + + deepEqual(actual, expected); }); test('should work with `eval` and `Function`', 2, function() { From 5acf5f6ee3b1d71f6fa42feccb0ea7d8ac8d4009 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 28 Jun 2015 10:17:19 -0700 Subject: [PATCH 099/107] Simplify `_.isNative` deps. --- lodash.src.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 2cb0f51bf8..386dba9148 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -97,7 +97,7 @@ * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). */ - var reRegExpChars = /^[:!,]|[\/^$\\.*+?()[\]{}|]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ @@ -768,7 +768,7 @@ /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - escapeRegExp(fnToString.call(hasOwnProperty)) + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); From c77ffa0f6ae18a34543b720782eec51bea7e529c Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 28 Jun 2015 14:26:18 -0700 Subject: [PATCH 100/107] Simplify `baseToString`. --- lodash.src.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 386dba9148..6aa8d435d2 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -382,9 +382,6 @@ * @returns {string} Returns the string. */ function baseToString(value) { - if (typeof value == 'string') { - return value; - } return value == null ? '' : (value + ''); } From 7f7c7f360e0e4fac4c79d9163e0e733f379d6e8f Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 28 Jun 2015 17:18:45 -0700 Subject: [PATCH 101/107] Update instanbul in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 213a015a03..3bf0cfe175 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ before_install: - "npm config set loglevel error" - "npm i -g npm@\"$NPM_VERSION\"" - "[ $SAUCE_LABS == false ] || npm i chalk@\"^1.0.0\" ecstatic@\"0.8.0\" request@\"^2.0.0\" sauce-tunnel@\"2.2.3\"" - - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.15\")" + - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.17\")" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7.6 && sudo wget --no-check-certificate -O $_/js.jar https://lodash.com/_travis/rhino-1.7.6.jar)" - "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7.6/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)" - "[ $BIN != 'ringo' ] || (wget --no-check-certificate https://lodash.com/_travis/ringojs-0.11.zip && sudo unzip ringojs-0.11 -d /opt && rm ringojs-0.11.zip)" From 29ceed91f069077a998451efbea9209acd1b37a6 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 29 Jun 2015 21:13:13 -0700 Subject: [PATCH 102/107] Add more shortcut fusion tests for `_.flow` and `_.flowRight`. --- test/test.js | 77 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/test/test.js b/test/test.js index dd86c936e8..1a1685cf36 100644 --- a/test/test.js +++ b/test/test.js @@ -2248,46 +2248,59 @@ notStrictEqual(combined, _.identity); }); - test('`_.' + methodName + '` should support shortcut fusion', 6, function() { + test('`_.' + methodName + '` should support shortcut fusion', 12, function() { var filterCount, - mapCount, - filter = _.filter, - map = _.map, - take = _.take; + mapCount; - _.filter = _.curry(_.rearg(_.ary(_.filter, 2), 1, 0), 2); - _.map = _.curry(_.rearg(_.ary(_.map, 2), 1, 0), 2); - _.take = _.curry(_.rearg(_.ary(_.take, 2), 1, 0), 2); + var iteratee = function(value) { + mapCount++; + return value * value; + }; - var filter2 = _.filter(function(value) { filterCount++; return value % 2 == 0; }), - map2 = _.map(function(value) { mapCount++; return value * value; }), - take2 = _.take(2); + var predicate = function(value) { + filterCount++; + return value % 2 == 0; + }; _.times(2, function(index) { - var fn = index ? _['_' + methodName] : func; - if (!fn) { - skipTest(3); - return; - } - var combined = isFlow - ? fn(map2, filter2, _.compact, take2) - : fn(take2, _.compact, filter2, map2); + var filter1 = _.filter, + filter2 = _.curry(_.rearg(_.ary(_.filter, 2), 1, 0), 2), + filter3 = (_.filter = index ? filter2 : filter1, filter2(predicate)); - filterCount = mapCount = 0; - deepEqual(combined(_.range(200)), [4, 16]); + var map1 = _.map, + map2 = _.curry(_.rearg(_.ary(_.map, 2), 1, 0), 2), + map3 = (_.map = index ? map2 : map1, map2(iteratee)); - if (!isNpm && WeakMap && WeakMap.name) { - strictEqual(filterCount, 5, 'filterCount'); - strictEqual(mapCount, 5, 'mapCount'); - } - else { - skipTest(2); - } - }); + var take1 = _.take, + take2 = _.curry(_.rearg(_.ary(_.take, 2), 1, 0), 2), + take3 = (_.take = index ? take2 : take1, take2(2)); - _.filter = filter; - _.map = map; - _.take = take; + _.times(2, function(index) { + var fn = index ? _['_' + methodName] : func; + if (!fn) { + skipTest(3); + return; + } + var combined = isFlow + ? fn(map3, filter3, _.compact, take3) + : fn(take3, _.compact, filter3, map3); + + filterCount = mapCount = 0; + deepEqual(combined(_.range(200)), [4, 16]); + + if (!isNpm && WeakMap && WeakMap.name) { + strictEqual(filterCount, 5, 'filterCount'); + strictEqual(mapCount, 5, 'mapCount'); + } + else { + skipTest(2); + } + }); + + _.filter = filter1; + _.map = map1; + _.take = take1; + }); }); test('`_.' + methodName + '` should work with curried functions with placeholders', 1, function() { From d93aa183f3fdbefe73c8b06ae3ecc6bae6416c56 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 29 Jun 2015 21:07:46 -0700 Subject: [PATCH 103/107] Ensure `_.flow` and `_.flowRight` works with `_.first`. [closes #1308] --- lodash.src.js | 14 +++++++------- test/test.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 6aa8d435d2..85641617d7 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1205,7 +1205,7 @@ takeCount = nativeMin(length, this.__takeCount__); if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) { - return baseWrapperValue(isRight ? array.reverse() : array, this.__actions__); + return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__); } var result = []; @@ -3433,7 +3433,7 @@ throw new TypeError(FUNC_ERROR_TEXT); } if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { - wrapper = new LodashWrapper([]); + wrapper = new LodashWrapper([], true); } } index = wrapper ? -1 : length; @@ -12428,7 +12428,9 @@ isLazy = useLazy = false; } var interceptor = function(value) { - return lodashFunc.apply(undefined, arrayPush([value], args)); + return (retUnwrapped && chainAll) + ? lodashFunc(value, 1)[0] + : lodashFunc.apply(undefined, arrayPush([value], args)); }; var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined }, @@ -12442,12 +12444,10 @@ } return lodashFunc.call(undefined, this.value())[0]; } - if (useLazy) { + if (!retUnwrapped && useLazy) { value = onlyLazy ? value : new LazyWrapper(this); var result = func.apply(value, args); - if (!retUnwrapped) { - result.__actions__.push(action); - } + result.__actions__.push(action); return new LodashWrapper(result, chainAll); } return this.thru(interceptor); diff --git a/test/test.js b/test/test.js index 1a1685cf36..327c858099 100644 --- a/test/test.js +++ b/test/test.js @@ -2248,6 +2248,16 @@ notStrictEqual(combined, _.identity); }); + test('`_.' + methodName + '` should work with a curried function and `_.first`', 1, function() { + var curried = _.curry(_.identity); + + var combined = isFlow + ? func(_.first, curried) + : func(curried, _.first); + + strictEqual(combined([1]), 1); + }); + test('`_.' + methodName + '` should support shortcut fusion', 12, function() { var filterCount, mapCount; @@ -4796,6 +4806,16 @@ } }); + test('should not execute immediately when explicitly chaining', 1, function() { + if (!isNpm) { + var wrapped = _(array).chain().first(); + strictEqual(wrapped.__wrapped__, array); + } + else { + skipTest(); + } + }); + test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { var array = _.range(1, LARGE_ARRAY_SIZE + 1); @@ -9261,6 +9281,16 @@ } }); + test('should not execute immediately when explicitly chaining', 1, function() { + if (!isNpm) { + var wrapped = _(array).chain().last(); + strictEqual(wrapped.__wrapped__, array); + } + else { + skipTest(); + } + }); + test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { var array = _.range(1, LARGE_ARRAY_SIZE + 1), From 8ba161463bfabd9b8bf0f00f268b7adc63fec01e Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 29 Jun 2015 22:44:30 -0700 Subject: [PATCH 104/107] Clarify implicit chaining in the `lodash` docs. [ci skip] --- lodash.src.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 85641617d7..73e985bd65 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -848,11 +848,11 @@ /** * Creates a `lodash` object which wraps `value` to enable implicit chaining. * Methods that operate on and return arrays, collections, and functions can - * be chained together. Methods that return a boolean or single value will - * automatically end the chain returning the unwrapped value. Explicit chaining - * may be enabled using `_.chain`. The execution of chained methods is lazy, - * that is, execution is deferred until `_#value` is implicitly or explicitly - * called. + * be chained together. Methods that retrieve a single value or may return a + * primitive value will automatically end the chain returning the unwrapped + * value. Explicit chaining may be enabled using `_.chain`. The execution of + * chained methods is lazy, that is, execution is deferred until `_#value` + * is implicitly or explicitly called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut * fusion is an optimization strategy which merge iteratee calls; this can help From e620d194221186188b5168a8171cc329f3646a17 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 29 Jun 2015 23:18:08 -0700 Subject: [PATCH 105/107] Disable JIT for ringo runs in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3bf0cfe175..33f4238c56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ env: - BIN="phantomjs" - BIN="rhino" OPTION="-opt -1" - BIN="rhino" OPTION="-opt -1 -require" - - BIN="ringo" + - BIN="ringo" OPTION="-o -1" matrix: include: - node_js: "iojs" From 7351c0b0b941e7faa450a7f53713659b3ebe76dc Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 27 Jun 2015 21:49:18 -0700 Subject: [PATCH 106/107] Rebuild lodash and docs. --- doc/README.md | 768 +++++++++++++++++------------ lodash.js | 1278 +++++++++++++++++++++++++++---------------------- lodash.min.js | 189 ++++---- lodash.src.js | 4 +- 4 files changed, 1261 insertions(+), 978 deletions(-) diff --git a/doc/README.md b/doc/README.md index 86bf6f6a74..c7a94e15a4 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,4 +1,4 @@ -# lodash v3.9.3 +# lodash v3.10.0 @@ -59,6 +59,7 @@ * `_.thru` * `_.prototype.chain` * `_.prototype.commit` +* `_.prototype.concat` * `_.prototype.plant` * `_.prototype.reverse` * `_.prototype.run` -> `value` @@ -140,6 +141,7 @@ * `_.flow` * `_.flowRight` * `_.memoize` +* `_.modArgs` * `_.negate` * `_.once` * `_.partial` @@ -192,8 +194,11 @@ ## `Math` * `_.add` +* `_.ceil` +* `_.floor` * `_.max` * `_.min` +* `_.round` * `_.sum` @@ -212,6 +217,7 @@ * `_.assign` * `_.create` * `_.defaults` +* `_.defaultsDeep` * `_.extend` -> `assign` * `_.findKey` * `_.findLastKey` @@ -304,10 +310,8 @@ ## `Properties` * `_.VERSION` * `_.support` -* `_.support.argsTag` * `_.support.enumErrorProps` * `_.support.enumPrototypes` -* `_.support.nodeTag` * `_.support.nonEnumShadows` * `_.support.ownLast` * `_.support.spliceObjects` @@ -332,7 +336,7 @@ ### `_.chunk(array, [size=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4651 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.chunk "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4623 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.chunk "See the npm package") 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 @@ -360,7 +364,7 @@ _.chunk(['a', 'b', 'c', 'd'], 3); ### `_.compact(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4682 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.compact "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4654 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.compact "See the npm package") Creates an array with all falsey values removed. The values `false`, `null`, `0`, `""`, `undefined`, and `NaN` are falsey. @@ -383,10 +387,10 @@ _.compact([0, 1, false, 2, '', 3]); ### `_.difference(array, [values])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4713 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.difference "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4685 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.difference "See the npm package") Creates an array of unique `array` values not included in the other -provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons. #### Arguments @@ -408,7 +412,7 @@ _.difference([1, 2, 3], [4, 2]); ### `_.drop(array, [n=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4743 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.drop "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4715 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.drop "See the npm package") Creates a slice of `array` with `n` elements dropped from the beginning. @@ -440,7 +444,7 @@ _.drop([1, 2, 3], 0); ### `_.dropRight(array, [n=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4778 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.dropright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4750 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.dropright "See the npm package") Creates a slice of `array` with `n` elements dropped from the end. @@ -472,7 +476,7 @@ _.dropRight([1, 2, 3], 0); ### `_.dropRightWhile(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4839 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.droprightwhile "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4811 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.droprightwhile "See the npm package") Creates a slice of `array` excluding elements dropped from the end. Elements are dropped until `predicate` returns falsey. The predicate is @@ -532,7 +536,7 @@ _.pluck(_.dropRightWhile(users, 'active'), 'user'); ### `_.dropWhile(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4894 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.dropwhile "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4866 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.dropwhile "See the npm package") Creates a slice of `array` excluding elements dropped from the beginning. Elements are dropped until `predicate` returns falsey. The predicate is @@ -592,7 +596,7 @@ _.pluck(_.dropWhile(users, 'active'), 'user'); ### `_.fill(array, value, [start=0], [end=array.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4928 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.fill "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4900 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.fill "See the npm package") Fills elements of `array` with `value` from `start` up to, but not including, `end`. @@ -630,7 +634,7 @@ _.fill([4, 6, 8], '*', 1, 2); ### `_.findIndex(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L4988 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findindex "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L4960 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findindex "See the npm package") This method is like `_.find` except that it returns the index of the first element `predicate` returns truthy for instead of the element itself. @@ -689,7 +693,7 @@ _.findIndex(users, 'active'); ### `_.findLastIndex(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5038 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findlastindex "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5010 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findlastindex "See the npm package") This method is like `_.findIndex` except that it iterates over elements of `collection` from right to left. @@ -748,7 +752,7 @@ _.findLastIndex(users, 'active'); ### `_.first(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5057 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.first "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5029 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.first "See the npm package") Gets the first element of `array`. @@ -776,7 +780,7 @@ _.first([]); ### `_.flatten(array, [isDeep])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5081 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flatten "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5053 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flatten "See the npm package") Flattens a nested array. If `isDeep` is `true` the array is recursively flattened, otherwise it is only flattened a single level. @@ -804,7 +808,7 @@ _.flatten([1, [2, 3, [4]]], true); ### `_.flattenDeep(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5102 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flattendeep "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5074 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flattendeep "See the npm package") Recursively flattens a nested array. @@ -826,10 +830,10 @@ _.flattenDeep([1, [2, 3, [4]]]); ### `_.indexOf(array, value, [fromIndex=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5135 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.indexof "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5107 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.indexof "See the npm package") Gets the index at which the first occurrence of `value` is found in `array` -using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons. If `fromIndex` is negative, it is used as the offset from the end of `array`. If `array` is sorted providing `true` for `fromIndex` performs a faster binary search. @@ -862,7 +866,7 @@ _.indexOf([1, 1, 2, 2], 2, true); ### `_.initial(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5167 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.initial "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5138 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.initial "See the npm package") Gets all but the last element of `array`. @@ -884,10 +888,10 @@ _.initial([1, 2, 3]); ### `_.intersection([arrays])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5185 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.intersection "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5156 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.intersection "See the npm package") Creates an array of unique values that are included in all of the provided -arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons. #### Arguments @@ -908,7 +912,7 @@ _.intersection([1, 2], [4, 2], [2, 1]); ### `_.last(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5235 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.last "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5206 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.last "See the npm package") Gets the last element of `array`. @@ -930,7 +934,7 @@ _.last([1, 2, 3]); ### `_.lastIndexOf(array, value, [fromIndex=array.length-1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5265 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.lastindexof "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5236 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.lastindexof "See the npm package") This method is like `_.indexOf` except that it iterates over elements of `array` from right to left. @@ -963,10 +967,10 @@ _.lastIndexOf([1, 1, 2, 2], 2, true); ### `_.pull(array, [values])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5313 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pull "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5284 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pull "See the npm package") Removes all provided values from `array` using -[`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +[`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons.

@@ -994,7 +998,7 @@ console.log(array); ### `_.pullAt(array, [indexes])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5360 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pullat "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5331 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pullat "See the npm package") Removes elements from `array` corresponding to the given indexes and returns an array of the removed elements. Indexes may be specified as an array of @@ -1028,7 +1032,7 @@ console.log(evens); ### `_.remove(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5407 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.remove "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5378 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.remove "See the npm package") Removes all elements from `array` that `predicate` returns truthy for and returns an array of the removed elements. The predicate is bound to @@ -1079,7 +1083,7 @@ console.log(evens); ### `_.rest(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5442 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.rest "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5413 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.rest "See the npm package") Gets all but the first element of `array`. @@ -1104,7 +1108,7 @@ _.rest([1, 2, 3]); ### `_.slice(array, [start=0], [end=array.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5460 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.slice "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5431 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.slice "See the npm package") Creates a slice of `array` from `start` up to, but not including, `end`.
@@ -1127,7 +1131,7 @@ lists in IE < 9 and to ensure dense arrays are returned. ### `_.sortedIndex(array, value, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5520 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortedindex "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5491 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortedindex "See the npm package") Uses a binary search to determine the lowest index at which `value` should be inserted into `array` in order to maintain its sort order. If an iteratee @@ -1186,7 +1190,7 @@ _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); ### `_.sortedLastIndex(array, value, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5542 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortedlastindex "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5513 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortedlastindex "See the npm package") This method is like `_.sortedIndex` except that it returns the highest index at which `value` should be inserted into `array` in order to @@ -1214,7 +1218,7 @@ _.sortedLastIndex([4, 4, 5, 5], 5); ### `_.take(array, [n=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5568 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.take "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5539 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.take "See the npm package") Creates a slice of `array` with `n` elements taken from the beginning. @@ -1246,7 +1250,7 @@ _.take([1, 2, 3], 0); ### `_.takeRight(array, [n=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5603 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.takeright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5574 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.takeright "See the npm package") Creates a slice of `array` with `n` elements taken from the end. @@ -1278,7 +1282,7 @@ _.takeRight([1, 2, 3], 0); ### `_.takeRightWhile(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5664 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.takerightwhile "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5635 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.takerightwhile "See the npm package") Creates a slice of `array` with elements taken from the end. Elements are taken until `predicate` returns falsey. The predicate is bound to `thisArg` @@ -1338,7 +1342,7 @@ _.pluck(_.takeRightWhile(users, 'active'), 'user'); ### `_.takeWhile(array, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5719 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.takewhile "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5690 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.takewhile "See the npm package") Creates a slice of `array` with elements taken from the beginning. Elements are taken until `predicate` returns falsey. The predicate is bound to @@ -1398,10 +1402,10 @@ _.pluck(_.takeWhile(users, 'active'), 'user'); ### `_.union([arrays])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5740 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.union "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5711 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.union "See the npm package") Creates an array of unique values, in order, from all of the provided arrays -using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons. #### Arguments @@ -1422,10 +1426,10 @@ _.union([1, 2], [4, 2], [2, 1]); ### `_.uniq(array, [isSorted], [iteratee], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5793 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.uniq "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5764 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.uniq "See the npm package") Creates a duplicate-free version of an array, using -[`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +[`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons, in which only the first occurence of each element is kept. Providing `true` for `isSorted` performs a faster search algorithm for sorted arrays. If an iteratee function is provided it is invoked for @@ -1485,7 +1489,7 @@ _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); ### `_.unzip(array)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5830 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.unzip "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5801 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.unzip "See the npm package") This method is like `_.zip` except that it accepts an array of grouped elements and creates an array regrouping the elements to their pre-zip @@ -1512,7 +1516,7 @@ _.unzip(zipped); ### `_.unzipWith(array, [iteratee], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5870 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.unzipwith "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5841 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.unzipwith "See the npm package") This method is like `_.unzip` except that it accepts an iteratee to specify how regrouped values should be combined. The `iteratee` is bound to `thisArg` @@ -1541,10 +1545,10 @@ _.unzipWith(zipped, _.add); ### `_.without(array, [values])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5901 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.without "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5872 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.without "See the npm package") Creates an array excluding all provided values using -[`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +[`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons. #### Arguments @@ -1566,7 +1570,7 @@ _.without([1, 2, 1, 3], 1, 2); ### `_.xor([arrays])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5921 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.xor "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5892 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.xor "See the npm package") Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) of the provided arrays. @@ -1589,7 +1593,7 @@ _.xor([1, 2], [4, 2]); ### `_.zip([arrays])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5951 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.zip "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5922 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.zip "See the npm package") 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 @@ -1613,7 +1617,7 @@ _.zip(['fred', 'barney'], [30, 40], [true, false]); ### `_.zipObject(props, [values=[]])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L5974 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.zipobject "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5945 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.zipobject "See the npm package") The inverse of `_.pairs`; this method returns an object composed from arrays of property names and values. Provide either a single two dimensional array, @@ -1645,7 +1649,7 @@ _.zipObject(['fred', 'barney'], [30, 40]); ### `_.zipWith([arrays], [iteratee], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6010 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.zipwith "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L5981 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.zipwith "See the npm package") This method is like `_.zip` except that it accepts an iteratee to specify how grouped values should be combined. The `iteratee` is bound to `thisArg` @@ -1677,20 +1681,21 @@ _.zipWith([1, 2], [10, 20], [100, 200], _.add); ### `_(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L957 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L944 "View in source") [Ⓣ][1] Creates a `lodash` object which wraps `value` to enable implicit chaining. Methods that operate on and return arrays, collections, and functions can -be chained together. Methods that return a boolean or single value will -automatically end the chain returning the unwrapped value. Explicit chaining -may be enabled using `_.chain`. The execution of chained methods is lazy, -that is, execution is deferred until `_#value` is implicitly or explicitly -called. +be chained together. Methods that retrieve a single value or may return a +primitive value will automatically end the chain returning the unwrapped +value. Explicit chaining may be enabled using `_.chain`. The execution of +chained methods is lazy, that is, execution is deferred until `_#value` +is implicitly or explicitly called.

Lazy evaluation allows several methods to support shortcut fusion. Shortcut -fusion is an optimization that merges iteratees to avoid creating intermediate -arrays and reduce the number of iteratee executions. +fusion is an optimization strategy which merge iteratee calls; this can help +to avoid the creation of intermediate data structures and greatly reduce the +number of iteratee executions.

Chaining is supported in custom builds as long as the `_#value` method is @@ -1719,37 +1724,38 @@ and `where` The chainable wrapper methods are:
`after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, -`countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, -`difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, -`filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, -`forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, -`groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, -`keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, -`memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`, -`pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`, -`property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, -`reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, -`slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, -`take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, -`thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, -`unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`, -`wrap`, `xor`, `zip`, `zipObject`, `zipWith` +`countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, +`defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, +`dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, +`forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, +`functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, +`invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, +`matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, +`modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, +`partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, +`pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, +`reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, +`sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, +`takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, +`transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, +`valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith`

The wrapper methods that are **not** chainable by default are:
-`add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, -`endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, -`findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`, -`gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, -`isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, -`isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, -`isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, -`isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`, -`max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`, -`parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, -`runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, -`sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`, -`trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words` +`add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, +`deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, +`findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, +`floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, +`inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, +`isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, +`isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, +`isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, +`last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, +`now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, +`reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, +`snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, +`startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, +`unescape`, `uniqueId`, `value`, and `words`

The wrapper method `sample` will return a wrapped value when `n` is provided, @@ -1789,7 +1795,7 @@ _.isArray(squares.value()); ### `_.chain(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6053 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6024 "View in source") [Ⓣ][1] Creates a `lodash` object that wraps `value` with explicit method chaining enabled. @@ -1824,7 +1830,7 @@ var youngest = _.chain(users) ### `_.tap(value, interceptor, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6082 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6053 "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 @@ -1856,7 +1862,7 @@ _([1, 2, 3]) ### `_.thru(value, interceptor, [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6108 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6079 "View in source") [Ⓣ][1] This method is like `_.tap` except that it returns the result of `interceptor`. @@ -1886,7 +1892,7 @@ _(' abc ') ### `_.prototype.chain()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6137 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6108 "View in source") [Ⓣ][1] Enables explicit method chaining on the wrapper object. @@ -1918,7 +1924,7 @@ _(users).chain() ### `_.prototype.commit()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6166 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6137 "View in source") [Ⓣ][1] Executes the chained sequence and returns the wrapped result. @@ -1928,16 +1934,16 @@ Executes the chained sequence and returns the wrapped result. #### Example ```js var array = [1, 2]; -var wrapper = _(array).push(3); +var wrapped = _(array).push(3); console.log(array); // => [1, 2] -wrapper = wrapper.commit(); +wrapped = wrapped.commit(); console.log(array); // => [1, 2, 3] -wrapper.last(); +wrapped.last(); // => 3 console.log(array); @@ -1949,8 +1955,37 @@ console.log(array); +### `_.prototype.concat([values])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6161 "View in source") [Ⓣ][1] + +Creates a new array joining a wrapped array with any additional arrays +and/or values. + +#### Arguments +1. `[values]` *(...*)*: The values to concatenate. + +#### Returns +*(Array)*: Returns the new concatenated array. + +#### Example +```js +var array = [1]; +var wrapped = _(array).concat(2, [3], [[4]]); + +console.log(wrapped.value()); +// => [1, 2, 3, [4]] + +console.log(array); +// => [1] +``` +* * * + + + + + ### `_.prototype.plant()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6193 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6191 "View in source") [Ⓣ][1] Creates a clone of the chained sequence planting `value` as the wrapped value. @@ -1960,17 +1995,17 @@ Creates a clone of the chained sequence planting `value` as the wrapped value. #### Example ```js var array = [1, 2]; -var wrapper = _(array).map(function(value) { +var wrapped = _(array).map(function(value) { return Math.pow(value, 2); }); var other = [3, 4]; -var otherWrapper = wrapper.plant(other); +var otherWrapped = wrapped.plant(other); -otherWrapper.value(); +otherWrapped.value(); // => [9, 16] -wrapper.value(); +wrapped.value(); // => [1, 4] ``` * * * @@ -1980,7 +2015,7 @@ wrapper.value(); ### `_.prototype.reverse()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6231 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6229 "View in source") [Ⓣ][1] Reverses the wrapped array so the first element becomes the last, the second element becomes the second to last, and so on. @@ -2008,7 +2043,7 @@ console.log(array); ### `_.prototype.toString()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6256 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6259 "View in source") [Ⓣ][1] Produces the result of coercing the unwrapped value to a string. @@ -2027,7 +2062,7 @@ _([1, 2, 3]).toString(); ### `_.prototype.value()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6273 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6276 "View in source") [Ⓣ][1] Executes the chained sequence to extract the unwrapped value. @@ -2055,7 +2090,7 @@ _([1, 2, 3]).value(); ### `_.at(collection, [props])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6299 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.at "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6302 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.at "See the npm package") Creates an array of elements corresponding to the given keys, or indexes, of `collection`. Keys may be specified as individual arguments or as arrays @@ -2083,7 +2118,7 @@ _.at(['barney', 'fred', 'pebbles'], 0, 2); ### `_.countBy(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6347 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.countby "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6350 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.countby "See the npm package") Creates an object composed of keys generated from the results of running each element of `collection` through `iteratee`. The corresponding value @@ -2135,7 +2170,7 @@ _.countBy(['one', 'two', 'three'], 'length'); ### `_.every(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6399 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.every "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6402 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.every "See the npm package") Checks if `predicate` returns truthy for **all** elements of `collection`. The predicate is bound to `thisArg` and invoked with three arguments:
@@ -2196,7 +2231,7 @@ _.every(users, 'active'); ### `_.filter(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6459 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.filter "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6462 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.filter "See the npm package") Iterates over elements of `collection`, returning an array of all elements `predicate` returns truthy for. The predicate is bound to `thisArg` and @@ -2258,7 +2293,7 @@ _.pluck(_.filter(users, 'active'), 'user'); ### `_.find(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6515 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.find "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6518 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.find "See the npm package") Iterates over elements of `collection`, returning the first element `predicate` returns truthy for. The predicate is bound to `thisArg` and @@ -2321,7 +2356,7 @@ _.result(_.find(users, 'active'), 'user'); ### `_.findLast(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6536 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findlast "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6539 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findlast "See the npm package") This method is like `_.find` except that it iterates over elements of `collection` from right to left. @@ -2348,7 +2383,7 @@ _.findLast([1, 2, 3, 4], function(n) { ### `_.findWhere(collection, source)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6567 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findwhere "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6570 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findwhere "See the npm package") Performs a deep comparison between each element in `collection` and the source object, returning the first element that has equivalent property @@ -2387,7 +2422,7 @@ _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user'); ### `_.forEach(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6601 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.foreach "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6604 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.foreach "See the npm package") Iterates over elements of `collection` invoking `iteratee` for each element. The `iteratee` is bound to `thisArg` and invoked with three arguments:
@@ -2429,7 +2464,7 @@ _.forEach({ 'a': 1, 'b': 2 }, function(n, key) { ### `_.forEachRight(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6622 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.foreachright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6625 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.foreachright "See the npm package") This method is like `_.forEach` except that it iterates over elements of `collection` from right to left. @@ -2459,7 +2494,7 @@ _([1, 2]).forEachRight(function(n) { ### `_.groupBy(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6666 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.groupby "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6669 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.groupby "See the npm package") Creates an object composed of keys generated from the results of running each element of `collection` through `iteratee`. The corresponding value @@ -2512,10 +2547,10 @@ _.groupBy(['one', 'two', 'three'], 'length'); ### `_.includes(collection, target, [fromIndex=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6703 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.includes "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6706 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.includes "See the npm package") Checks if `value` is in `collection` using -[`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) +[`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) for equality comparisons. If `fromIndex` is negative, it is used as the offset from the end of `collection`. @@ -2551,7 +2586,7 @@ _.includes('pebbles', 'eb'); ### `_.indexBy(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6768 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.indexby "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6768 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.indexby "See the npm package") Creates an object composed of keys generated from the results of running each element of `collection` through `iteratee`. The corresponding value @@ -2608,7 +2643,7 @@ _.indexBy(keyData, function(object) { ### `_.invoke(collection, path, [args])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6794 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.invoke "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6794 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.invoke "See the npm package") Invokes the method at `path` of each element in `collection`, returning an array of the results of each invoked method. Any additional arguments @@ -2638,7 +2673,7 @@ _.invoke([123, 456], String.prototype.split, ''); ### `_.map(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6863 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.map "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6863 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.map "See the npm package") Creates an array of values by running each element in `collection` through `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three @@ -2709,7 +2744,7 @@ _.map(users, 'user'); ### `_.partition(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6928 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.partition "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6928 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.partition "See the npm package") Creates an array of elements split into two groups, the first of which contains elements `predicate` returns truthy for, while the second of which @@ -2779,7 +2814,7 @@ _.map(_.partition(users, 'active'), mapper); ### `_.pluck(collection, path)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6955 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pluck "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6955 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pluck "See the npm package") Gets the property value of `path` from all elements in `collection`. @@ -2811,7 +2846,7 @@ _.pluck(userIndex, 'age'); ### `_.reduce(collection, [iteratee=_.identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L6995 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.reduce "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L6996 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.reduce "See the npm package") Reduces `collection` to a value which is the accumulated result of running each element in `collection` through `iteratee`, where each successive @@ -2826,7 +2861,8 @@ Many lodash methods are guarded to work as iteratees for methods like

The guarded methods are:
-`assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` +`assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`, +and `sortByOrder` #### Aliases *_.foldl, _.inject* @@ -2860,7 +2896,7 @@ _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) { ### `_.reduceRight(collection, [iteratee=_.identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7019 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.reduceright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7020 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.reduceright "See the npm package") This method is like `_.reduce` except that it iterates over elements of `collection` from right to left. @@ -2893,7 +2929,7 @@ _.reduceRight(array, function(flattened, other) { ### `_.reject(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7057 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.reject "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7058 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.reject "See the npm package") The opposite of `_.filter`; this method returns the elements of `collection` that `predicate` does **not** return truthy for. @@ -2937,7 +2973,7 @@ _.pluck(_.reject(users, 'active'), 'user'); ### `_.sample(collection, [n])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7083 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sample "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7084 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sample "See the npm package") Gets a random element or `n` random elements from a collection. @@ -2963,7 +2999,7 @@ _.sample([1, 2, 3, 4], 2); ### `_.shuffle(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7120 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.shuffle "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7121 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.shuffle "See the npm package") Creates an array of shuffled values, using a version of the [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). @@ -2986,7 +3022,7 @@ _.shuffle([1, 2, 3, 4]); ### `_.size(collection)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7144 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.size "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7145 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.size "See the npm package") Gets the size of `collection` by returning its length for array-like values or the number of own enumerable properties for objects. @@ -3015,7 +3051,7 @@ _.size('pebbles'); ### `_.some(collection, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7198 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.some "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7199 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.some "See the npm package") Checks if `predicate` returns truthy for **any** element of `collection`. The function returns as soon as it finds a passing value and does not iterate @@ -3077,7 +3113,7 @@ _.some(users, 'active'); ### `_.sortBy(collection, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7257 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortby "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7258 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortby "See the npm package") Creates an array of elements, sorted in ascending order by the results of running each element in a collection through `iteratee`. This method performs @@ -3136,7 +3172,7 @@ _.pluck(_.sortBy(users, 'user'), 'user'); ### `_.sortByAll(collection, iteratees)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7308 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortbyall "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7309 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortbyall "See the npm package") This method is like `_.sortBy` except that it can sort by multiple iteratees or property names. @@ -3180,13 +3216,13 @@ _.map(_.sortByAll(users, 'user', function(chr) { -### `_.sortByOrder(collection, iteratees, orders)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7353 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortbyorder "See the npm package") +### `_.sortByOrder(collection, iteratees, [orders])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7354 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sortbyorder "See the npm package") This method is like `_.sortByAll` except that it allows specifying the -sort orders of the iteratees to sort by. A truthy value in `orders` will -sort the corresponding property name in ascending order while a falsey -value will sort it in descending order. +sort orders of the iteratees to sort by. If `orders` is unspecified, all +values are sorted in ascending order. Otherwise, a value is sorted in +ascending order if its corresponding order is "asc", and descending if "desc".

If a property name is provided for an iteratee the created `_.property` @@ -3200,7 +3236,7 @@ object, else `false`. #### Arguments 1. `collection` *(Array|Object|string)*: The collection to iterate over. 2. `iteratees` *(Function[]|Object[]|string[])*: The iteratees to sort by. -3. `orders` *(boolean[])*: The sort orders of `iteratees`. +3. `[orders]` *(boolean[])*: The sort orders of `iteratees`. #### Returns *(Array)*: Returns the new sorted array. @@ -3215,7 +3251,7 @@ var users = [ ]; // sort by `user` in ascending order and by `age` in descending order -_.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values); +_.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values); // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] ``` * * * @@ -3225,7 +3261,7 @@ _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values); ### `_.where(collection, source)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7398 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.where "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7399 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.where "See the npm package") Performs a deep comparison between each element in `collection` and the source object, returning an array of all elements that have equivalent @@ -3270,7 +3306,7 @@ _.pluck(_.where(users, { 'pets': ['dino'] }), 'user'); ### `_.now` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7418 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.now "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7419 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.now "See the npm package") Gets the number of milliseconds that have elapsed since the Unix epoch (1 January 1970 00:00:00 UTC). @@ -3295,7 +3331,7 @@ _.defer(function(stamp) { ### `_.after(n, func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7447 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.after "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7448 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.after "See the npm package") The opposite of `_.before`; this method creates a function that invokes `func` once it is called `n` or more times. @@ -3327,7 +3363,7 @@ _.forEach(saves, function(type) { ### `_.ary(func, [n=func.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7481 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.ary "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7482 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.ary "See the npm package") Creates a function that accepts up to `n` arguments ignoring any additional arguments. @@ -3351,7 +3387,7 @@ _.map(['6', '8', '10'], _.ary(parseInt, 1)); ### `_.before(n, func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7505 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.before "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7506 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.before "See the npm package") Creates a function that invokes `func`, with the `this` binding and arguments of the created function, while it is called less than `n` times. Subsequent @@ -3376,7 +3412,7 @@ jQuery('#add').on('click', _.before(5, addContactToList)); ### `_.bind(func, thisArg, [partials])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7562 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.bind "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7563 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.bind "See the npm package") Creates a function that invokes `func` with the `this` binding of `thisArg` and prepends any additional `_.bind` arguments to those provided to the @@ -3422,7 +3458,7 @@ bound('hi'); ### `_.bindAll(object, [methodNames])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7599 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.bindall "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7600 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.bindall "See the npm package") Binds methods of an object to the object itself, overwriting the existing method. Method names may be specified as individual arguments or as arrays @@ -3459,7 +3495,7 @@ jQuery('#docs').on('click', view.onClick); ### `_.bindKey(object, key, [partials])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7656 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.bindkey "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7657 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.bindkey "See the npm package") Creates a function that invokes the method at `object[key]` and prepends any additional `_.bindKey` arguments to those provided to the bound function. @@ -3514,7 +3550,7 @@ bound('hi'); ### `_.curry(func, [arity=func.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7705 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.curry "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7706 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.curry "See the npm package") Creates a function that accepts one or more arguments of `func` that when called either invokes `func` returning its result, if all `func` arguments @@ -3564,7 +3600,7 @@ curried(1)(_, 3)(2); ### `_.curryRight(func, [arity=func.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7744 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.curryright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7745 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.curryright "See the npm package") This method is like `_.curry` except that arguments are applied to `func` in the manner of `_.partialRight` instead of `_.partial`. @@ -3611,7 +3647,7 @@ curried(3)(1, _)(2); ### `_.debounce(func, [wait=0], [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7809 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.debounce "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7810 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.debounce "See the npm package") Creates a debounced function that delays invoking `func` until after `wait` milliseconds have elapsed since the last time the debounced function was @@ -3682,7 +3718,7 @@ delete models.todo; ### `_.defer(func, [args])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7940 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.defer "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7935 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.defer "See the npm package") Defers invoking the `func` until the current call stack has cleared. Any additional arguments are provided to `func` when it is invoked. @@ -3708,7 +3744,7 @@ _.defer(function(text) { ### `_.delay(func, wait, [args])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7962 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.delay "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7957 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.delay "See the npm package") Invokes `func` after `wait` milliseconds. Any additional arguments are provided to `func` when it is invoked. @@ -3735,7 +3771,7 @@ _.delay(function(text) { ### `_.flow([funcs])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L7986 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flow "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L7981 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flow "See the npm package") Creates a function that returns the result of invoking the provided functions with the `this` binding of the created function, where each @@ -3764,7 +3800,7 @@ addSquare(1, 2); ### `_.flowRight([funcs])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8008 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flowright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8003 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.flowright "See the npm package") This method is like `_.flow` except that it creates a function that invokes the provided functions from right to left. @@ -3795,7 +3831,7 @@ addSquare(1, 2); ### `_.memoize(func, [resolver])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8061 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.memoize "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8056 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.memoize "See the npm package") 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 @@ -3807,7 +3843,7 @@ function.
**Note:** The cache is exposed as the `cache` property on the memoized function. Its creation may be customized by replacing the `_.memoize.Cache` -constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) +constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) method interface of `get`, `has`, and `set`. #### Arguments @@ -3855,8 +3891,47 @@ identity(other); +### `_.modArgs(func, [transforms])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8107 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.modargs "See the npm package") + +Creates a function that runs each argument through a corresponding +transform function. + +#### Arguments +1. `func` *(Function)*: The function to wrap. +2. `[transforms]` *(...(Function|Function[])*: The functions to transform arguments, specified as individual functions or arrays of functions. + +#### Returns +*(Function)*: Returns the new function. + +#### Example +```js +function doubled(n) { + return n * 2; +} + +function square(n) { + return n * n; +} + +var modded = _.modArgs(function(x, y) { + return [x, y]; +}, square, doubled); + +modded(1, 2); +// => [1, 4] + +modded(5, 10); +// => [25, 20] +``` +* * * + + + + + ### `_.negate(predicate)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8100 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.negate "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8141 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.negate "See the npm package") Creates a function that negates the result of the predicate `func`. The `func` predicate is invoked with the `this` binding and arguments of the @@ -3884,7 +3959,7 @@ _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); ### `_.once(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8126 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.once "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8167 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.once "See the npm package") 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 @@ -3910,7 +3985,7 @@ initialize(); ### `_.partial(func, [partials])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8162 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.partial "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8203 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.partial "See the npm package") Creates a function that invokes `func` with `partial` arguments prepended to those provided to the new function. This method is like `_.bind` except @@ -3953,7 +4028,7 @@ greetFred('hi'); ### `_.partialRight(func, [partials])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8195 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.partialright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8236 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.partialright "See the npm package") This method is like `_.partial` except that partially applied arguments are appended to those provided to the new function. @@ -3995,7 +4070,7 @@ sayHelloTo('fred'); ### `_.rearg(func, indexes)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8225 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.rearg "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8266 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.rearg "See the npm package") Creates a function that invokes `func` with arguments arranged according to the specified indexes where the argument value at the first index is @@ -4031,7 +4106,7 @@ map(function(n) { ### `_.restParam(func, [start=func.length-1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8251 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.restparam "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8292 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.restparam "See the npm package") Creates a function that invokes `func` with the `this` binding of the created function and arguments from `start` and beyond provided as an array. @@ -4063,7 +4138,7 @@ say('hello', 'fred', 'barney', 'pebbles'); ### `_.spread(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8311 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.spread "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8352 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.spread "See the npm package") Creates a function that invokes `func` with the `this` binding of the created function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3). @@ -4104,7 +4179,7 @@ numbers.then(_.spread(function(x, y) { ### `_.throttle(func, [wait=0], [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8359 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.throttle "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8400 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.throttle "See the npm package") Creates a throttled function that only invokes `func` at most once per every `wait` milliseconds. The throttled function comes with a `cancel` @@ -4152,7 +4227,7 @@ jQuery(window).on('popstate', throttled.cancel); ### `_.wrap(value, wrapper)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8399 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.wrap "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8437 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.wrap "See the npm package") Creates a function that provides `value` to the wrapper function as its first argument. Any additional arguments provided to the function are @@ -4188,7 +4263,7 @@ p('fred, barney, & pebbles'); ### `_.clone(value, [isDeep], [customizer], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8457 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.clone "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8495 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.clone "See the npm package") 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 @@ -4249,7 +4324,7 @@ el.childNodes.length; ### `_.cloneDeep(value, [customizer], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8516 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.clonedeep "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8554 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.clonedeep "See the npm package") Creates a deep clone of `value`. If `customizer` is provided it is invoked to produce the cloned values. If `customizer` returns `undefined` cloning @@ -4304,7 +4379,7 @@ el.childNodes.length; ### `_.gt(value, other)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8542 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.gt "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8580 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.gt "See the npm package") Checks if `value` is greater than `other`. @@ -4333,7 +4408,7 @@ _.gt(1, 3); ### `_.gte(value, other)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8566 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.gte "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8604 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.gte "See the npm package") Checks if `value` is greater than or equal to `other`. @@ -4362,7 +4437,7 @@ _.gte(1, 3); ### `_.isArguments(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8586 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isarguments "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8624 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isarguments "See the npm package") Checks if `value` is classified as an `arguments` object. @@ -4387,7 +4462,7 @@ _.isArguments([1, 2, 3]); ### `_.isArray(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8613 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isarray "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8645 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isarray "See the npm package") Checks if `value` is classified as an `Array` object. @@ -4412,7 +4487,7 @@ _.isArray(function() { return arguments; }()); ### `_.isBoolean(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8633 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isboolean "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8665 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isboolean "See the npm package") Checks if `value` is classified as a boolean primitive or object. @@ -4437,7 +4512,7 @@ _.isBoolean(null); ### `_.isDate(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8653 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isdate "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8685 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isdate "See the npm package") Checks if `value` is classified as a `Date` object. @@ -4462,7 +4537,7 @@ _.isDate('Mon April 23 2012'); ### `_.isElement(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8673 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.iselement "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8705 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.iselement "See the npm package") Checks if `value` is a DOM element. @@ -4487,7 +4562,7 @@ _.isElement(''); ### `_.isEmpty(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8711 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isempty "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8736 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isempty "See the npm package") Checks if `value` is empty. A value is considered empty unless it is an `arguments` object, array, string, or jQuery-like collection with a length @@ -4523,7 +4598,7 @@ _.isEmpty({ 'a': 1 }); ### `_.isEqual(value, other, [customizer], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8766 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isequal "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8791 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isequal "See the npm package") Performs a deep comparison between two values to determine if they are equivalent. If `customizer` is provided it is invoked to compare values. @@ -4579,7 +4654,7 @@ _.isEqual(array, other, function(value, other) { ### `_.isError(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8789 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.iserror "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8814 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.iserror "See the npm package") Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, `SyntaxError`, `TypeError`, or `URIError` object. @@ -4605,12 +4680,12 @@ _.isError(Error); ### `_.isFinite(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8820 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isfinite "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8845 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isfinite "See the npm package") Checks if `value` is a finite primitive number.

-**Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). +**Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite). #### Arguments 1. `value` *(*)*: The value to check. @@ -4642,7 +4717,7 @@ _.isFinite(Infinity); ### `_.isFunction(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8840 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isfunction "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8865 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isfunction "See the npm package") Checks if `value` is classified as a `Function` object. @@ -4667,7 +4742,7 @@ _.isFunction(/abc/); ### `_.isMatch(object, source, [customizer], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8913 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.ismatch "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8938 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.ismatch "See the npm package") Performs a deep comparison between `object` and `source` to determine if `object` contains equivalent property values. If `customizer` is provided @@ -4716,7 +4791,7 @@ _.isMatch(object, source, function(value, other) { ### `_.isNaN(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8943 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnan "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8968 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnan "See the npm package") Checks if `value` is `NaN`.
@@ -4751,7 +4826,7 @@ _.isNaN(undefined); ### `_.isNative(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8965 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnative "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8990 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnative "See the npm package") Checks if `value` is a native function. @@ -4776,7 +4851,7 @@ _.isNative(_); ### `_.isNull(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8991 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnull "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9016 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnull "See the npm package") Checks if `value` is `null`. @@ -4801,7 +4876,7 @@ _.isNull(void 0); ### `_.isNumber(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9017 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnumber "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9042 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isnumber "See the npm package") Checks if `value` is classified as a `Number` primitive or object.
@@ -4833,7 +4908,7 @@ _.isNumber('8.4'); ### `_.isObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L8867 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isobject "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L8892 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isobject "See the npm package") Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) @@ -4862,7 +4937,7 @@ _.isObject(1); ### `_.isPlainObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9051 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isplainobject "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9076 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isplainobject "See the npm package") Checks if `value` is a plain object, that is, an object created by the `Object` constructor or one with a `[[Prototype]]` of `null`. @@ -4902,7 +4977,7 @@ _.isPlainObject(Object.create(null)); ### `_.isRegExp(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9079 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isregexp "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9120 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isregexp "See the npm package") Checks if `value` is classified as a `RegExp` object. @@ -4927,7 +5002,7 @@ _.isRegExp('/abc/'); ### `_.isString(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9099 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isstring "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9140 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isstring "See the npm package") Checks if `value` is classified as a `String` primitive or object. @@ -4952,7 +5027,7 @@ _.isString(1); ### `_.isTypedArray(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9119 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.istypedarray "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9160 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.istypedarray "See the npm package") Checks if `value` is classified as a typed array. @@ -4977,7 +5052,7 @@ _.isTypedArray([]); ### `_.isUndefined(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9139 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isundefined "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9180 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.isundefined "See the npm package") Checks if `value` is `undefined`. @@ -5002,7 +5077,7 @@ _.isUndefined(null); ### `_.lt(value, other)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9163 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.lt "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9204 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.lt "See the npm package") Checks if `value` is less than `other`. @@ -5031,7 +5106,7 @@ _.lt(3, 1); ### `_.lte(value, other)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9187 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.lte "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9228 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.lte "See the npm package") Checks if `value` is less than or equal to `other`. @@ -5060,7 +5135,7 @@ _.lte(3, 1); ### `_.toArray(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9206 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.toarray "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9247 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.toarray "See the npm package") Converts `value` to an array. @@ -5084,7 +5159,7 @@ Converts `value` to an array. ### `_.toPlainObject(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9242 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.toplainobject "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9283 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.toplainobject "See the npm package") Converts `value` to a plain object flattening inherited enumerable properties of `value` to own properties of the plain object. @@ -5122,7 +5197,7 @@ _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); ### `_.add(augend, addend)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11759 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.add "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11802 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.add "See the npm package") Adds two numbers. @@ -5144,8 +5219,66 @@ _.add(6, 4); +### `_.ceil(n, [precision=0])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11826 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.ceil "See the npm package") + +Calculates `n` rounded up to `precision`. + +#### Arguments +1. `n` *(number)*: The number to round up. +2. `[precision=0]` *(number)*: The precision to round up to. + +#### Returns +*(number)*: Returns the rounded up number. + +#### Example +```js +_.ceil(4.006); +// => 5 + +_.ceil(6.004, 2); +// => 6.01 + +_.ceil(6040, -2); +// => 6100 +``` +* * * + + + + + +### `_.floor(n, [precision=0])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11848 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.floor "See the npm package") + +Calculates `n` rounded down to `precision`. + +#### Arguments +1. `n` *(number)*: The number to round down. +2. `[precision=0]` *(number)*: The precision to round down to. + +#### Returns +*(number)*: Returns the rounded down number. + +#### Example +```js +_.floor(4.006); +// => 4 + +_.floor(0.046, 2); +// => 0.04 + +_.floor(4060, -2); +// => 4000 +``` +* * * + + + + + ### `_.max(collection, [iteratee], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11810 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.max "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11897 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.max "See the npm package") Gets the maximum value of `collection`. If `collection` is empty or falsey `-Infinity` is returned. If an iteratee function is provided it is invoked @@ -5204,7 +5337,7 @@ _.max(users, 'age'); ### `_.min(collection, [iteratee], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11859 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.min "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11946 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.min "See the npm package") Gets the minimum value of `collection`. If `collection` is empty or falsey `Infinity` is returned. If an iteratee function is provided it is invoked @@ -5262,8 +5395,37 @@ _.min(users, 'age'); +### `_.round(n, [precision=0])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11968 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.round "See the npm package") + +Calculates `n` rounded to `precision`. + +#### Arguments +1. `n` *(number)*: The number to round. +2. `[precision=0]` *(number)*: The precision to round to. + +#### Returns +*(number)*: Returns the rounded number. + +#### Example +```js +_.round(4.006); +// => 4 + +_.round(4.006, 2); +// => 4.01 + +_.round(4060, -2); +// => 4100 +``` +* * * + + + + + ### `_.sum(collection, [iteratee], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11893 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sum "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L12002 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.sum "See the npm package") Gets the sum of the values in `collection`. @@ -5310,7 +5472,7 @@ _.sum(objects, 'n'); ### `_.inRange(n, [start=0], end)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10266 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.inrange "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10320 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.inrange "See the npm package") Checks if `n` is between `start` and up to but not including, `end`. If `end` is not specified it is set to `start` with `start` then set to `0`. @@ -5350,7 +5512,7 @@ _.inRange(5.2, 4); ### `_.random([min=0], [max=1], [floating])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10304 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.random "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10358 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.random "See the npm package") 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. @@ -5392,7 +5554,7 @@ _.random(1.2, 5.2); ### `_.assign(object, [sources], [customizer], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9280 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.assign "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9371 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.assign "See the npm package") Assigns own enumerable properties of source object(s) to the destination object. Subsequent sources overwrite property assignments of previous sources. @@ -5402,7 +5564,7 @@ The `customizer` is bound to `thisArg` and invoked with five arguments:


**Note:** This method mutates `object` and is based on -[`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign). +[`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign). #### Aliases *_.extend* @@ -5436,7 +5598,7 @@ defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); ### `_.create(prototype, [properties])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9320 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.create "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9411 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.create "See the npm package") Creates an object that inherits from the given `prototype` object. If a `properties` object is provided its own enumerable properties are assigned @@ -5478,7 +5640,7 @@ circle instanceof Shape; ### `_.defaults(object, [sources])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9346 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.defaults "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9437 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.defaults "See the npm package") Assigns own enumerable properties of source object(s) to the destination object for all destination properties that resolve to `undefined`. Once a @@ -5505,8 +5667,35 @@ _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); +### `_.defaultsDeep(object, [sources])` +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9457 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.defaultsdeep "See the npm package") + +This method is like `_.defaults` except that it recursively assigns +default properties. +
+
+**Note:** This method mutates `object`. + +#### Arguments +1. `object` *(Object)*: The destination object. +2. `[sources]` *(...Object)*: The source objects. + +#### Returns +*(Object)*: Returns `object`. + +#### Example +```js +_.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); +// => { 'user': { 'name': 'barney', 'age': 36 } } +``` +* * * + + + + + ### `_.findKey(object, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9403 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findkey "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9507 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findkey "See the npm package") This method is like `_.find` except that it returns the key of the first element `predicate` returns truthy for instead of the element itself. @@ -5565,7 +5754,7 @@ _.findKey(users, 'active'); ### `_.findLastKey(object, [predicate=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9453 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findlastkey "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9557 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.findlastkey "See the npm package") This method is like `_.findKey` except that it iterates over elements of a collection in the opposite order. @@ -5624,7 +5813,7 @@ _.findLastKey(users, 'active'); ### `_.forIn(object, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9482 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forin "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9586 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forin "See the npm package") Iterates over own and inherited enumerable properties of an object invoking `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked @@ -5660,7 +5849,7 @@ _.forIn(new Foo, function(value, key) { ### `_.forInRight(object, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9509 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forinright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9613 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forinright "See the npm package") This method is like `_.forIn` except that it iterates over properties of `object` in the opposite order. @@ -5694,7 +5883,7 @@ _.forInRight(new Foo, function(value, key) { ### `_.forOwn(object, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9538 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forown "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9642 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forown "See the npm package") Iterates over own enumerable properties of an object invoking `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked with @@ -5730,7 +5919,7 @@ _.forOwn(new Foo, function(value, key) { ### `_.forOwnRight(object, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9565 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forownright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9669 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.forownright "See the npm package") This method is like `_.forOwn` except that it iterates over properties of `object` in the opposite order. @@ -5764,7 +5953,7 @@ _.forOwnRight(new Foo, function(value, key) { ### `_.functions(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9582 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.functions "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9686 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.functions "See the npm package") Creates an array of function property names from all enumerable properties, own and inherited, of `object`. @@ -5790,7 +5979,7 @@ _.functions(_); ### `_.get(object, path, [defaultValue])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9610 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.get "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9714 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.get "See the npm package") Gets the property value at `path` of `object`. If the resolved value is `undefined` the `defaultValue` is used in its place. @@ -5823,7 +6012,7 @@ _.get(object, 'a.b.c', 'default'); ### `_.has(object, path)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9637 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.has "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9741 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.has "See the npm package") Checks if `path` is a direct property. @@ -5854,7 +6043,7 @@ _.has(object, ['a', 'b', 'c']); ### `_.invert(object, [multiValue])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9678 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.invert "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9782 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.invert "See the npm package") Creates an object composed of the inverted keys and values of `object`. If `object` contains duplicate values, subsequent values overwrite property @@ -5885,13 +6074,13 @@ _.invert(object, true); ### `_.keys(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9732 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.keys "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9836 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.keys "See the npm package") Creates an array of the own enumerable property names of `object`.

**Note:** Non-object values are coerced to objects. See the -[ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) +[ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) for more details. #### Arguments @@ -5922,7 +6111,7 @@ _.keys('hi'); ### `_.keysIn(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9763 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.keysin "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9867 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.keysin "See the npm package") Creates an array of the own and inherited enumerable property names of `object`.
@@ -5954,7 +6143,7 @@ _.keysIn(new Foo); ### `_.mapKeys(object, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9840 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.mapkeys "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9944 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.mapkeys "See the npm package") The opposite of `_.mapValues`; this method creates an object with the same values as `object` and keys generated by running each own enumerable @@ -5982,7 +6171,7 @@ _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { ### `_.mapValues(object, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9883 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.mapvalues "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9987 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.mapvalues "See the npm package") Creates an object with the same keys as `object` and values generated by running each own enumerable property of `object` through `iteratee`. The @@ -6034,7 +6223,7 @@ _.mapValues(users, 'age'); ### `_.merge(object, [sources], [customizer], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9933 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.merge "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L9337 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.merge "See the npm package") Recursively merges own enumerable properties of the source object(s), that don't resolve to `undefined` into the destination object. Subsequent sources @@ -6091,7 +6280,7 @@ _.merge(object, other, function(a, b) { ### `_.omit(object, [predicate], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9958 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.omit "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10012 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.omit "See the npm package") The opposite of `_.pick`; this method creates an object composed of the own and inherited enumerable properties of `object` that are not omitted. @@ -6121,7 +6310,7 @@ _.omit(object, _.isNumber); ### `_.pairs(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L9986 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pairs "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10040 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pairs "See the npm package") Creates a two dimensional array of the key-value pairs for `object`, e.g. `[[key1, value1], [key2, value2]]`. @@ -6144,7 +6333,7 @@ _.pairs({ 'barney': 36, 'fred': 40 }); ### `_.pick(object, [predicate], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10027 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pick "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10081 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pick "See the npm package") Creates an object composed of the picked `object` properties. Property names may be specified as individual arguments or as arrays of property @@ -6177,7 +6366,7 @@ _.pick(object, _.isString); ### `_.result(object, path, [defaultValue])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10064 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.result "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10118 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.result "See the npm package") This method is like `_.get` except that if the resolved value is a function it is invoked with the `this` binding of its parent object and its result @@ -6214,7 +6403,7 @@ _.result(object, 'a.b.c', _.constant('default')); ### `_.set(object, path, value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10100 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.set "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10154 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.set "See the npm package") Sets the property value of `path` on `object`. If a portion of `path` does not exist it is created. @@ -6246,7 +6435,7 @@ console.log(object.x[0].y.z); ### `_.transform(object, [iteratee=_.identity], [accumulator], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10155 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.transform "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10209 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.transform "See the npm package") An alternative to `_.reduce`; this method transforms `object` to a new `accumulator` object which is the result of running each of its own enumerable @@ -6284,7 +6473,7 @@ _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) { ### `_.values(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10202 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.values "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10256 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.values "See the npm package") Creates an array of the own enumerable property values of `object`.
@@ -6319,7 +6508,7 @@ _.values('hi'); ### `_.valuesIn(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10229 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.valuesin "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10283 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.valuesin "See the npm package") Creates an array of the own and inherited enumerable property values of `object`. @@ -6358,7 +6547,7 @@ _.valuesIn(new Foo); ### `_.camelCase([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10360 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.camelcase "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10414 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.camelcase "See the npm package") Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). @@ -6386,7 +6575,7 @@ _.camelCase('__foo_bar__'); ### `_.capitalize([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10378 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.capitalize "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10432 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.capitalize "See the npm package") Capitalizes the first character of `string`. @@ -6408,7 +6597,7 @@ _.capitalize('fred'); ### `_.deburr([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10397 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.deburr "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10451 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.deburr "See the npm package") Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). @@ -6431,7 +6620,7 @@ _.deburr('déjà vu'); ### `_.endsWith([string=''], [target], [position=string.length])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10423 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.endswith "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10477 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.endswith "See the npm package") Checks if `string` ends with the given target string. @@ -6461,7 +6650,7 @@ _.endsWith('abc', 'b', 2); ### `_.escape([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10468 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.escape "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10522 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.escape "See the npm package") Converts the characters "&", "<", ">", '"', "'", and "\`", in `string` to their corresponding HTML entities. @@ -6506,7 +6695,7 @@ _.escape('fred, barney, & pebbles'); ### `_.escapeRegExp([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10490 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.escaperegexp "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10544 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.escaperegexp "See the npm package") Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?", "*", "+", "(", ")", "[", "]", "{" and "}" in `string`. @@ -6529,7 +6718,7 @@ _.escapeRegExp('[lodash](https://lodash.com/)'); ### `_.kebabCase([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10516 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.kebabcase "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10570 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.kebabcase "See the npm package") Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). @@ -6557,7 +6746,7 @@ _.kebabCase('__foo_bar__'); ### `_.pad([string=''], [length=0], [chars=' '])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10542 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pad "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10596 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.pad "See the npm package") Pads `string` on the left and right sides if it's shorter than `length`. Padding characters are truncated if they can't be evenly divided by `length`. @@ -6588,7 +6777,7 @@ _.pad('abc', 3); ### `_.padLeft([string=''], [length=0], [chars=' '])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10580 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.padleft "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10634 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.padleft "See the npm package") Pads `string` on the left side if it's shorter than `length`. Padding characters are truncated if they exceed `length`. @@ -6619,7 +6808,7 @@ _.padLeft('abc', 3); ### `_.padRight([string=''], [length=0], [chars=' '])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10604 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.padright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10658 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.padright "See the npm package") Pads `string` on the right side if it's shorter than `length`. Padding characters are truncated if they exceed `length`. @@ -6650,7 +6839,7 @@ _.padRight('abc', 3); ### `_.parseInt(string, [radix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10629 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.parseint "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10683 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.parseint "See the npm package") Converts `string` to an integer of the specified radix. If `radix` is `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, @@ -6682,7 +6871,7 @@ _.map(['6', '08', '10'], _.parseInt); ### `_.repeat([string=''], [n=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10671 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.repeat "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10716 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.repeat "See the npm package") Repeats the given string `n` times. @@ -6711,7 +6900,7 @@ _.repeat('abc', 0); ### `_.snakeCase([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10710 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.snakecase "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10755 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.snakecase "See the npm package") Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case). @@ -6739,7 +6928,7 @@ _.snakeCase('--foo-bar'); ### `_.startCase([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10733 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.startcase "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10778 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.startcase "See the npm package") Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). @@ -6767,7 +6956,7 @@ _.startCase('__foo_bar__'); ### `_.startsWith([string=''], [target], [position=0])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10758 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.startswith "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10803 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.startswith "See the npm package") Checks if `string` starts with the given target string. @@ -6797,7 +6986,7 @@ _.startsWith('abc', 'b', 1); ### `_.template([string=''], [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10863 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.template "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L10908 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.template "See the npm package") Creates a compiled template function that can interpolate data properties in "interpolate" delimiters, HTML-escape interpolated data properties in @@ -6904,7 +7093,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\ ### `_.trim([string=''], [chars=whitespace])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L10990 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trim "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11035 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trim "See the npm package") Removes leading and trailing whitespace or specified characters from `string`. @@ -6933,7 +7122,7 @@ _.map([' foo ', ' bar '], _.trim); ### `_.trimLeft([string=''], [chars=whitespace])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11021 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trimleft "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11066 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trimleft "See the npm package") Removes leading whitespace or specified characters from `string`. @@ -6959,7 +7148,7 @@ _.trimLeft('-_-abc-_-', '_-'); ### `_.trimRight([string=''], [chars=whitespace])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11051 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trimright "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11096 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trimright "See the npm package") Removes trailing whitespace or specified characters from `string`. @@ -6985,7 +7174,7 @@ _.trimRight('-_-abc-_-', '_-'); ### `_.trunc([string=''], [options], [options.length=30], [options.omission='...'], [options.separator])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11103 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trunc "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11148 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.trunc "See the npm package") Truncates `string` if it's longer than the given maximum string length. The last characters of the truncated string are replaced with the omission @@ -7033,7 +7222,7 @@ _.trunc('hi-diddly-ho there, neighborino', { ### `_.unescape([string=''])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11173 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.unescape "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11218 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.unescape "See the npm package") The inverse of `_.escape`; this method converts the HTML entities `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their @@ -7061,7 +7250,7 @@ _.unescape('fred, barney, & pebbles'); ### `_.words([string=''], [pattern])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11198 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.words "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11243 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.words "See the npm package") Splits `string` into an array of its words. @@ -7093,7 +7282,7 @@ _.words('fred, barney, & pebbles', /[^, ]+/g); ### `_.attempt(func)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11228 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.attempt "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11273 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.attempt "See the npm package") Attempts to invoke `func`, returning either the result or the caught error object. Any additional arguments are provided to `func` when it is invoked. @@ -7122,7 +7311,7 @@ if (_.isError(elements)) { ### `_.callback([func=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11274 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.callback "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11319 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.callback "See the npm package") Creates a function that invokes `func` with the `this` binding of `thisArg` and arguments of the created function. If `func` is a property name the @@ -7170,7 +7359,7 @@ _.filter(users, 'age__gt36'); ### `_.constant(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11299 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.constant "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11344 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.constant "See the npm package") Creates a function that returns `value`. @@ -7195,7 +7384,7 @@ getter() === object; ### `_.identity(value)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11320 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.identity "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11365 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.identity "See the npm package") This method returns the first argument provided to it. @@ -7219,7 +7408,7 @@ _.identity(object) === object; ### `_.matches(source)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11349 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.matches "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11394 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.matches "See the npm package") Creates a function that performs a deep comparison between a given object and `source`, returning `true` if the given object has equivalent property @@ -7254,7 +7443,7 @@ _.filter(users, _.matches({ 'age': 40, 'active': false })); ### `_.matchesProperty(path, srcValue)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11377 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.matchesproperty "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11422 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.matchesproperty "See the npm package") Creates a function that compares the property value of `path` on a given object to `value`. @@ -7288,7 +7477,7 @@ _.find(users, _.matchesProperty('user', 'fred')); ### `_.method(path, [args])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11404 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.method "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11449 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.method "See the npm package") Creates a function that invokes the method at `path` on a given object. Any additional arguments are provided to the invoked method. @@ -7320,7 +7509,7 @@ _.invoke(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c'); ### `_.methodOf(object, [args])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11432 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.methodof "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11477 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.methodof "See the npm package") The opposite of `_.method`; this method creates a function that invokes the method at a given path on `object`. Any additional arguments are @@ -7351,7 +7540,7 @@ _.map([['a', '2'], ['c', '0']], _.methodOf(object)); ### `_.mixin([object=lodash], source, [options])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11474 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.mixin "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11519 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.mixin "See the npm package") Adds all own enumerable function properties of a source object to the destination object. If `object` is a function then methods are added to @@ -7396,7 +7585,7 @@ _('fred').vowels(); ### `_.noConflict()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11539 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.noconflict "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11582 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.noconflict "See the npm package") Reverts the `_` variable to its previous value and returns a reference to the `lodash` function. @@ -7415,7 +7604,7 @@ var lodash = _.noConflict(); ### `_.noop()` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11558 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.noop "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11601 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.noop "See the npm package") A no-operation function that returns `undefined` regardless of the arguments it receives. @@ -7434,7 +7623,7 @@ _.noop(object) === undefined; ### `_.property(path)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11584 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.property "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11627 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.property "See the npm package") Creates a function that returns the property value at `path` on a given object. @@ -7465,7 +7654,7 @@ _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); ### `_.propertyOf(object)` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11608 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.propertyof "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11651 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.propertyof "See the npm package") The opposite of `_.property`; this method creates a function that returns the property value at a given path on `object`. @@ -7494,7 +7683,7 @@ _.map([['a', '2'], ['c', '0']], _.propertyOf(object)); ### `_.range([start=0], end, [step=1])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11647 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.range "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11690 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.range "See the npm package") Creates an array of numbers (positive and/or negative) progressing from `start` up to, but not including, `end`. If `end` is not specified it is @@ -7536,7 +7725,7 @@ _.range(0); ### `_.runInContext([context=root])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L717 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.runincontext "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L723 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.runincontext "See the npm package") Create a new pristine `lodash` function using the given `context` object. @@ -7580,7 +7769,7 @@ var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; ### `_.times(n, [iteratee=_.identity], [thisArg])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11700 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.times "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11743 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.times "See the npm package") Invokes the iteratee function `n` times, returning an array of the results of each invocation. The `iteratee` is bound to `thisArg` and invoked with @@ -7616,7 +7805,7 @@ _.times(3, function(n) { ### `_.uniqueId([prefix])` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L11738 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.uniqueid "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L11781 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.uniqueid "See the npm package") Generates a unique ID. If `prefix` is provided the ID is appended to it. @@ -7647,7 +7836,7 @@ _.uniqueId(); ### `_.templateSettings.imports._` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1164 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1122 "View in source") [Ⓣ][1] A reference to the `lodash` function. @@ -7664,7 +7853,7 @@ A reference to the `lodash` function. ### `_.VERSION` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L12191 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L12299 "View in source") [Ⓣ][1] (string): The semantic version number. @@ -7675,7 +7864,7 @@ A reference to the `lodash` function. ### `_.support` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L999 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.support "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L986 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.support "See the npm package") (Object): An object environment feature flags. @@ -7685,20 +7874,8 @@ A reference to the `lodash` function. -### `_.support.argsTag` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1016 "View in source") [Ⓣ][1] - -(boolean): Detect if the `toStringTag` of `arguments` objects is resolvable -(all but Firefox < 4, IE < 9). - -* * * - - - - - ### `_.support.enumErrorProps` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1025 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1003 "View in source") [Ⓣ][1] (boolean): Detect if `name` or `message` properties of `Error.prototype` are enumerable by default (IE < 9, Safari < 5.1). @@ -7710,7 +7887,7 @@ enumerable by default (IE < 9, Safari < 5.1). ### `_.support.enumPrototypes` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1039 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1017 "View in source") [Ⓣ][1] (boolean): Detect if `prototype` properties are enumerable by default.
@@ -7726,19 +7903,8 @@ property to `true`. -### `_.support.nodeTag` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1047 "View in source") [Ⓣ][1] - -(boolean): Detect if the `toStringTag` of DOM nodes is resolvable (all but IE < 9). - -* * * - - - - - ### `_.support.nonEnumShadows` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1058 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1028 "View in source") [Ⓣ][1] (boolean): Detect if properties shadowing those on `Object.prototype` are non-enumerable.
@@ -7753,7 +7919,7 @@ are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). ### `_.support.ownLast` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1066 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1036 "View in source") [Ⓣ][1] (boolean): Detect if own properties are iterated after inherited properties (IE < 9). @@ -7764,7 +7930,7 @@ are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). ### `_.support.spliceObjects` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1081 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1051 "View in source") [Ⓣ][1] (boolean): Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. @@ -7783,7 +7949,7 @@ while `splice()` is buggy regardless of mode in IE < 9. ### `_.support.unindexedChars` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1092 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1062 "View in source") [Ⓣ][1] (boolean): Detect lack of support for accessing string characters by index.
@@ -7798,7 +7964,7 @@ by index on string literals, not string objects. ### `_.templateSettings` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1116 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.templatesettings "See the npm package") +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1074 "View in source") [Ⓣ][1] [Ⓝ](https://www.npmjs.com/package/lodash.templatesettings "See the npm package") (Object): By default, the template delimiters used by lodash are like those in embedded Ruby (ERB). Change the following template settings to use @@ -7811,7 +7977,7 @@ alternative delimiters. ### `_.templateSettings.escape` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1124 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1082 "View in source") [Ⓣ][1] (RegExp): Used to detect `data` property values to be HTML-escaped. @@ -7822,7 +7988,7 @@ alternative delimiters. ### `_.templateSettings.evaluate` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1132 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1090 "View in source") [Ⓣ][1] (RegExp): Used to detect code to be evaluated. @@ -7833,7 +7999,7 @@ alternative delimiters. ### `_.templateSettings.imports` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1156 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1114 "View in source") [Ⓣ][1] (Object): Used to import variables into the compiled template. @@ -7844,7 +8010,7 @@ alternative delimiters. ### `_.templateSettings.interpolate` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1140 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1098 "View in source") [Ⓣ][1] (RegExp): Used to detect `data` property values to inject. @@ -7855,7 +8021,7 @@ alternative delimiters. ### `_.templateSettings.variable` -# [Ⓢ](https://github.com/lodash/lodash/blob/3.9.3/lodash.src.js#L1148 "View in source") [Ⓣ][1] +# [Ⓢ](https://github.com/lodash/lodash/blob/3.10.0/lodash.src.js#L1106 "View in source") [Ⓣ][1] (string): Used to reference the data object in the template text. diff --git a/lodash.js b/lodash.js index 73bf0b122c..e1eb0ad15e 100644 --- a/lodash.js +++ b/lodash.js @@ -1,6 +1,6 @@ /** * @license - * lodash 3.9.3 (Custom Build) + * lodash 3.10.0 (Custom Build) * Build: `lodash modern -o ./lodash.js` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.8.3 @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '3.9.3'; + var VERSION = '3.10.0'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -34,9 +34,11 @@ var HOT_COUNT = 150, HOT_SPAN = 16; + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** Used to indicate the type of lazy iteratees. */ - var LAZY_DROP_WHILE_FLAG = 0, - LAZY_FILTER_FLAG = 1, + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; /** Used as the `TypeError` message for "Functions" methods. */ @@ -93,11 +95,10 @@ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; /** - * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). - * In addition to special characters the forward slash is escaped to allow for - * easier `eval` use and `Function` compilation. + * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) + * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). */ - var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ @@ -106,7 +107,7 @@ /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; - /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ + /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ @@ -138,25 +139,13 @@ return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); }()); - /** Used to detect and test for whitespace. */ - var whitespace = ( - // Basic whitespace characters. - ' \t\x0b\f\xa0\ufeff' + - - // Line terminators. - '\n\r\u2028\u2029' + - - // Unicode category "Zs" space separators. - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); - /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', - 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', - 'isFinite', 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'window' + 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite', + 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap' ]; /** Used to make template sourceURLs easier to identify. */ @@ -192,13 +181,6 @@ cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; - /** Used as an internal `_.debounce` options object by `_.throttle`. */ - var debounceOptions = { - 'leading': false, - 'maxWait': 0, - 'trailing': false - }; - /** Used to map latin-1 supplementary letters to basic latin letters. */ var deburredLetters = { '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', @@ -246,6 +228,15 @@ 'object': true }; + /** Used to escape characters for inclusion in compiled regexes. */ + var regexpEscapes = { + '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34', + '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39', + 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46', + 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66', + 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78' + }; + /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', @@ -386,9 +377,6 @@ * @returns {string} Returns the string. */ function baseToString(value) { - if (typeof value == 'string') { - return value; - } return value == null ? '' : (value + ''); } @@ -430,8 +418,8 @@ * sort them in ascending order. * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @returns {number} Returns the sort order indicator for `object`. */ function compareAscending(object, other) { @@ -439,16 +427,16 @@ } /** - * Used by `_.sortByOrder` to compare multiple properties of each element - * in a collection and stable sort them in the following order: + * Used by `_.sortByOrder` to compare multiple properties of a value to another + * and stable sort them. * - * If `orders` is unspecified, sort in ascending order for all properties. - * Otherwise, for each property, sort in ascending order if its corresponding value in - * orders is true, and descending order if false. + * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise, + * a value is sorted in ascending order if its corresponding order is "asc", and + * descending if "desc". * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @param {boolean[]} orders The order to sort by for each property. * @returns {number} Returns the sort order indicator for `object`. */ @@ -465,7 +453,8 @@ if (index >= ordersLength) { return result; } - return result * (orders[index] ? 1 : -1); + var order = orders[index]; + return result * ((order === 'asc' || order === true) ? 1 : -1); } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications @@ -501,8 +490,25 @@ } /** - * Used by `_.template` to escape characters for inclusion in compiled - * string literals. + * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes. + * + * @private + * @param {string} chr The matched character to escape. + * @param {string} leadingChar The capture group for a leading character. + * @param {string} whitespaceChar The capture group for a whitespace character. + * @returns {string} Returns the escaped character. + */ + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return '\\' + chr; + } + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. * * @private * @param {string} chr The matched character to escape. @@ -713,9 +719,6 @@ objectProto = Object.prototype, stringProto = String.prototype; - /** Used to detect DOM support. */ - var document = (document = context.window) ? document.document : null; - /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; @@ -726,56 +729,42 @@ var idCounter = 0; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; /** Used to restore the original `_` reference in `_.noConflict`. */ - var oldDash = context._; + var oldDash = root._; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - escapeRegExp(fnToString.call(hasOwnProperty)) + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method references. */ - var ArrayBuffer = getNative(context, 'ArrayBuffer'), - bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), - ceil = Math.ceil, + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, - floor = Math.floor, - getPrototypeOf = getNative(Object, 'getPrototypeOf'), parseFloat = context.parseFloat, - push = arrayProto.push, + pow = Math.pow, + propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, 'Set'), setTimeout = context.setTimeout, splice = arrayProto.splice, - Uint8Array = getNative(context, 'Uint8Array'), + Uint8Array = context.Uint8Array, WeakMap = getNative(context, 'WeakMap'); - /** Used to clone array buffers. */ - var Float64Array = (function() { - // Safari 5 errors when using an array buffer to initialize a typed array - // where the array buffer's `byteLength` is not a multiple of the typed - // array's `BYTES_PER_ELEMENT`. - try { - var func = getNative(context, 'Float64Array'), - result = new func(new ArrayBuffer(10), 0, 1) && func; - } catch(e) {} - return result || null; - }()); - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeCreate = getNative(Object, 'create'), + var nativeCeil = Math.ceil, + nativeCreate = getNative(Object, 'create'), + nativeFloor = Math.floor, nativeIsArray = getNative(Array, 'isArray'), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, 'keys'), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, 'now'), - nativeNumIsFinite = getNative(Number, 'isFinite'), nativeParseInt = context.parseInt, nativeRandom = Math.random; @@ -788,11 +777,8 @@ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - /** Used as the size, in bytes, of each `Float64Array` element. */ - var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; - /** - * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) * of an array-like value. */ var MAX_SAFE_INTEGER = 9007199254740991; @@ -808,15 +794,16 @@ /** * Creates a `lodash` object which wraps `value` to enable implicit chaining. * Methods that operate on and return arrays, collections, and functions can - * be chained together. Methods that return a boolean or single value will - * automatically end the chain returning the unwrapped value. Explicit chaining - * may be enabled using `_.chain`. The execution of chained methods is lazy, - * that is, execution is deferred until `_#value` is implicitly or explicitly - * called. + * be chained together. Methods that retrieve a single value or may return a + * primitive value will automatically end the chain returning the unwrapped + * value. Explicit chaining may be enabled using `_.chain`. The execution of + * chained methods is lazy, that is, execution is deferred until `_#value` + * is implicitly or explicitly called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut - * fusion is an optimization that merges iteratees to avoid creating intermediate - * arrays and reduce the number of iteratee executions. + * fusion is an optimization strategy which merge iteratee calls; this can help + * to avoid the creation of intermediate data structures and greatly reduce the + * number of iteratee executions. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. @@ -839,36 +826,37 @@ * The chainable wrapper methods are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, - * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, - * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, - * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, - * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, - * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, - * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`, - * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`, - * `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, - * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, - * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, - * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, - * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, - * `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`, - * `wrap`, `xor`, `zip`, `zipObject`, `zipWith` + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, + * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, + * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, + * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, + * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, + * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, + * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, + * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, + * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, + * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, + * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, + * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`, - * `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, - * `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, - * `isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, - * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, - * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`, - * `max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`, - * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, - * `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, - * `sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`, - * `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words` + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, + * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, + * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, + * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, + * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, + * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, + * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, + * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, + * `unescape`, `uniqueId`, `value`, and `words` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. @@ -943,27 +931,6 @@ */ var support = lodash.support = {}; - (function(x) { - var Ctor = function() { this.x = x; }, - object = { '0': x, 'length': x }, - props = []; - - Ctor.prototype = { 'valueOf': x, 'y': x }; - for (var key in new Ctor) { props.push(key); } - - /** - * Detect if the DOM is supported. - * - * @memberOf _.support - * @type boolean - */ - try { - support.dom = document.createDocumentFragment().nodeType === 11; - } catch(e) { - support.dom = false; - } - }(1, 0)); - /** * By default, the template delimiters used by lodash are like those in * embedded Ruby (ERB). Change the following template settings to use @@ -1035,13 +1002,12 @@ */ function LazyWrapper(value) { this.__wrapped__ = value; - this.__actions__ = null; + this.__actions__ = []; this.__dir__ = 1; - this.__dropCount__ = 0; this.__filtered__ = false; - this.__iteratees__ = null; + this.__iteratees__ = []; this.__takeCount__ = POSITIVE_INFINITY; - this.__views__ = null; + this.__views__ = []; } /** @@ -1053,17 +1019,13 @@ * @returns {Object} Returns the cloned `LazyWrapper` object. */ function lazyClone() { - var actions = this.__actions__, - iteratees = this.__iteratees__, - views = this.__views__, - result = new LazyWrapper(this.__wrapped__); - - result.__actions__ = actions ? arrayCopy(actions) : null; + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); result.__dir__ = this.__dir__; result.__filtered__ = this.__filtered__; - result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__iteratees__ = arrayCopy(this.__iteratees__); result.__takeCount__ = this.__takeCount__; - result.__views__ = views ? arrayCopy(views) : null; + result.__views__ = arrayCopy(this.__views__); return result; } @@ -1096,22 +1058,25 @@ * @returns {*} Returns the unwrapped value. */ function lazyValue() { - var array = this.__wrapped__.value(); - if (!isArray(array)) { - return baseWrapperValue(array, this.__actions__); - } - var dir = this.__dir__, + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), isRight = dir < 0, - view = getView(0, array.length, this.__views__), + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : (start - 1), - takeCount = nativeMin(length, this.__takeCount__), iteratees = this.__iteratees__, - iterLength = iteratees ? iteratees.length : 0, + iterLength = iteratees.length, resIndex = 0, - result = []; + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) { + return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__); + } + var result = []; outer: while (length-- && resIndex < takeCount) { @@ -1123,30 +1088,16 @@ while (++iterIndex < iterLength) { var data = iteratees[iterIndex], iteratee = data.iteratee, - type = data.type; + type = data.type, + computed = iteratee(value); - if (type == LAZY_DROP_WHILE_FLAG) { - if (data.done && (isRight ? (index > data.index) : (index < data.index))) { - data.count = 0; - data.done = false; - } - data.index = index; - if (!data.done) { - var limit = data.limit; - if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) { - continue outer; - } - } - } else { - var computed = iteratee(value); - if (type == LAZY_MAP_FLAG) { - value = computed; - } else if (!computed) { - if (type == LAZY_FILTER_FLAG) { - continue outer; - } else { - break outer; - } + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; } } } @@ -1278,6 +1229,30 @@ /*------------------------------------------------------------------------*/ + /** + * Creates a new array joining `array` with `other`. + * + * @private + * @param {Array} array The array to join. + * @param {Array} other The other array to join. + * @returns {Array} Returns the new concatenated array. + */ + function arrayConcat(array, other) { + var index = -1, + length = array.length, + othIndex = -1, + othLength = other.length, + result = Array(length + othLength); + + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + /** * Copies the values of `source` to `array`. * @@ -1433,6 +1408,25 @@ return result; } + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands and `this` binding. @@ -1504,18 +1498,20 @@ } /** - * A specialized version of `_.sum` for arrays without support for iteratees. + * A specialized version of `_.sum` for arrays without support for callback + * shorthands and `this` binding.. * * @private * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. * @returns {number} Returns the sum. */ - function arraySum(array) { + function arraySum(array, iteratee) { var length = array.length, result = 0; while (length--) { - result += +array[length] || 0; + result += +iteratee(array[length]) || 0; } return result; } @@ -1719,7 +1715,7 @@ : (object ? value : {}); } } - // Check for circular references and return corresponding clone. + // Check for circular references and return its corresponding clone. stackA || (stackA = []); stackB || (stackB = []); @@ -1754,7 +1750,7 @@ if (isObject(prototype)) { object.prototype = prototype; var result = new object; - object.prototype = null; + object.prototype = undefined; } return result || {}; }; @@ -1796,7 +1792,7 @@ var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, - cache = (isCommon && values.length >= 200) ? createCache(values) : null, + cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, valuesLength = values.length; if (cache) { @@ -1972,13 +1968,14 @@ * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. + * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isDeep, isStrict) { + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, - length = array.length, - resIndex = -1, - result = []; + length = array.length; while (++index < length) { var value = array[index]; @@ -1986,16 +1983,12 @@ (isStrict || isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). - value = baseFlatten(value, isDeep, isStrict); - } - var valIndex = -1, - valLength = value.length; - - while (++valIndex < valLength) { - result[++resIndex] = value[valIndex]; + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); } } else if (!isStrict) { - result[++resIndex] = value; + result[result.length] = value; } } return result; @@ -2350,7 +2343,7 @@ * @private * @param {Object} object The destination object. * @param {Object} source The source object. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns `object`. @@ -2360,7 +2353,7 @@ return object; } var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), - props = isSrcArr ? null : keys(source); + props = isSrcArr ? undefined : keys(source); arrayEach(props || source, function(srcValue, key) { if (props) { @@ -2399,7 +2392,7 @@ * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. @@ -2506,7 +2499,7 @@ * @returns {number} Returns the random number. */ function baseRandom(min, max) { - return min + floor(nativeRandom() * (max - min + 1)); + return min + nativeFloor(nativeRandom() * (max - min + 1)); } /** @@ -2672,7 +2665,7 @@ indexOf = getIndexOf(), length = array.length, isCommon = indexOf == baseIndexOf, - isLarge = isCommon && length >= 200, + isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; @@ -2771,11 +2764,8 @@ length = actions.length; while (++index < length) { - var args = [result], - action = actions[index]; - - push.apply(args, action.args); - result = action.func.apply(action.thisArg, args); + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([result], action.args)); } return result; } @@ -2834,7 +2824,7 @@ valIsUndef = value === undefined; while (low < high) { - var mid = floor((low + high) / 2), + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; @@ -2903,26 +2893,11 @@ * @returns {ArrayBuffer} Returns the cloned array buffer. */ function bufferClone(buffer) { - return bufferSlice.call(buffer, 0); - } - if (!bufferSlice) { - // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. - bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + var result = new ArrayBuffer(buffer.byteLength), + view = new Uint8Array(result); - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); - } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); - } - return result; - }; + view.set(new Uint8Array(buffer)); + return result; } /** @@ -2941,7 +2916,7 @@ argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, - result = Array(argsLength + leftLength); + result = Array(leftLength + argsLength); while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; @@ -2988,12 +2963,7 @@ } /** - * Creates a function that aggregates a collection, creating an accumulator - * object composed from the results of running each element in the collection - * through an iteratee. - * - * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, - * and `_.partition`. + * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. @@ -3023,10 +2993,7 @@ } /** - * Creates a function that assigns properties of source object(s) to a given - * destination object. - * - * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. + * Creates a `_.assign`, `_.defaults`, or `_.merge` function. * * @private * @param {Function} assigner The function to assign values. @@ -3137,9 +3104,9 @@ * @param {Array} [values] The values to cache. * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. */ - var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { - return new SetCache(values); - }; + function createCache(values) { + return (nativeCreate && Set) ? new SetCache(values) : null; + } /** * Creates a function that produces compound words out of the words in a @@ -3174,7 +3141,7 @@ function createCtorWrapper(Ctor) { return function() { // Use a `switch` statement to work with class constructors. - // See https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist + // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { @@ -3184,6 +3151,8 @@ case 3: return new Ctor(args[0], args[1], args[2]); case 4: return new Ctor(args[0], args[1], args[2], args[3]); case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); } var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); @@ -3204,15 +3173,34 @@ function createCurry(flag) { function curryFunc(func, arity, guard) { if (guard && isIterateeCall(func, arity, guard)) { - arity = null; + arity = undefined; } - var result = createWrapper(func, flag, null, null, null, null, null, arity); + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curryFunc.placeholder; return result; } return curryFunc; } + /** + * Creates a `_.defaults` or `_.defaultsDeep` function. + * + * @private + * @param {Function} assigner The function to assign values. + * @param {Function} customizer The function to customize assigned values. + * @returns {Function} Returns the new defaults function. + */ + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + /** * Creates a `_.max` or `_.min` function. * @@ -3224,11 +3212,11 @@ function createExtremum(comparator, exValue) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } iteratee = getCallback(iteratee, thisArg, 3); if (iteratee.length == 1) { - collection = toIterable(collection); + collection = isArray(collection) ? collection : toIterable(collection); var result = arrayExtremum(collection, iteratee, comparator, exValue); if (!(collection.length && result === exValue)) { return result; @@ -3309,7 +3297,7 @@ throw new TypeError(FUNC_ERROR_TEXT); } if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { - wrapper = new LodashWrapper([]); + wrapper = new LodashWrapper([], true); } } index = wrapper ? -1 : length; @@ -3317,7 +3305,7 @@ func = funcs[index]; var funcName = getFuncName(func), - data = funcName == 'wrapper' ? getData(func) : null; + data = funcName == 'wrapper' ? getData(func) : undefined; if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); @@ -3326,12 +3314,14 @@ } } return function() { - var args = arguments; - if (wrapper && args.length == 1 && isArray(args[0])) { - return wrapper.plant(args[0]).value(); + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); } var index = 0, - result = length ? funcs[index].apply(this, args) : args[0]; + result = length ? funcs[index].apply(this, args) : value; while (++index < length) { result = funcs[index].call(this, result); @@ -3435,7 +3425,7 @@ function createPartial(flag) { var partialFunc = restParam(function(func, partials) { var holders = replaceHolders(partials, partialFunc.placeholder); - return createWrapper(func, flag, null, partials, holders); + return createWrapper(func, flag, undefined, partials, holders); }); return partialFunc; } @@ -3481,7 +3471,7 @@ isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, - Ctor = isBindKey ? null : createCtorWrapper(func); + Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by @@ -3505,12 +3495,12 @@ length -= argsHolders.length; if (length < arity) { - var newArgPos = argPos ? arrayCopy(argPos) : null, + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), - newsHolders = isCurry ? argsHolders : null, - newHoldersRight = isCurry ? null : argsHolders, - newPartials = isCurry ? args : null, - newPartialsRight = isCurry ? null : args; + newsHolders = isCurry ? argsHolders : undefined, + newHoldersRight = isCurry ? undefined : argsHolders, + newPartials = isCurry ? args : undefined, + newPartialsRight = isCurry ? undefined : args; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); @@ -3564,7 +3554,7 @@ } var padLength = length - strLength; chars = chars == null ? ' ' : (chars + ''); - return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); } /** @@ -3590,7 +3580,7 @@ argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, - args = Array(argsLength + leftLength); + args = Array(leftLength + argsLength); while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; @@ -3604,6 +3594,25 @@ return wrapper; } + /** + * Creates a `_.ceil`, `_.floor`, or `_.round` function. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : (+precision || 0); + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + /** * Creates a `_.sortedIndex` or `_.sortedLastIndex` function. * @@ -3653,16 +3662,16 @@ var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); - partials = holders = null; + partials = holders = undefined; } length -= (holders ? holders.length : 0); if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; - partials = holders = null; + partials = holders = undefined; } - var data = isBindKey ? null : getData(func), + var data = isBindKey ? undefined : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; if (data) { @@ -3741,7 +3750,7 @@ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private - * @param {Object} value The object to compare. + * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. @@ -3941,13 +3950,13 @@ * @private * @param {number} start The start of the view. * @param {number} end The end of the view. - * @param {Array} [transforms] The transformations to apply to the view. + * @param {Array} transforms The transformations to apply to the view. * @returns {Object} Returns an object containing the `start` and `end` * positions of the view. */ function getView(start, end, transforms) { var index = -1, - length = transforms ? transforms.length : 0; + length = transforms.length; while (++index < length) { var data = transforms[index], @@ -4146,7 +4155,7 @@ /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @private * @param {*} value The value to check. @@ -4238,6 +4247,18 @@ return data; } + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + /** * A specialized version of `_.pick` which picks `object` properties specified * by `props`. @@ -4337,38 +4358,6 @@ }; }()); - /** - * A fallback implementation of `_.isPlainObject` which checks if `value` - * is an object created by the `Object` constructor or has a `[[Prototype]]` - * of `null`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - */ - function shimIsPlainObject(value) { - var Ctor, - support = lodash.support; - - // Exit early for non `Object` objects. - if (!(isObjectLike(value) && objToString.call(value) == objectTag) || - (!hasOwnProperty.call(value, 'constructor') && - (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { - return false; - } - // IE < 9 iterates inherited properties before own properties. If the first - // iterated property is an object's own property then there are no inherited - // enumerable properties. - var result; - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - baseForIn(value, function(subValue, key) { - result = key; - }); - return result === undefined || hasOwnProperty.call(value, result); - } - /** * A fallback implementation of `Object.keys` which creates an array of the * own enumerable property names of `object`. @@ -4482,12 +4471,12 @@ if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { - size = nativeMax(+size || 1, 1); + size = nativeMax(nativeFloor(size) || 1, 1); } var index = 0, length = array ? array.length : 0, resIndex = -1, - result = Array(ceil(length / size)); + result = Array(nativeCeil(length / size)); while (index < length) { result[++resIndex] = baseSlice(array, index, (index += size)); @@ -4526,7 +4515,7 @@ /** * Creates an array of unique `array` values not included in the other - * provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -4541,7 +4530,7 @@ * // => [1, 3] */ var difference = restParam(function(array, values) { - return isArrayLike(array) + return (isObjectLike(array) && isArrayLike(array)) ? baseDifference(array, baseFlatten(values, false, true)) : []; }); @@ -4936,7 +4925,7 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `array`. If `array` is sorted providing `true` for `fromIndex` * performs a faster binary search. @@ -4970,10 +4959,9 @@ if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; } else if (fromIndex) { - var index = binaryIndex(array, value), - other = array[index]; - - if (value === value ? (value === other) : (other !== other)) { + var index = binaryIndex(array, value); + if (index < length && + (value === value ? (value === array[index]) : (array[index] !== array[index]))) { return index; } return -1; @@ -5000,7 +4988,7 @@ /** * Creates an array of unique values that are included in all of the provided - * arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5121,7 +5109,7 @@ /** * Removes all provided values from `array` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. @@ -5554,7 +5542,7 @@ /** * Creates an array of unique values, in order, from all of the provided arrays - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5573,7 +5561,7 @@ /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurence of each element * is kept. Providing `true` for `isSorted` performs a faster search algorithm * for sorted arrays. If an iteratee function is provided it is invoked for @@ -5627,7 +5615,7 @@ } if (isSorted != null && typeof isSorted != 'boolean') { thisArg = iteratee; - iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; isSorted = false; } var callback = getCallback(); @@ -5714,7 +5702,7 @@ /** * Creates an array excluding all provided values using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5756,7 +5744,7 @@ var array = arguments[index]; if (isArrayLike(array)) { var result = result - ? baseDifference(result, array).concat(baseDifference(array, result)) + ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; } } @@ -5978,16 +5966,16 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).push(3); + * var wrapped = _(array).push(3); * * console.log(array); * // => [1, 2] * - * wrapper = wrapper.commit(); + * wrapped = wrapped.commit(); * console.log(array); * // => [1, 2, 3] * - * wrapper.last(); + * wrapped.last(); * // => 3 * * console.log(array); @@ -5997,6 +5985,33 @@ return new LodashWrapper(this.value(), this.__chain__); } + /** + * Creates a new array joining a wrapped array with any additional arrays + * and/or values. + * + * @name concat + * @memberOf _ + * @category Chain + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var wrapped = _(array).concat(2, [3], [[4]]); + * + * console.log(wrapped.value()); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [toObject(array)], values); + }); + }); + /** * Creates a clone of the chained sequence planting `value` as the wrapped value. * @@ -6007,17 +6022,17 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).map(function(value) { + * var wrapped = _(array).map(function(value) { * return Math.pow(value, 2); * }); * * var other = [3, 4]; - * var otherWrapper = wrapper.plant(other); + * var otherWrapped = wrapped.plant(other); * - * otherWrapper.value(); + * otherWrapped.value(); * // => [9, 16] * - * wrapper.value(); + * wrapped.value(); * // => [1, 4] */ function wrapperPlant(value) { @@ -6060,15 +6075,20 @@ */ function wrapperReverse() { var value = this.__wrapped__; + + var interceptor = function(value) { + return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse(); + }; if (value instanceof LazyWrapper) { + var wrapped = value; if (this.__actions__.length) { - value = new LazyWrapper(this); + wrapped = new LazyWrapper(this); } - return new LodashWrapper(value.reverse(), this.__chain__); + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + return new LodashWrapper(wrapped, this.__chain__); } - return this.thru(function(value) { - return value.reverse(); - }); + return this.thru(interceptor); } /** @@ -6226,7 +6246,7 @@ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); @@ -6500,7 +6520,7 @@ /** * Checks if `value` is in `collection` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `collection`. * @@ -6533,17 +6553,14 @@ collection = values(collection); length = collection.length; } - if (!length) { - return false; - } if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { fromIndex = 0; } else { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) - ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) - : (getIndexOf(collection, target, fromIndex) > -1); + ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) + : (!!length && getIndexOf(collection, target, fromIndex) > -1); } /** @@ -6625,7 +6642,7 @@ result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); + var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; @@ -6795,7 +6812,8 @@ * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: - * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`, + * and `sortByOrder` * * @static * @memberOf _ @@ -7025,7 +7043,7 @@ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); @@ -7086,7 +7104,7 @@ return []; } if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } var index = -1; iteratee = getCallback(iteratee, thisArg, 3); @@ -7145,9 +7163,9 @@ /** * This method is like `_.sortByAll` except that it allows specifying the - * sort orders of the iteratees to sort by. A truthy value in `orders` will - * sort the corresponding property name in ascending order while a falsey - * value will sort it in descending order. + * sort orders of the iteratees to sort by. If `orders` is unspecified, all + * values are sorted in ascending order. Otherwise, a value is sorted in + * ascending order if its corresponding order is "asc", and descending if "desc". * * If a property name is provided for an iteratee the created `_.property` * style callback returns the property value of the given element. @@ -7161,7 +7179,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {boolean[]} orders The sort orders of `iteratees`. + * @param {boolean[]} [orders] The sort orders of `iteratees`. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Array} Returns the new sorted array. * @example @@ -7174,7 +7192,7 @@ * ]; * * // sort by `user` in ascending order and by `age` in descending order - * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values); + * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values); * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] */ function sortByOrder(collection, iteratees, orders, guard) { @@ -7182,7 +7200,7 @@ return []; } if (guard && isIterateeCall(iteratees, orders, guard)) { - orders = null; + orders = undefined; } if (!isArray(iteratees)) { iteratees = iteratees == null ? [] : [iteratees]; @@ -7307,10 +7325,10 @@ */ function ary(func, n, guard) { if (guard && isIterateeCall(func, n, guard)) { - n = null; + n = undefined; } n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); - return createWrapper(func, ARY_FLAG, null, null, null, null, n); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); } /** @@ -7345,7 +7363,7 @@ result = func.apply(this, arguments); } if (n <= 1) { - func = null; + func = undefined; } return result; }; @@ -7653,9 +7671,9 @@ var leading = true; trailing = false; } else if (isObject(options)) { - leading = options.leading; + leading = !!options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); - trailing = 'trailing' in options ? options.trailing : trailing; + trailing = 'trailing' in options ? !!options.trailing : trailing; } function cancel() { @@ -7665,41 +7683,35 @@ if (maxTimeoutId) { clearTimeout(maxTimeoutId); } + lastCalled = 0; maxTimeoutId = timeoutId = trailingCall = undefined; } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } + complete(trailingCall, maxTimeoutId); } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { - if (timeoutId) { - clearTimeout(timeoutId); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (trailing || (maxWait !== wait)) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } + complete(trailing, timeoutId); } function debounced() { @@ -7739,7 +7751,7 @@ result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = null; + args = thisArg = undefined; } return result; } @@ -7844,7 +7856,7 @@ * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) * method interface of `get`, `has`, and `set`. * * @static @@ -7905,6 +7917,52 @@ return memoized; } + /** + * Creates a function that runs each argument through a corresponding + * transform function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms] The functions to transform + * arguments, specified as individual functions or arrays of functions. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var modded = _.modArgs(function(x, y) { + * return [x, y]; + * }, square, doubled); + * + * modded(1, 2); + * // => [1, 4] + * + * modded(5, 10); + * // => [25, 20] + */ + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the @@ -8050,7 +8108,7 @@ * // => [3, 6, 9] */ var rearg = restParam(function(func, indexes) { - return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes)); + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); }); /** @@ -8196,10 +8254,7 @@ leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } - debounceOptions.leading = leading; - debounceOptions.maxWait = +wait; - debounceOptions.trailing = trailing; - return debounce(func, wait, debounceOptions); + return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing }); } /** @@ -8225,7 +8280,7 @@ */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; - return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []); } /*------------------------------------------------------------------------*/ @@ -8411,7 +8466,8 @@ * // => false */ function isArguments(value) { - return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag; + return isObjectLike(value) && isArrayLike(value) && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); } /** @@ -8491,14 +8547,7 @@ * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && - (objToString.call(value).indexOf('Element') > -1); - } - // Fallback for environments without DOM support. - if (!support.dom) { - isElement = function(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); - }; + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } /** @@ -8613,7 +8662,7 @@ /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). + * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite). * * @static * @memberOf _ @@ -8637,9 +8686,9 @@ * _.isFinite(Infinity); * // => false */ - var isFinite = nativeNumIsFinite || function(value) { + function isFinite(value) { return typeof value == 'number' && nativeIsFinite(value); - }; + } /** * Checks if `value` is classified as a `Function` object. @@ -8657,12 +8706,12 @@ * _.isFunction(/abc/); * // => false */ - var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) { + function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. - return objToString.call(value) == funcTag; - }; + return isObject(value) && objToString.call(value) == funcTag; + } /** * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. @@ -8786,7 +8835,7 @@ if (value == null) { return false; } - if (objToString.call(value) == funcTag) { + if (isFunction(value)) { return reIsNative.test(fnToString.call(value)); } return isObjectLike(value) && reIsHostCtor.test(value); @@ -8868,17 +8917,26 @@ * _.isPlainObject(Object.create(null)); * // => true */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && objToString.call(value) == objectTag)) { + function isPlainObject(value) { + var Ctor; + + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || + (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } - var valueOf = getNative(value, 'valueOf'), - objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); - - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + var result; + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } /** * Checks if `value` is classified as a `RegExp` object. @@ -8897,7 +8955,7 @@ * // => false */ function isRegExp(value) { - return isObjectLike(value) && objToString.call(value) == regexpTag; + return isObject(value) && objToString.call(value) == regexpTag; } /** @@ -9063,6 +9121,56 @@ /*------------------------------------------------------------------------*/ + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined` into the destination object. Subsequent sources + * overwrite property assignments of previous sources. If `customizer` is + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled + * by the method instead. The `customizer` is bound to `thisArg` and invoked + * with five arguments: (objectValue, sourceValue, key, object, source). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. + * @example + * + * var users = { + * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * }; + * + * var ages = { + * 'data': [{ 'age': 36 }, { 'age': 40 }] + * }; + * + * _.merge(users, ages); + * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } + * + * // using a customizer callback + * var object = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var other = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(object, other, function(a, b) { + * if (_.isArray(a)) { + * return a.concat(b); + * } + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } + */ + var merge = createAssigner(baseMerge); + /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. @@ -9071,7 +9179,7 @@ * (objectValue, sourceValue, key, object, source). * * **Note:** This method mutates `object` and is based on - * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign). + * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign). * * @static * @memberOf _ @@ -9138,7 +9246,7 @@ function create(prototype, properties, guard) { var result = baseCreate(prototype); if (guard && isIterateeCall(prototype, properties, guard)) { - properties = null; + properties = undefined; } return properties ? baseAssign(result, properties) : result; } @@ -9161,14 +9269,27 @@ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ - var defaults = restParam(function(args) { - var object = args[0]; - if (object == null) { - return object; - } - args.push(assignDefaults); - return assign.apply(undefined, args); - }); + var defaults = createDefaults(assign, assignDefaults); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); + * // => { 'user': { 'name': 'barney', 'age': 36 } } + * + */ + var defaultsDeep = createDefaults(merge, mergeDefaults); /** * This method is like `_.find` except that it returns the key of the first @@ -9495,7 +9616,7 @@ */ function invert(object, multiValue, guard) { if (guard && isIterateeCall(object, multiValue, guard)) { - multiValue = null; + multiValue = undefined; } var index = -1, props = keys(object), @@ -9524,7 +9645,7 @@ * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) * for more details. * * @static @@ -9548,7 +9669,7 @@ * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object == null ? null : object.constructor; + var Ctor = object == null ? undefined : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) { return shimKeys(object); @@ -9672,56 +9793,6 @@ */ var mapValues = createObjectMapper(); - /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * overwrite property assignments of previous sources. If `customizer` is - * provided it is invoked to produce the merged values of the destination and - * source properties. If `customizer` returns `undefined` merging is handled - * by the method instead. The `customizer` is bound to `thisArg` and invoked - * with five arguments: (objectValue, sourceValue, key, object, source). - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {Object} Returns `object`. - * @example - * - * var users = { - * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] - * }; - * - * var ages = { - * 'data': [{ 'age': 36 }, { 'age': 40 }] - * }; - * - * _.merge(users, ages); - * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } - * - * // using a customizer callback - * var object = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var other = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(object, other, function(a, b) { - * if (_.isArray(a)) { - * return a.concat(b); - * } - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } - */ - var merge = createAssigner(baseMerge); - /** * The opposite of `_.pick`; this method creates an object composed of the * own and inherited enumerable properties of `object` that are not omitted. @@ -9952,7 +10023,7 @@ if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : null); + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); } } else { accumulator = {}; @@ -10055,7 +10126,7 @@ */ function inRange(value, start, end) { start = +start || 0; - if (typeof end === 'undefined') { + if (end === undefined) { end = start; start = 0; } else { @@ -10093,7 +10164,7 @@ */ function random(min, max, floating) { if (floating && isIterateeCall(min, max, floating)) { - max = floating = null; + max = floating = undefined; } var noMin = min == null, noMax = max == null; @@ -10280,8 +10351,8 @@ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, '\\$&') - : string; + ? string.replace(reRegExpChars, escapeRegExpChar) + : (string || '(?:)'); } /** @@ -10338,8 +10409,8 @@ return string; } var mid = (length - strLength) / 2, - leftLength = floor(mid), - rightLength = ceil(mid); + leftLength = nativeFloor(mid), + rightLength = nativeCeil(mid); chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; @@ -10417,25 +10488,16 @@ * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - if (guard && isIterateeCall(string, radix, guard)) { + // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. + // Chrome fails to trim leading whitespace characters. + // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { radix = 0; + } else if (radix) { + radix = +radix; } - return nativeParseInt(string, radix); - } - // Fallback for environments with pre-ES5 implementations. - if (nativeParseInt(whitespace + '08') != 8) { - parseInt = function(string, radix, guard) { - // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. - // Chrome fails to trim leading whitespace characters. - // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. - if (guard ? isIterateeCall(string, radix, guard) : radix == null) { - radix = 0; - } else if (radix) { - radix = +radix; - } - string = trim(string); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); - }; + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); } /** @@ -10471,7 +10533,7 @@ if (n % 2) { result += string; } - n = floor(n / 2); + n = nativeFloor(n / 2); string += string; } while (n); @@ -10656,7 +10718,7 @@ var settings = lodash.templateSettings; if (otherOptions && isIterateeCall(string, options, otherOptions)) { - options = otherOptions = null; + options = otherOptions = undefined; } string = baseToString(string); options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); @@ -10892,7 +10954,7 @@ */ function trunc(string, options, guard) { if (guard && isIterateeCall(string, options, guard)) { - options = null; + options = undefined; } var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; @@ -10987,7 +11049,7 @@ */ function words(string, pattern, guard) { if (guard && isIterateeCall(string, pattern, guard)) { - pattern = null; + pattern = undefined; } string = baseToString(string); return string.match(pattern || reWords) || []; @@ -11063,7 +11125,7 @@ */ function callback(func, thisArg, guard) { if (guard && isIterateeCall(func, thisArg, guard)) { - thisArg = null; + thisArg = undefined; } return isObjectLike(func) ? matches(func) @@ -11264,8 +11326,8 @@ function mixin(object, source, options) { if (options == null) { var isObj = isObject(source), - props = isObj ? keys(source) : null, - methodNames = (props && props.length) ? baseFunctions(source, props) : null; + props = isObj ? keys(source) : undefined, + methodNames = (props && props.length) ? baseFunctions(source, props) : undefined; if (!(methodNames ? methodNames.length : isObj)) { methodNames = false; @@ -11304,9 +11366,7 @@ result.__chain__ = chainAll; return result; } - var args = [this.value()]; - push.apply(args, arguments); - return func.apply(object, args); + return func.apply(object, arrayPush([this.value()], arguments)); }; }(func)); } @@ -11327,7 +11387,7 @@ * var lodash = _.noConflict(); */ function noConflict() { - context._ = oldDash; + root._ = oldDash; return this; } @@ -11436,7 +11496,7 @@ */ function range(start, end, step) { if (step && isIterateeCall(start, end, step)) { - end = step = null; + end = step = undefined; } start = +start || 0; step = step == null ? 1 : (+step || 0); @@ -11450,7 +11510,7 @@ // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. var index = -1, - length = nativeMax(ceil((end - start) / (step || 1)), 0), + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (++index < length) { @@ -11488,7 +11548,7 @@ * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { - n = floor(n); + n = nativeFloor(n); // Exit early to avoid a JSC JIT bug in Safari 8 // where `Array(0)` is treated as `Array(1)`. @@ -11550,6 +11610,50 @@ return (+augend || 0) + (+addend || 0); } + /** + * Calculates `n` rounded up to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + + /** + * Calculates `n` rounded down to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + /** * Gets the maximum value of `collection`. If `collection` is empty or falsey * `-Infinity` is returned. If an iteratee function is provided it is invoked @@ -11648,6 +11752,28 @@ */ var min = createExtremum(lt, POSITIVE_INFINITY); + /** + * Calculates `n` rounded to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round. + * @param {number} [precision=0] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + /** * Gets the sum of the values in `collection`. * @@ -11682,17 +11808,11 @@ */ function sum(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; - } - var callback = getCallback(), - noIteratee = iteratee == null; - - if (!(noIteratee && callback === baseCallback)) { - noIteratee = false; - iteratee = callback(iteratee, thisArg, 3); + iteratee = undefined; } - return noIteratee - ? arraySum(isArray(collection) ? collection : toIterable(collection)) + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 + ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); } @@ -11739,6 +11859,7 @@ lodash.curryRight = curryRight; lodash.debounce = debounce; lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; @@ -11777,6 +11898,7 @@ lodash.method = method; lodash.methodOf = methodOf; lodash.mixin = mixin; + lodash.modArgs = modArgs; lodash.negate = negate; lodash.omit = omit; lodash.once = once; @@ -11852,6 +11974,7 @@ lodash.attempt = attempt; lodash.camelCase = camelCase; lodash.capitalize = capitalize; + lodash.ceil = ceil; lodash.clone = clone; lodash.cloneDeep = cloneDeep; lodash.deburr = deburr; @@ -11867,6 +11990,7 @@ lodash.findLastKey = findLastKey; lodash.findWhere = findWhere; lodash.first = first; + lodash.floor = floor; lodash.get = get; lodash.gt = gt; lodash.gte = gte; @@ -11915,6 +12039,7 @@ lodash.reduceRight = reduceRight; lodash.repeat = repeat; lodash.result = result; + lodash.round = round; lodash.runInContext = runInContext; lodash.size = size; lodash.snakeCase = snakeCase; @@ -11985,48 +12110,20 @@ lodash[methodName].placeholder = lodash; }); - // Add `LazyWrapper` methods that accept an `iteratee` value. - arrayEach(['dropWhile', 'filter', 'map', 'takeWhile'], function(methodName, type) { - var isFilter = type != LAZY_MAP_FLAG, - isDropWhile = type == LAZY_DROP_WHILE_FLAG; - - LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { - var filtered = this.__filtered__, - result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(), - iteratees = result.__iteratees__ || (result.__iteratees__ = []); - - iteratees.push({ - 'done': false, - 'count': 0, - 'index': 0, - 'iteratee': getCallback(iteratee, thisArg, 1), - 'limit': -1, - 'type': type - }); - - result.__filtered__ = filtered || isFilter; - return result; - }; - }); - // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. arrayEach(['drop', 'take'], function(methodName, index) { - var whileName = methodName + 'While'; - LazyWrapper.prototype[methodName] = function(n) { - var filtered = this.__filtered__, - result = (filtered && !index) ? this.dropWhile() : this.clone(); + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); - n = n == null ? 1 : nativeMax(floor(n) || 0, 0); + var result = this.clone(); if (filtered) { - if (index) { - result.__takeCount__ = nativeMin(result.__takeCount__, n); - } else { - last(result.__iteratees__).limit = n; - } + result.__takeCount__ = nativeMin(result.__takeCount__, n); } else { - var views = result.__views__ || (result.__views__ = []); - views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); + result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); } return result; }; @@ -12034,9 +12131,18 @@ LazyWrapper.prototype[methodName + 'Right'] = function(n) { return this.reverse()[methodName](n).reverse(); }; + }); + + // Add `LazyWrapper` methods that accept an `iteratee` value. + arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { + var type = index + 1, + isFilter = type != LAZY_MAP_FLAG; - LazyWrapper.prototype[methodName + 'RightWhile'] = function(predicate, thisArg) { - return this.reverse()[whileName](predicate, thisArg).reverse(); + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ 'iteratee': getCallback(iteratee, thisArg, 1), 'type': type }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; }; }); @@ -12054,7 +12160,7 @@ var dropName = 'drop' + (index ? '' : 'Right'); LazyWrapper.prototype[methodName] = function() { - return this[dropName](1); + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); }; }); @@ -12083,10 +12189,13 @@ start = start == null ? 0 : (+start || 0); var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } if (start < 0) { - result = this.takeRight(-start); + result = result.takeRight(-start); } else if (start) { - result = this.drop(start); + result = result.drop(start); } if (end !== undefined) { end = (+end || 0); @@ -12095,21 +12204,25 @@ return result; }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { - return this.drop(0); + return this.take(POSITIVE_INFINITY); }; // Add `LazyWrapper` methods to `lodash.prototype`. baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var lodashFunc = lodash[methodName]; + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), + retUnwrapped = /^(?:first|last)$/.test(methodName), + lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName]; + if (!lodashFunc) { return; } - var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), - retUnwrapped = /^(?:first|last)$/.test(methodName); - lodash.prototype[methodName] = function() { - var args = arguments, + var args = retUnwrapped ? [1] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, @@ -12118,28 +12231,30 @@ useLazy = isLazy || isArray(value); if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { - // avoid lazy use if the iteratee has a "length" value other than `1` + // Avoid lazy use if the iteratee has a "length" value other than `1`. isLazy = useLazy = false; } - var onlyLazy = isLazy && !isHybrid; - if (retUnwrapped && !chainAll) { - return onlyLazy - ? func.call(value) - : lodashFunc.call(lodash, this.value()); - } var interceptor = function(value) { - var otherArgs = [value]; - push.apply(otherArgs, args); - return lodashFunc.apply(lodash, otherArgs); + return (retUnwrapped && chainAll) + ? lodashFunc(value, 1)[0] + : lodashFunc.apply(undefined, arrayPush([value], args)); }; - if (useLazy) { - var wrapper = onlyLazy ? value : new LazyWrapper(this), - result = func.apply(wrapper, args); - if (!retUnwrapped && (isHybrid || result.__actions__)) { - var actions = result.__actions__ || (result.__actions__ = []); - actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined }, + onlyLazy = isLazy && !isHybrid; + + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); return new LodashWrapper(result, chainAll); } return this.thru(interceptor); @@ -12147,7 +12262,7 @@ }); // Add `Array` and `String` methods to `lodash.prototype`. - arrayEach(['concat', 'join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { + arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); @@ -12174,7 +12289,7 @@ } }); - realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': null }]; + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }]; // Add functions to the lazy wrapper. LazyWrapper.prototype.clone = lazyClone; @@ -12184,6 +12299,7 @@ // Add chaining functions to the `lodash` wrapper. lodash.prototype.chain = wrapperChain; lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; lodash.prototype.plant = wrapperPlant; lodash.prototype.reverse = wrapperReverse; lodash.prototype.toString = wrapperToString; diff --git a/lodash.min.js b/lodash.min.js index 4d6e9ff0bf..f57c37beeb 100644 --- a/lodash.min.js +++ b/lodash.min.js @@ -1,98 +1,99 @@ /** * @license - * lodash 3.9.3 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE + * lodash 3.10.0 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE * Build: `lodash modern -o ./lodash.js` */ -;(function(){function n(n,t){if(n!==t){var r=null===n,e=n===m,u=n===n,i=null===t,o=t===m,f=t===t;if(n>t&&!i||!u||r&&!o&&f||e&&f)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 _(n,t){for(var r=-1,e=n.length,u=-1,i=[];++ro(t,l,0)&&u.push(l);return u}function at(n,t){var r=true;return Mu(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ct(n,t,r,e){var u=e,i=u;return Mu(n,function(n,o,f){o=+t(n,o,f),(r(o,u)||o===e&&o===i)&&(u=o,i=n)}),i}function st(n,t){var r=[];return Mu(n,function(n,e,u){t(n,e,u)&&r.push(n); -}),r}function pt(n,t,r,e){var u;return r(n,function(n,r,i){return t(n,r,i)?(u=e?r:n,false):void 0}),u}function ht(n,t,r){for(var e=-1,u=n.length,i=-1,o=[];++et&&(t=-t>u?0:u+t),r=r===m||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Me(u);++eu(l,s,0)&&((t||f)&&l.push(s),a.push(c))}return a}function Ft(n,t){for(var r=-1,e=t.length,u=Me(e);++r>>1,o=n[i];(r?o<=t:ou?m:i,u=1);++earguments.length;return typeof e=="function"&&i===m&&Ti(r)?n(r,e,u,o):Et(r,mr(e,i,4),u,o,t)}}function sr(n,t,r,e,u,i,o,f,l,a){function c(){for(var w=arguments.length,A=w,j=Me(w);A--;)j[A]=arguments[A];if(e&&(j=qt(j,e,u)),i&&(j=Dt(j,i,o)),v||y){var A=c.placeholder,k=_(j,A),w=w-k.length; -if(wt?0:t)):[]}function qr(n,t,r){var e=n?n.length:0;return e?((r?Cr(n,t,r):null==t)&&(t=1), -t=e-(+t||0),Ct(n,0,0>t?0:t)):[]}function Dr(n){return n?n[0]:m}function Kr(n,t,e){var u=n?n.length:0;if(!u)return-1;if(typeof e=="number")e=0>e?ku(u+e,0):e;else if(e)return e=zt(n,t),n=n[e],(t===t?t===n:n!==n)?e:-1;return r(n,t,e||0)}function Vr(n){var t=n?n.length:0;return t?n[t-1]:m}function Yr(n){return Pr(n,1)}function Zr(n,t,e,u){if(!n||!n.length)return[];null!=t&&typeof t!="boolean"&&(u=e,e=Cr(n,t,u)?null:t,t=false);var i=mr();if((null!=e||i!==it)&&(e=i(e,u,3)),t&&br()==r){t=e;var o;e=-1,u=n.length; -for(var i=-1,f=[];++er?ku(u+r,0):r||0,typeof n=="string"||!Ti(n)&&me(n)?rt?0:+t||0,e);++r=n&&(t=null),r}}function fe(n,t,r){function e(){var r=t-(wi()-a);0>=r||r>t?(f&&cu(f),r=p,f=s=p=m,r&&(h=wi(),l=n.apply(c,o),s||f||(o=c=null))):s=gu(e,r)}function u(){s&&cu(s),f=s=p=m,(v||_!==t)&&(h=wi(),l=n.apply(c,o),s||f||(o=c=null))}function i(){if(o=arguments,a=wi(),c=this,p=v&&(s||!g),false===_)var r=g&&!s;else{f||g||(h=a);var i=_-(a-h),y=0>=i||i>_;y?(f&&(f=cu(f)),h=a,l=n.apply(c,o)):f||(f=gu(u,i))}return y&&s?s=cu(s):s||t===_||(s=gu(e,t)),r&&(y=true,l=n.apply(c,o)), -!y||s||f||(o=c=null),l}var o,f,l,a,c,s,p,h=0,_=false,v=true;if(typeof n!="function")throw new Je(N);if(t=0>t?0:+t||0,true===r)var g=true,v=false;else ve(r)&&(g=r.leading,_="maxWait"in r&&ku(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return i.cancel=function(){s&&cu(s),f&&cu(f),f=s=p=m},i}function le(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),r.cache=i.set(u,e),e)}if(typeof n!="function"||t&&typeof t!="function")throw new Je(N);return r.cache=new le.Cache, -r}function ae(n,t){if(typeof n!="function")throw new Je(N);return t=ku(t===m?n.length-1:+t||0,0),function(){for(var r=arguments,e=-1,u=ku(r.length-t,0),i=Me(u);++et}function se(n){return p(n)&&Ir(n)&&uu.call(n)==z}function pe(n){return!!n&&1===n.nodeType&&p(n)&&-1t||!n||!Au(t))return r;do t%2&&(r+=n),t=su(t/2),n+=n;while(t);return r}function Se(n,t,r){var e=n;return(n=u(n))?(r?Cr(e,t,r):null==t)?n.slice(v(n),g(n)+1):(t+="",n.slice(i(n,t),o(n,t)+1)):n}function Te(n,t,r){ -return r&&Cr(n,t,r)&&(t=null),n=u(n),n.match(t||Wn)||[]}function Ue(n,t,r){return r&&Cr(n,t,r)&&(t=null),p(n)?Ne(n):it(n,t)}function $e(n){return function(){return n}}function Fe(n){return n}function Ne(n){return xt(ot(n,true))}function Le(n,t,r){if(null==r){var e=ve(t),u=e?Ki(t):null;((u=u&&u.length?yt(t,u):null)?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=yt(t,Ki(t)));var i=true,e=-1,o=$i(n),f=u.length;false===r?i=false:ve(r)&&"chain"in r&&(i=r.chain);for(;++e=S)return r}else n=0;return Ku(r,e)}}(),Ju=ae(function(n,t){return Ir(n)?lt(n,ht(t,false,true)):[]}),Xu=tr(),Hu=tr(true),Qu=ae(function(n){for(var t=n.length,e=t,u=Me(c),i=br(),o=i==r,f=[];e--;){var l=n[e]=Ir(l=n[e])?l:[];u[e]=o&&120<=l.length?Vu(e&&l):null}var o=n[0],a=-1,c=o?o.length:0,s=u[0]; -n:for(;++a(s?qn(s,l):i(f,l,0))){for(e=t;--e;){var p=u[e];if(0>(p?qn(p,l):i(n[e],l,0)))continue n}s&&s.push(l),f.push(l)}return f}),ni=ae(function(t,r){r=ht(r);var e=et(t,r);return Rt(t,r.sort(n)),e}),ti=_r(),ri=_r(true),ei=ae(function(n){return $t(ht(n,false,true))}),ui=ae(function(n,t){return Ir(n)?lt(n,t):[]}),ii=ae(Gr),oi=ae(function(n){var t=n.length,r=2--n?t.apply(this,arguments):void 0}},Nn.ary=function(n,t,r){return r&&Cr(n,t,r)&&(t=null),t=n&&null==t?n.length:ku(+t||0,0),vr(n,I,null,null,null,null,t)},Nn.assign=Ni,Nn.at=fi,Nn.before=oe,Nn.bind=bi,Nn.bindAll=xi,Nn.bindKey=Ai,Nn.callback=Ue,Nn.chain=Hr,Nn.chunk=function(n,t,r){t=(r?Cr(n,t,r):null==t)?1:ku(+t||1,1),r=0;for(var e=n?n.length:0,u=-1,i=Me(au(e/t));rr&&(r=-r>u?0:u+r),e=e===m||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;rt?0:t)):[]},Nn.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?Cr(n,t,r):null==t)&&(t=1),t=e-(+t||0),Ct(n,0>t?0:t)):[]},Nn.takeRightWhile=function(n,t,r){return n&&n.length?Nt(n,mr(t,r,3),false,true):[]},Nn.takeWhile=function(n,t,r){return n&&n.length?Nt(n,mr(t,r,3)):[]; -},Nn.tap=function(n,t,r){return t.call(r,n),n},Nn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new Je(N);return false===r?e=false:ve(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Fn.leading=e,Fn.maxWait=+t,Fn.trailing=u,fe(n,t,Fn)},Nn.thru=Qr,Nn.times=function(n,t,r){if(n=su(n),1>n||!Au(n))return[];var e=-1,u=Me(Ou(n,4294967295));for(t=Mt(t,r,1);++ee?u[e]=t(e):t(e);return u},Nn.toArray=xe,Nn.toPlainObject=Ae,Nn.transform=function(n,t,r,e){var u=Ti(n)||we(n); -return t=mr(t,e,4),null==r&&(u||ve(n)?(e=n.constructor,r=u?Ti(n)?new e:[]:Bu($i(e)?e.prototype:null)):r={}),(u?Kn:vt)(n,function(n,e,u){return t(r,n,e,u)}),r},Nn.union=ei,Nn.uniq=Zr,Nn.unzip=Gr,Nn.unzipWith=Jr,Nn.values=Re,Nn.valuesIn=function(n){return Ft(n,ke(n))},Nn.where=function(n,t){return te(n,xt(t))},Nn.without=ui,Nn.wrap=function(n,t){return t=null==t?Fe:t,vr(t,O,null,[n],[])},Nn.xor=function(){for(var n=-1,t=arguments.length;++nr?0:+r||0,e),r-=t.length,0<=r&&n.indexOf(t,r)==r},Nn.escape=function(n){return(n=u(n))&&pn.test(n)?n.replace(cn,a):n},Nn.escapeRegExp=Ee,Nn.every=ne,Nn.find=ai,Nn.findIndex=Xu,Nn.findKey=zi,Nn.findLast=ci,Nn.findLastIndex=Hu,Nn.findLastKey=Bi,Nn.findWhere=function(n,t){return ai(n,xt(t))},Nn.first=Dr,Nn.get=function(n,t,r){ -return n=null==n?m:dt(n,Br(t),t+""),n===m?r:n},Nn.gt=ce,Nn.gte=function(n,t){return n>=t},Nn.has=function(n,t){if(null==n)return false;var r=ru.call(n,t);if(!r&&!Wr(t)){if(t=Br(t),n=1==t.length?n:dt(n,Ct(t,0,-1)),null==n)return false;t=Vr(t),r=ru.call(n,t)}return r||Tr(n.length)&&Er(t,n.length)&&(Ti(n)||se(n))},Nn.identity=Fe,Nn.includes=re,Nn.indexOf=Kr,Nn.inRange=function(n,t,r){return t=+t||0,"undefined"===typeof r?(r=t,t=0):r=+r||0,n>=Ou(t,r)&&nr?ku(e+r,0):Ou(r||0,e-1))+1;else if(r)return u=zt(n,t,true)-1,n=n[u],(t===t?t===n:n!==n)?u:-1;if(t!==t)return s(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},Nn.lt=be,Nn.lte=function(n,t){return n<=t},Nn.max=oo,Nn.min=fo,Nn.noConflict=function(){return h._=iu,this},Nn.noop=ze,Nn.now=wi, -Nn.pad=function(n,t,r){n=u(n),t=+t;var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Nn.sum=function(n,t,r){r&&Cr(n,t,r)&&(t=null);var e=mr(),u=null==t;if(u&&e===it||(u=false, -t=e(t,r,3)),u){for(n=Ti(n)?n:Lr(n),t=n.length,r=0;t--;)r+=+n[t]||0;n=r}else n=Ut(n,t);return n},Nn.template=function(n,t,r){var e=Nn.templateSettings;r&&Cr(n,t,r)&&(t=r=null),n=u(n),t=tt(rt({},r||t),e,nt),r=tt(rt({},t.imports),e.imports,nt);var i,o,f=Ki(r),l=Ft(r,f),a=0;r=t.interpolate||En;var s="__p+='";r=Ze((t.escape||En).source+"|"+r.source+"|"+(r===vn?An:En).source+"|"+(t.evaluate||En).source+"|$","g");var p="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,u,f,l){ -return e||(e=u),s+=n.slice(a,l).replace(Cn,c),r&&(i=true,s+="'+__e("+r+")+'"),f&&(o=true,s+="';"+f+";\n__p+='"),e&&(s+="'+((__t=("+e+"))==null?'':__t)+'"),a=l+t.length,t}),s+="';",(t=t.variable)||(s="with(obj){"+s+"}"),s=(o?s.replace(on,""):s).replace(fn,"$1").replace(ln,"$1;"),s="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(i?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+s+"return __p}",t=eo(function(){return De(f,p+"return "+s).apply(m,l); -}),t.source=s,_e(t))throw t;return t},Nn.trim=Se,Nn.trimLeft=function(n,t,r){var e=n;return(n=u(n))?n.slice((r?Cr(e,t,r):null==t)?v(n):i(n,t+"")):n},Nn.trimRight=function(n,t,r){var e=n;return(n=u(n))?(r?Cr(e,t,r):null==t)?n.slice(0,g(n)+1):n.slice(0,o(n,t+"")+1):n},Nn.trunc=function(n,t,r){r&&Cr(n,t,r)&&(t=null);var e=C;if(r=W,null!=t)if(ve(t)){var i="separator"in t?t.separator:i,e="length"in t?+t.length||0:e;r="omission"in t?u(t.omission):r}else e=+t||0;if(n=u(n),e>=n.length)return n;if(e-=r.length, -1>e)return r;if(t=n.slice(0,e),null==i)return t+r;if(de(i)){if(n.slice(e).search(i)){var o,f=n.slice(0,e);for(i.global||(i=Ze(i.source,(jn.exec(i)||"")+"g")),i.lastIndex=0;n=i.exec(f);)o=n.index;t=t.slice(0,null==o?e:o)}}else n.indexOf(i,e)!=e&&(i=t.lastIndexOf(i),-1u.__dir__?"Right":"")}),u},Bn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse(); -},Bn.prototype[n+"RightWhile"]=function(n,t){return this.reverse()[r](n,t).reverse()}}),Kn(["first","last"],function(n,t){var r="take"+(t?"Right":"");Bn.prototype[n]=function(){return this[r](1).value()[0]}}),Kn(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right");Bn.prototype[n]=function(){return this[r](1)}}),Kn(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?xt:Be;Bn.prototype[n]=function(n){return this[r](e(n))}}),Bn.prototype.compact=function(){return this.filter(Fe)},Bn.prototype.reject=function(n,t){ -return n=mr(n,t,1),this.filter(function(t){return!n(t)})},Bn.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=this;return 0>n?r=this.takeRight(-n):n&&(r=this.drop(n)),t!==m&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r},Bn.prototype.toArray=function(){return this.drop(0)},vt(Bn.prototype,function(n,t){var r=Nn[t];if(r){var e=/^(?:filter|map|reject)|While$/.test(t),u=/^(?:first|last)$/.test(t);Nn.prototype[t]=function(){function t(n){return n=[n],_u.apply(n,i),r.apply(Nn,n)}var i=arguments,o=this.__chain__,f=this.__wrapped__,l=!!this.__actions__.length,a=f instanceof Bn,c=i[0],s=a||Ti(f); -return s&&e&&typeof c=="function"&&1!=c.length&&(a=s=false),a=a&&!l,u&&!o?a?n.call(f):r.call(Nn,this.value()):s?(f=n.apply(a?f:new Bn(this),i),u||!l&&!f.__actions__||(f.__actions__||(f.__actions__=[])).push({func:Qr,args:[t],thisArg:Nn}),new zn(f,o)):this.thru(t)}}}),Kn("concat join pop push replace shift sort splice split unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?Qe:Xe)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|replace|shift)$/.test(n);Nn.prototype[n]=function(){ -var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),vt(Bn.prototype,function(n,t){var r=Nn[t];if(r){var e=r.name;(Lu[e]||(Lu[e]=[])).push({name:t,func:r})}}),Lu[sr(null,x).name]=[{name:"wrapper",func:null}],Bn.prototype.clone=function(){var n=this.__actions__,t=this.__iteratees__,r=this.__views__,e=new Bn(this.__wrapped__);return e.__actions__=n?Dn(n):null,e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=t?Dn(t):null, -e.__takeCount__=this.__takeCount__,e.__views__=r?Dn(r):null,e},Bn.prototype.reverse=function(){if(this.__filtered__){var n=new Bn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},Bn.prototype.value=function(){var n=this.__wrapped__.value();if(!Ti(n))return Lt(n,this.__actions__);var t,r=this.__dir__,e=0>r;t=n.length;for(var u=this.__views__,i=0,o=-1,f=u?u.length:0;++op.index:u=_:!h(s))))continue n}else if(p=h(s),_==F)s=p;else if(!p){if(_==$)continue n;break n}}a[l++]=s}return a},Nn.prototype.chain=function(){ -return Hr(this)},Nn.prototype.commit=function(){return new zn(this.value(),this.__chain__)},Nn.prototype.plant=function(n){for(var t,r=this;r instanceof Ln;){var e=Mr(r);t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},Nn.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Bn?(this.__actions__.length&&(n=new Bn(this)),new zn(n.reverse(),this.__chain__)):this.thru(function(n){return n.reverse()})},Nn.prototype.toString=function(){return this.value()+""},Nn.prototype.run=Nn.prototype.toJSON=Nn.prototype.valueOf=Nn.prototype.value=function(){ -return Lt(this.__wrapped__,this.__actions__)},Nn.prototype.collect=Nn.prototype.map,Nn.prototype.head=Nn.prototype.first,Nn.prototype.select=Nn.prototype.filter,Nn.prototype.tail=Nn.prototype.rest,Nn}var m,w="3.9.3",b=1,x=2,A=4,j=8,k=16,O=32,R=64,I=128,E=256,C=30,W="...",S=150,T=16,U=0,$=1,F=2,N="Expected a function",L="__lodash_placeholder__",z="[object Arguments]",B="[object Array]",M="[object Boolean]",P="[object Date]",q="[object Error]",D="[object Function]",K="[object Number]",V="[object Object]",Y="[object RegExp]",Z="[object String]",G="[object ArrayBuffer]",J="[object Float32Array]",X="[object Float64Array]",H="[object Int8Array]",Q="[object Int16Array]",nn="[object Int32Array]",tn="[object Uint8Array]",rn="[object Uint8ClampedArray]",en="[object Uint16Array]",un="[object Uint32Array]",on=/\b__p\+='';/g,fn=/\b(__p\+=)''\+/g,ln=/(__e\(.*?\)|\b__t\))\+'';/g,an=/&(?:amp|lt|gt|quot|#39|#96);/g,cn=/[&<>"'`]/g,sn=RegExp(an.source),pn=RegExp(cn.source),hn=/<%-([\s\S]+?)%>/g,_n=/<%([\s\S]+?)%>/g,vn=/<%=([\s\S]+?)%>/g,gn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,yn=/^\w*$/,dn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g,mn=/[.*+?^${}()|[\]\/\\]/g,wn=RegExp(mn.source),bn=/[\u0300-\u036f\ufe20-\ufe23]/g,xn=/\\(\\)?/g,An=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,jn=/\w*$/,kn=/^0[xX]/,On=/^\[object .+?Constructor\]$/,Rn=/^\d+$/,In=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,En=/($^)/,Cn=/['\n\r\u2028\u2029\\]/g,Wn=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?=[A-Z\\xc0-\\xd6\\xd8-\\xde][a-z\\xdf-\\xf6\\xf8-\\xff]+)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+|[A-Z\\xc0-\\xd6\\xd8-\\xde]+|[0-9]+","g"),Sn=" \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",Tn="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseFloat parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window".split(" "),Un={}; -Un[J]=Un[X]=Un[H]=Un[Q]=Un[nn]=Un[tn]=Un[rn]=Un[en]=Un[un]=true,Un[z]=Un[B]=Un[G]=Un[M]=Un[P]=Un[q]=Un[D]=Un["[object Map]"]=Un[K]=Un[V]=Un[Y]=Un["[object Set]"]=Un[Z]=Un["[object WeakMap]"]=false;var $n={};$n[z]=$n[B]=$n[G]=$n[M]=$n[P]=$n[J]=$n[X]=$n[H]=$n[Q]=$n[nn]=$n[K]=$n[V]=$n[Y]=$n[Z]=$n[tn]=$n[rn]=$n[en]=$n[un]=true,$n[q]=$n[D]=$n["[object Map]"]=$n["[object Set]"]=$n["[object WeakMap]"]=false;var Fn={leading:false,maxWait:0,trailing:false},Nn={"\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"},Ln={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},zn={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Bn={"function":true,object:true},Mn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Pn=Bn[typeof exports]&&exports&&!exports.nodeType&&exports,qn=Bn[typeof module]&&module&&!module.nodeType&&module,Dn=Bn[typeof self]&&self&&self.Object&&self,Kn=Bn[typeof window]&&window&&window.Object&&window,Vn=qn&&qn.exports===Pn&&Pn,Yn=Pn&&qn&&typeof global=="object"&&global&&global.Object&&global||Kn!==(this&&this.window)&&Kn||Dn||this,Zn=d(); -typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Yn._=Zn, define(function(){return Zn})):Pn&&qn?Vn?(qn.exports=Zn)._=Zn:Pn._=Zn:Yn._=Zn}).call(this); \ No newline at end of file +;(function(){function n(n,t){if(n!==t){var r=null===n,e=n===w,u=n===n,o=null===t,i=t===w,f=t===t;if(n>t&&!o||!u||r&&!i&&f||e&&f)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,t){for(var r=-1,e=n.length,u=-1,o=[];++r=F&&gu&&lu?new Dn(t):null,c=t.length;a&&(i=Mn,f=false,t=a);n:for(;++oi(t,a,0)&&u.push(a);return u}function at(n,t){var r=true;return Su(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ct(n,t,r,e){var u=e,o=u;return Su(n,function(n,i,f){i=+t(n,i,f),(r(i,u)||i===e&&i===o)&&(u=i, +o=n)}),o}function lt(n,t){var r=[];return Su(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function st(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 pt(n,t,r,e){e||(e=[]);for(var u=-1,o=n.length;++ut&&(t=-t>u?0:u+t),r=r===w||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Be(u);++e=c)break n;o=e[o],u*="asc"===o||true===o?1:-1;break n}u=t.b-r.b}return u})}function $t(n,t){ +var r=0;return Su(n,function(n,e,u){r+=+t(n,e,u)||0}),r}function St(n,t){var e=-1,u=xr(),o=n.length,i=u==r,f=i&&o>=F,a=f&&gu&&lu?new Dn(void 0):null,c=[];a?(u=Mn,i=false):(f=false,a=t?[]:c);n:for(;++eu(a,s,0)&&((t||f)&&a.push(s),c.push(l))}return c}function Ft(n,t){for(var r=-1,e=t.length,u=Be(e);++r>>1,i=n[o];(r?i<=t:iu?w:o,u=1);++e=F)return t.plant(e).value();for(var u=0,n=r?o[u].apply(this,n):e;++uarguments.length;return typeof e=="function"&&o===w&&Oo(r)?n(r,e,u,i):Ot(r,wr(e,o,4),u,i,t)}}function sr(n,t,r,e,u,o,i,f,a,c){function l(){for(var m=arguments.length,b=m,j=Be(m);b--;)j[b]=arguments[b];if(e&&(j=Mt(j,e,u)),o&&(j=qt(j,o,i)),_||y){var b=l.placeholder,k=v(j,b),m=m-k.length;if(mt?0:t)):[]}function Pr(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0,0>t?0:t)):[]}function Kr(n){return n?n[0]:w}function Vr(n,t,e){var u=n?n.length:0;if(!u)return-1;if(typeof e=="number")e=0>e?bu(u+e,0):e;else if(e)return e=Lt(n,t), +er?bu(u+r,0):r||0,typeof n=="string"||!Oo(n)&&be(n)?r<=u&&-1t?0:+t||0,e);++r=n&&(t=w),r}}function ae(n,t,r){function e(t,r){r&&iu(r),a=p=h=w,t&&(_=ho(),c=n.apply(s,f),p||a||(f=s=w))}function u(){var n=t-(ho()-l);0>=n||n>t?e(h,a):p=su(u,n)}function o(){e(g,p); +}function i(){if(f=arguments,l=ho(),s=this,h=g&&(p||!y),false===v)var r=y&&!p;else{a||y||(_=l);var e=v-(l-_),i=0>=e||e>v;i?(a&&(a=iu(a)),_=l,c=n.apply(s,f)):a||(a=su(o,e))}return i&&p?p=iu(p):p||t===v||(p=su(u,t)),r&&(i=true,c=n.apply(s,f)),!i||p||a||(f=s=w),c}var f,a,c,l,s,p,h,_=0,v=false,g=true;if(typeof n!="function")throw new Ge(L);if(t=0>t?0:+t||0,true===r)var y=true,g=false;else ge(r)&&(y=!!r.leading,v="maxWait"in r&&bu(+r.maxWait||0,t),g="trailing"in r?!!r.trailing:g);return i.cancel=function(){p&&iu(p),a&&iu(a), +_=0,a=p=h=w},i}function ce(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=n.apply(this,e),r.cache=o.set(u,e),e)}if(typeof n!="function"||t&&typeof t!="function")throw new Ge(L);return r.cache=new ce.Cache,r}function le(n,t){if(typeof n!="function")throw new Ge(L);return t=bu(t===w?n.length-1:+t||0,0),function(){for(var r=arguments,e=-1,u=bu(r.length-t,0),o=Be(u);++et}function pe(n){return h(n)&&Er(n)&&nu.call(n,"callee")&&!cu.call(n,"callee")}function he(n,t,r,e){return e=(r=typeof r=="function"?Bt(r,e,3):w)?r(n,t):w,e===w?dt(n,t,r):!!e}function _e(n){return h(n)&&typeof n.message=="string"&&ru.call(n)==P}function ve(n){return ge(n)&&ru.call(n)==K}function ge(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function ye(n){ +return null==n?false:ve(n)?uu.test(Qe.call(n)):h(n)&&Rn.test(n)}function de(n){return typeof n=="number"||h(n)&&ru.call(n)==V}function me(n){var t;if(!h(n)||ru.call(n)!=Z||pe(n)||!(nu.call(n,"constructor")||(t=n.constructor,typeof t!="function"||t instanceof t)))return false;var r;return ht(n,function(n,t){r=t}),r===w||nu.call(n,r)}function we(n){return ge(n)&&ru.call(n)==Y}function be(n){return typeof n=="string"||h(n)&&ru.call(n)==G}function xe(n){return h(n)&&Sr(n.length)&&!!Sn[ru.call(n)]}function Ae(n,t){ +return nt||!n||!mu(t))return r;do t%2&&(r+=n),t=yu(t/2),n+=n;while(t);return r}function We(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(g(n),y(n)+1):(t+="",n.slice(o(n,t),i(n,t)+1)):n}function $e(n,t,r){return r&&Ur(n,t,r)&&(t=w),n=u(n),n.match(t||Wn)||[]}function Se(n,t,r){return r&&Ur(n,t,r)&&(t=w),h(n)?Ne(n):ut(n,t)}function Fe(n){ +return n}function Ne(n){return bt(ot(n,true))}function Te(n,t,r){if(null==r){var e=ge(t),u=e?zo(t):w;((u=u&&u.length?gt(t,u):w)?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=gt(t,zo(t)));var o=true,e=-1,i=ve(n),f=u.length;false===r?o=false:ge(r)&&"chain"in r&&(o=r.chain);for(;++e=$)return r}else n=0;return Lu(r,e)}}(),Mu=le(function(n,t){ +return h(n)&&Er(n)?ft(n,pt(t,false,true)):[]}),qu=tr(),Pu=tr(true),Ku=le(function(n){for(var t=n.length,e=t,u=Be(l),o=xr(),i=o==r,f=[];e--;){var a=n[e]=Er(a=n[e])?a:[];u[e]=i&&120<=a.length&&gu&&lu?new Dn(e&&a):null}var i=n[0],c=-1,l=i?i.length:0,s=u[0];n:for(;++c(s?Mn(s,a):o(f,a,0))){for(e=t;--e;){var p=u[e];if(0>(p?Mn(p,a):o(n[e],a,0)))continue n}s&&s.push(a),f.push(a)}return f}),Vu=le(function(t,r){r=pt(r);var e=rt(t,r);return It(t,r.sort(n)),e}),Zu=vr(),Yu=vr(true),Gu=le(function(n){return St(pt(n,false,true)); +}),Ju=le(function(n,t){return Er(n)?ft(n,t):[]}),Xu=le(Jr),Hu=le(function(n){var t=n.length,r=2--n?t.apply(this,arguments):void 0}},Nn.ary=function(n,t,r){return r&&Ur(n,t,r)&&(t=w),t=n&&null==t?n.length:bu(+t||0,0),gr(n,E,w,w,w,w,t)},Nn.assign=Co,Nn.at=no,Nn.before=fe,Nn.bind=_o,Nn.bindAll=vo,Nn.bindKey=go,Nn.callback=Se,Nn.chain=Qr,Nn.chunk=function(n,t,r){t=(r?Ur(n,t,r):null==t)?1:bu(yu(t)||1,1),r=0;for(var e=n?n.length:0,u=-1,o=Be(vu(e/t));rr&&(r=-r>u?0:u+r),e=e===w||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;rt?0:t)):[]},Nn.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0>t?0:t)):[]},Nn.takeRightWhile=function(n,t,r){ +return n&&n.length?Nt(n,wr(t,r,3),false,true):[]},Nn.takeWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3)):[]},Nn.tap=function(n,t,r){return t.call(r,n),n},Nn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new Ge(L);return false===r?e=false:ge(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ae(n,t,{leading:e,maxWait:+t,trailing:u})},Nn.thru=ne,Nn.times=function(n,t,r){if(n=yu(n),1>n||!mu(n))return[];var e=-1,u=Be(xu(n,4294967295));for(t=Bt(t,r,1);++ee?u[e]=t(e):t(e); +return u},Nn.toArray=je,Nn.toPlainObject=ke,Nn.transform=function(n,t,r,e){var u=Oo(n)||xe(n);return t=wr(t,e,4),null==r&&(u||ge(n)?(e=n.constructor,r=u?Oo(n)?new e:[]:$u(ve(e)?e.prototype:w)):r={}),(u?Pn:_t)(n,function(n,e,u){return t(r,n,e,u)}),r},Nn.union=Gu,Nn.uniq=Gr,Nn.unzip=Jr,Nn.unzipWith=Xr,Nn.values=Ee,Nn.valuesIn=function(n){return Ft(n,Re(n))},Nn.where=function(n,t){return re(n,bt(t))},Nn.without=Ju,Nn.wrap=function(n,t){return t=null==t?Fe:t,gr(t,R,w,[n],[])},Nn.xor=function(){for(var n=-1,t=arguments.length;++nr?0:+r||0,e),r-=t.length,0<=r&&n.indexOf(t,r)==r},Nn.escape=function(n){return(n=u(n))&&hn.test(n)?n.replace(sn,c):n},Nn.escapeRegExp=function(n){return(n=u(n))&&bn.test(n)?n.replace(wn,l):n||"(?:)"},Nn.every=te,Nn.find=ro,Nn.findIndex=qu,Nn.findKey=$o,Nn.findLast=eo, +Nn.findLastIndex=Pu,Nn.findLastKey=So,Nn.findWhere=function(n,t){return ro(n,bt(t))},Nn.first=Kr,Nn.floor=ni,Nn.get=function(n,t,r){return n=null==n?w:yt(n,Dr(t),t+""),n===w?r:n},Nn.gt=se,Nn.gte=function(n,t){return n>=t},Nn.has=function(n,t){if(null==n)return false;var r=nu.call(n,t);if(!r&&!Wr(t)){if(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),null==n)return false;t=Zr(t),r=nu.call(n,t)}return r||Sr(n.length)&&Cr(t,n.length)&&(Oo(n)||pe(n))},Nn.identity=Fe,Nn.includes=ee,Nn.indexOf=Vr,Nn.inRange=function(n,t,r){ +return t=+t||0,r===w?(r=t,t=0):r=+r||0,n>=xu(t,r)&&nr?bu(e+r,0):xu(r||0,e-1))+1;else if(r)return u=Lt(n,t,true)-1,n=n[u],(t===t?t===n:n!==n)?u:-1; +if(t!==t)return p(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},Nn.lt=Ae,Nn.lte=function(n,t){return n<=t},Nn.max=ti,Nn.min=ri,Nn.noConflict=function(){return Zn._=eu,this},Nn.noop=Le,Nn.now=ho,Nn.pad=function(n,t,r){n=u(n),t=+t;var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Nn.sum=function(n,t,r){if(r&&Ur(n,t,r)&&(t=w),t=wr(t,r,3),1==t.length){n=Oo(n)?n:zr(n),r=n.length;for(var e=0;r--;)e+=+t(n[r])||0;n=e}else n=$t(n,t);return n},Nn.template=function(n,t,r){var e=Nn.templateSettings;r&&Ur(n,t,r)&&(t=r=w),n=u(n),t=nt(tt({},r||t),e,Qn),r=nt(tt({},t.imports),e.imports,Qn); +var o,i,f=zo(r),a=Ft(r,f),c=0;r=t.interpolate||Cn;var l="__p+='";r=Ze((t.escape||Cn).source+"|"+r.source+"|"+(r===gn?jn:Cn).source+"|"+(t.evaluate||Cn).source+"|$","g");var p="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,u,f,a){return e||(e=u),l+=n.slice(c,a).replace(Un,s),r&&(o=true,l+="'+__e("+r+")+'"),f&&(i=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),c=a+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(i?l.replace(fn,""):l).replace(an,"$1").replace(cn,"$1;"), +l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(o?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Jo(function(){return qe(f,p+"return "+l).apply(w,a)}),t.source=l,_e(t))throw t;return t},Nn.trim=We,Nn.trimLeft=function(n,t,r){var e=n;return(n=u(n))?n.slice((r?Ur(e,t,r):null==t)?g(n):o(n,t+"")):n},Nn.trimRight=function(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+"")+1):n; +},Nn.trunc=function(n,t,r){r&&Ur(n,t,r)&&(t=w);var e=U;if(r=W,null!=t)if(ge(t)){var o="separator"in t?t.separator:o,e="length"in t?+t.length||0:e;r="omission"in t?u(t.omission):r}else e=+t||0;if(n=u(n),e>=n.length)return n;if(e-=r.length,1>e)return r;if(t=n.slice(0,e),null==o)return t+r;if(we(o)){if(n.slice(e).search(o)){var i,f=n.slice(0,e);for(o.global||(o=Ze(o.source,(kn.exec(o)||"")+"g")),o.lastIndex=0;n=o.exec(f);)i=n.index;t=t.slice(0,null==i?e:i)}}else n.indexOf(o,e)!=e&&(o=t.lastIndexOf(o), +-1u.__dir__?"Right":"")}),u},zn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),Pn(["filter","map","takeWhile"],function(n,t){ +var r=t+1,e=r!=T;zn.prototype[n]=function(n,t){var u=this.clone();return u.__iteratees__.push({iteratee:wr(n,t,1),type:r}),u.__filtered__=u.__filtered__||e,u}}),Pn(["first","last"],function(n,t){var r="take"+(t?"Right":"");zn.prototype[n]=function(){return this[r](1).value()[0]}}),Pn(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right");zn.prototype[n]=function(){return this.__filtered__?new zn(this):this[r](1)}}),Pn(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?bt:ze;zn.prototype[n]=function(n){ +return this[r](e(n))}}),zn.prototype.compact=function(){return this.filter(Fe)},zn.prototype.reject=function(n,t){return n=wr(n,t,1),this.filter(function(t){return!n(t)})},zn.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=this;return r.__filtered__&&(0t)?new zn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==w&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r)},zn.prototype.takeRightWhile=function(n,t){return this.reverse().takeWhile(n,t).reverse()},zn.prototype.toArray=function(){return this.take(Ru); +},_t(zn.prototype,function(n,t){var r=/^(?:filter|map|reject)|While$/.test(t),e=/^(?:first|last)$/.test(t),u=Nn[e?"take"+("last"==t?"Right":""):t];u&&(Nn.prototype[t]=function(){function t(n){return e&&i?u(n,1)[0]:u.apply(w,Jn([n],o))}var o=e?[1]:arguments,i=this.__chain__,f=this.__wrapped__,a=!!this.__actions__.length,c=f instanceof zn,l=o[0],s=c||Oo(f);return s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false),l={func:ne,args:[t],thisArg:w},a=c&&!a,e&&!i?a?(f=f.clone(),f.__actions__.push(l),n.call(f)):u.call(w,this.value())[0]:!e&&s?(f=a?f:new zn(this), +f=n.apply(f,o),f.__actions__.push(l),new Ln(f,i)):this.thru(t)})}),Pn("join pop push replace shift sort splice split unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?He:Je)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|replace|shift)$/.test(n);Nn.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),_t(zn.prototype,function(n,t){var r=Nn[t];if(r){var e=r.name;(Wu[e]||(Wu[e]=[])).push({ +name:t,func:r})}}),Wu[sr(w,A).name]=[{name:"wrapper",func:w}],zn.prototype.clone=function(){var n=new zn(this.__wrapped__);return n.__actions__=qn(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=qn(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=qn(this.__views__),n},zn.prototype.reverse=function(){if(this.__filtered__){var n=new zn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},zn.prototype.value=function(){ +var n,t=this.__wrapped__.value(),r=this.__dir__,e=Oo(t),u=0>r,o=e?t.length:0;n=o;for(var i=this.__views__,f=0,a=-1,c=i.length;++ar.__dir__?n:n.reverse()}var t=this.__wrapped__; +if(t instanceof zn){var r=t;return this.__actions__.length&&(r=new zn(this)),r=r.reverse(),r.__actions__.push({func:ne,args:[n],thisArg:w}),new Ln(r,this.__chain__)}return this.thru(n)},Nn.prototype.toString=function(){return this.value()+""},Nn.prototype.run=Nn.prototype.toJSON=Nn.prototype.valueOf=Nn.prototype.value=function(){return Tt(this.__wrapped__,this.__actions__)},Nn.prototype.collect=Nn.prototype.map,Nn.prototype.head=Nn.prototype.first,Nn.prototype.select=Nn.prototype.filter,Nn.prototype.tail=Nn.prototype.rest, +Nn}var w,b="3.10.0",x=1,A=2,j=4,k=8,I=16,R=32,O=64,E=128,C=256,U=30,W="...",$=150,S=16,F=200,N=1,T=2,L="Expected a function",z="__lodash_placeholder__",B="[object Arguments]",D="[object Array]",M="[object Boolean]",q="[object Date]",P="[object Error]",K="[object Function]",V="[object Number]",Z="[object Object]",Y="[object RegExp]",G="[object String]",J="[object ArrayBuffer]",X="[object Float32Array]",H="[object Float64Array]",Q="[object Int8Array]",nn="[object Int16Array]",tn="[object Int32Array]",rn="[object Uint8Array]",en="[object Uint8ClampedArray]",un="[object Uint16Array]",on="[object Uint32Array]",fn=/\b__p\+='';/g,an=/\b(__p\+=)''\+/g,cn=/(__e\(.*?\)|\b__t\))\+'';/g,ln=/&(?:amp|lt|gt|quot|#39|#96);/g,sn=/[&<>"'`]/g,pn=RegExp(ln.source),hn=RegExp(sn.source),_n=/<%-([\s\S]+?)%>/g,vn=/<%([\s\S]+?)%>/g,gn=/<%=([\s\S]+?)%>/g,yn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,dn=/^\w*$/,mn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g,wn=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,bn=RegExp(wn.source),xn=/[\u0300-\u036f\ufe20-\ufe23]/g,An=/\\(\\)?/g,jn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,kn=/\w*$/,In=/^0[xX]/,Rn=/^\[object .+?Constructor\]$/,On=/^\d+$/,En=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,Cn=/($^)/,Un=/['\n\r\u2028\u2029\\]/g,Wn=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?=[A-Z\\xc0-\\xd6\\xd8-\\xde][a-z\\xdf-\\xf6\\xf8-\\xff]+)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+|[A-Z\\xc0-\\xd6\\xd8-\\xde]+|[0-9]+","g"),$n="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout isFinite parseFloat parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap".split(" "),Sn={}; +Sn[X]=Sn[H]=Sn[Q]=Sn[nn]=Sn[tn]=Sn[rn]=Sn[en]=Sn[un]=Sn[on]=true,Sn[B]=Sn[D]=Sn[J]=Sn[M]=Sn[q]=Sn[P]=Sn[K]=Sn["[object Map]"]=Sn[V]=Sn[Z]=Sn[Y]=Sn["[object Set]"]=Sn[G]=Sn["[object WeakMap]"]=false;var Fn={};Fn[B]=Fn[D]=Fn[J]=Fn[M]=Fn[q]=Fn[X]=Fn[H]=Fn[Q]=Fn[nn]=Fn[tn]=Fn[V]=Fn[Z]=Fn[Y]=Fn[G]=Fn[rn]=Fn[en]=Fn[un]=Fn[on]=true,Fn[P]=Fn[K]=Fn["[object Map]"]=Fn["[object Set]"]=Fn["[object WeakMap]"]=false;var Nn={"\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"},Tn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Ln={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},zn={"function":true,object:true},Bn={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"},Dn={"\\":"\\", +"'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mn=zn[typeof exports]&&exports&&!exports.nodeType&&exports,qn=zn[typeof module]&&module&&!module.nodeType&&module,Pn=zn[typeof self]&&self&&self.Object&&self,Kn=zn[typeof window]&&window&&window.Object&&window,Vn=qn&&qn.exports===Mn&&Mn,Zn=Mn&&qn&&typeof global=="object"&&global&&global.Object&&global||Kn!==(this&&this.window)&&Kn||Pn||this,Yn=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Zn._=Yn, define(function(){ +return Yn})):Mn&&qn?Vn?(qn.exports=Yn)._=Yn:Mn._=Yn:Zn._=Yn}).call(this); \ No newline at end of file diff --git a/lodash.src.js b/lodash.src.js index 73e985bd65..1ec2ebe50b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1,6 +1,6 @@ /** * @license - * lodash 3.9.3 + * lodash 3.10.0 * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.8.3 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors @@ -12,7 +12,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '3.9.3'; + var VERSION = '3.10.0'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, From f2d87df120c6a675d358f66b37b01adc637cbe55 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 30 Jun 2015 09:40:56 -0700 Subject: [PATCH 107/107] Bump to v3.10.0. --- README.md | 6 +++--- component.json | 2 +- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 48fd725f2a..f36e4d4e4c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# lodash v3.9.3 +# lodash v3.10.0 The [modern build](https://github.com/lodash/lodash/wiki/Build-Differences) of [lodash](https://lodash.com/) with packages for [Bower](http://bower.io/), [Component](http://component.github.io/), & [Volo](http://volojs.org/). @@ -16,8 +16,8 @@ $ lodash modern -o ./lodash.js lodash is also available in a variety of other builds & module formats. * npm packages for [modern](https://www.npmjs.com/package/lodash), [compatibility](https://www.npmjs.com/package/lodash-compat), & [per method](https://www.npmjs.com/browse/keyword/lodash-modularized) builds - * AMD modules for [modern](https://github.com/lodash/lodash/tree/3.9.3-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.9.3-amd) builds - * ES modules for the [modern](https://github.com/lodash/lodash/tree/3.9.3-es) build + * AMD modules for [modern](https://github.com/lodash/lodash/tree/3.10.0-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.10.0-amd) builds + * ES modules for the [modern](https://github.com/lodash/lodash/tree/3.10.0-es) build ## Further Reading diff --git a/component.json b/component.json index dad68e0675..82986672d5 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "lodash", "repo": "lodash/lodash", - "version": "3.9.3", + "version": "3.10.0", "description": "The modern build of lodash.", "license": "MIT", "main": "lodash.js", diff --git a/package.json b/package.json index f7f7c43b73..61ea18af70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "3.9.3", + "version": "3.10.0", "main": "lodash.src.js", "private": true, "devDependencies": {