From bdeca2edce353aa439dc2a014c78da23492d6397 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 3 Feb 2015 08:47:04 -0800 Subject: [PATCH 01/61] Update .gitignore to ignore lodash.compat.min.js. [ci skip] --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e27563e184..58a3a4336a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ *.custom.* *.log *.map -lodash.compat.js +lodash.compat.min.js node_modules From 083e401717e482c0732cb0ffe46d08cca1ed8938 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 3 Feb 2015 19:59:39 -0800 Subject: [PATCH 02/61] Fix param doc typos in `baseIsMatch`, `_.chunk`, & `_.isMatch`. [ci skip] [closes #923] --- lodash.src.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 2f55e9354a..91b96c6032 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -2360,7 +2360,7 @@ * shorthands or `this` binding. * * @private - * @param {Object} source The object to inspect. + * @param {Object} object The object to inspect. * @param {Array} props The source property names to match. * @param {Array} values The source values to match. * @param {Array} strictCompareFlags Strict comparison flags for source values. @@ -4089,7 +4089,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to process. - * @param {numer} [size=1] The length of each chunk. + * @param {number} [size=1] The length of each chunk. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the new array containing chunks. * @example @@ -8025,7 +8025,7 @@ * @static * @memberOf _ * @category Lang - * @param {Object} source The object to inspect. + * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Function} [customizer] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `customizer`. From aa1edd6b943c547b160d6b3ee8f2b0f0be835c87 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 4 Feb 2015 21:20:11 -0800 Subject: [PATCH 03/61] Update tested io.js version in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 75b5f9fb60..7c4ca245f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ node_js: env: global: - BIN="node" BUILD="compat" ISTANBUL=false NODE_BIN=$BIN OPTION="" - - IOJS_VERSION="v1.0.4" NPM_VERSION="^2.0.0" SAUCE_LABS=false SAUCE_USERNAME="lodash" + - IOJS_VERSION="v1.1.0" NPM_VERSION="^2.0.0" SAUCE_LABS=false SAUCE_USERNAME="lodash" - secure: "tg1JFsIFnxzLaTboFPOnm+aJCuMm5+JdhLlESlqg9x3fwro++7KCnwHKLNovhchaPe4otC43ZMB/nfWhDnDm11dKbm/V6HlTkED+dadTsaLxVDg6J+7yK41QhokBPJOxLV78iDaNaAQVYEirAgZ0yn8kFubxmNKV+bpCGQNc9yU=" matrix: - BUILD="compat" From 97a885a05cf7d4e5819c6f2230ecff6545ddc420 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 4 Feb 2015 22:51:25 -0800 Subject: [PATCH 04/61] Use sauce-tunnel v2.1.1 to avoid hangs when closing tunnels. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7c4ca245f0..2c160f1349 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ before_install: - "nvm use $TRAVIS_NODE_VERSION" - "npm config set loglevel error" - "npm i -g npm@\"$NPM_VERSION\"" - - "[ $SAUCE_LABS == false ] || npm i chalk@\"0.5.1\" ecstatic@\"0.5.8\" request@\"^2.0.0\" sauce-tunnel@\"^2.0.0\"" + - "[ $SAUCE_LABS == false ] || npm i chalk@\"0.5.1\" ecstatic@\"0.5.8\" request@\"^2.0.0\" sauce-tunnel@\"2.1.1\"" - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.5\")" - "[ $BIN != 'iojs' ] || (wget https://iojs.org/dist/${IOJS_VERSION}/iojs-${IOJS_VERSION}-linux-x64.tar.xz && sudo tar xJf iojs-${IOJS_VERSION}-linux-x64.tar.xz -C /opt && rm iojs-${IOJS_VERSION}-linux-x64.tar.xz)" - "[ $BIN != 'iojs' ] || (sudo ln -s /opt/iojs-${IOJS_VERSION}-linux-x64/bin/iojs /usr/local/bin/iojs && sudo chmod +x $_)" From d2f6416e4578bb6cbc3792126f643949fa7f07b7 Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 5 Feb 2015 09:47:47 -0800 Subject: [PATCH 05/61] Add `_.runInContext` usage example to `_.mixin` docs. [ci skip] --- lodash.src.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lodash.src.js b/lodash.src.js index 91b96c6032..e8ec840153 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -10302,6 +10302,9 @@ * }); * } * + * // use `_.runInContext` to avoid potential conflicts (esp. in Node.js) + * var _ = require('lodash').runInContext(); + * * _.mixin({ 'vowels': vowels }); * _.vowels('fred'); * // => ['e'] From ecbc46a91d8da0559e4b091ef476aea7a2ee68d2 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2015 21:52:14 -0800 Subject: [PATCH 06/61] Remove unused `unshift` variable. --- lodash.src.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index e8ec840153..c840b4aca8 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -755,7 +755,6 @@ setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, - unshift = arrayProto.unshift, WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers. */ From 35fa977981717e187affe9747e2ecd56f45fb0b1 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2015 21:09:26 -0800 Subject: [PATCH 07/61] Update to Node.js 0.12 and simplify io.js install in travis.yml. --- .travis.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2c160f1349..6984109d20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: node_js node_js: - - "0.10" + - "0.12" env: global: - BIN="node" BUILD="compat" ISTANBUL=false NODE_BIN=$BIN OPTION="" - - IOJS_VERSION="v1.1.0" NPM_VERSION="^2.0.0" SAUCE_LABS=false SAUCE_USERNAME="lodash" + - NPM_VERSION="^2.0.0" SAUCE_LABS=false SAUCE_USERNAME="lodash" - secure: "tg1JFsIFnxzLaTboFPOnm+aJCuMm5+JdhLlESlqg9x3fwro++7KCnwHKLNovhchaPe4otC43ZMB/nfWhDnDm11dKbm/V6HlTkED+dadTsaLxVDg6J+7yK41QhokBPJOxLV78iDaNaAQVYEirAgZ0yn8kFubxmNKV+bpCGQNc9yU=" matrix: - BUILD="compat" @@ -24,8 +24,11 @@ matrix: - node_js: "0.8" env: BUILD="modern" NPM_VERSION="~1.4.0" - node_js: "0.10" - env: SAUCE_LABS=true - node_js: "0.10" + env: BUILD="modern" + - node_js: "0.12" + env: SAUCE_LABS=true + - node_js: "0.12" env: SAUCE_LABS=true BUILD="modern" git: depth: 10 @@ -38,8 +41,7 @@ before_install: - "npm i -g npm@\"$NPM_VERSION\"" - "[ $SAUCE_LABS == false ] || npm i chalk@\"0.5.1\" ecstatic@\"0.5.8\" request@\"^2.0.0\" sauce-tunnel@\"2.1.1\"" - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.5\")" - - "[ $BIN != 'iojs' ] || (wget https://iojs.org/dist/${IOJS_VERSION}/iojs-${IOJS_VERSION}-linux-x64.tar.xz && sudo tar xJf iojs-${IOJS_VERSION}-linux-x64.tar.xz -C /opt && rm iojs-${IOJS_VERSION}-linux-x64.tar.xz)" - - "[ $BIN != 'iojs' ] || (sudo ln -s /opt/iojs-${IOJS_VERSION}-linux-x64/bin/iojs /usr/local/bin/iojs && sudo chmod +x $_)" + - "[ $BIN != 'iojs' ] || nvm install iojs" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7R5 && sudo wget --no-check-certificate -O $_/js.jar https://lodash.com/_travis/rhino-1.7R5.jar)" - "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7R5/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)" - "[ $BIN != 'ringo' ] || (wget --no-check-certificate https://lodash.com/_travis/ringojs-0.11.zip && sudo unzip ringojs-0.11 -d /opt && rm ringojs-0.11.zip)" From 82c7a22d275b53c760294b0c878a2fdc74f877b4 Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2015 22:45:58 -0800 Subject: [PATCH 08/61] Ensure `_.flow` and `_.flowRight` return an identity function when no arguments are provided. [closes #938] --- lodash.src.js | 4 ++-- test/test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index c840b4aca8..81d8bbd26b 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7207,7 +7207,7 @@ length = funcs.length; if (!length) { - return function() {}; + return function() { return arguments[0]; }; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); @@ -7252,7 +7252,7 @@ fromIndex = funcs.length - 1; if (fromIndex < 0) { - return function() {}; + return function() { return arguments[0]; }; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); diff --git a/test/test.js b/test/test.js index f1bfde13d2..673a92ea10 100644 --- a/test/test.js +++ b/test/test.js @@ -2023,15 +2023,15 @@ notStrictEqual(func(_.noop), _.noop); }); - test('`_.' + methodName + '` should return a noop function when no arguments are provided', 2, function() { + test('`_.' + methodName + '` should return an identity function when no arguments are provided', 2, function() { var combined = func(); try { - strictEqual(combined(), undefined); + strictEqual(combined('a'), 'a'); } catch(e) { ok(false, e.message); } - notStrictEqual(combined, _.noop); + notStrictEqual(combined, _.identity); }); test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() { From 5ab79f292bdac961b7636c758aa40cea12abba4b Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2015 23:09:52 -0800 Subject: [PATCH 09/61] Allow `_.attempt` to provide additional arguments to `func`. [closes #929] --- lodash.src.js | 10 +++++----- test/test.js | 17 +++++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 81d8bbd26b..abf40704cc 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -10140,8 +10140,8 @@ /*------------------------------------------------------------------------*/ /** - * Attempts to invoke `func`, returning either the result or the caught - * error object. + * Attempts to invoke `func`, returning either the result or the caught error + * object. Any additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -10151,9 +10151,9 @@ * @example * * // avoid throwing errors for invalid selectors - * var elements = _.attempt(function() { + * var elements = _.attempt(function(selector) { * return document.querySelectorAll(selector); - * }); + * }, '>_>'); * * if (_.isError(elements)) { * elements = []; @@ -10161,7 +10161,7 @@ */ function attempt(func) { try { - return func(); + return func.apply(undefined, baseSlice(arguments, 1)); } catch(e) { return isError(e) ? e : Error(e); } diff --git a/test/test.js b/test/test.js index 673a92ea10..ba59dfa431 100644 --- a/test/test.js +++ b/test/test.js @@ -1076,6 +1076,11 @@ strictEqual(_.attempt(_.constant('x')), 'x'); }); + test('should provide additional arguments to `func`', 1, function() { + var actual = _.attempt(function() { return slice.call(arguments); }, 1, 2); + deepEqual(actual, [1, 2]); + }); + test('should return the caught error', 1, function() { var expected = _.map(errors, _.constant(true)); @@ -3378,16 +3383,16 @@ } }); - asyncTest('should accept additional arguments', 1, function() { + asyncTest('should provide additional arguments to `func`', 1, function() { if (!(isRhino && isModularize)) { var args; _.defer(function() { args = slice.call(arguments); - }, 1, 2, 3); + }, 1, 2); setTimeout(function() { - deepEqual(args, [1, 2, 3]); + deepEqual(args, [1, 2]); QUnit.start(); }, 128); } @@ -3444,16 +3449,16 @@ } }); - asyncTest('should accept additional arguments', 1, function() { + asyncTest('should provide additional arguments to `func`', 1, function() { if (!(isRhino && isModularize)) { var args; _.delay(function() { args = slice.call(arguments); - }, 32, 1, 2, 3); + }, 32, 1, 2); setTimeout(function() { - deepEqual(args, [1, 2, 3]); + deepEqual(args, [1, 2]); QUnit.start(); }, 128); } From c6f73d9df8e09351663182e1ac61a971bd66074e Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2015 23:14:03 -0800 Subject: [PATCH 10/61] Consistent `apply(undefined, ...)` use. --- lodash.src.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index abf40704cc..9199954e5e 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3361,9 +3361,9 @@ if (bitmask == BIND_FLAG) { var result = createBindWrapper(newData[0], newData[2]); } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { - result = createPartialWrapper.apply(null, newData); + result = createPartialWrapper.apply(undefined, newData); } else { - result = createHybridWrapper.apply(null, newData); + result = createHybridWrapper.apply(undefined, newData); } var setter = data ? baseSetData : setData; return setter(result, newData); From 2a86f0776c494386c5291aab47c1a0152827bfce Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2015 23:44:14 -0800 Subject: [PATCH 11/61] Fix travis run. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6984109d20..8ac63bbcab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ matrix: - node_js: "0.8" env: BUILD="modern" NPM_VERSION="~1.4.0" - node_js: "0.10" + env: - node_js: "0.10" env: BUILD="modern" - node_js: "0.12" From af02a1e0246667462865fdf7b3181757251f5115 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 7 Feb 2015 09:45:11 -0800 Subject: [PATCH 12/61] Replace some `_.isFunction` checks with simple `typeof` checks and replace some `typeof` checks with `_.isFunction` checks based on likelihood of a problem value older enviros being passed. --- lodash.src.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 9199954e5e..35e2b2a834 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -1907,7 +1907,7 @@ * @returns {number} Returns the timer id. */ function baseDelay(func, wait, args, fromIndex) { - if (!isFunction(func)) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); @@ -3331,7 +3331,7 @@ */ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { var isBindKey = bitmask & BIND_KEY_FLAG; - if (!isBindKey && !isFunction(func)) { + if (!isBindKey && typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } var length = partials ? partials.length : 0; @@ -6655,8 +6655,8 @@ * // => logs 'done saving!' after the two async saves have completed */ function after(n, func) { - if (!isFunction(func)) { - if (isFunction(n)) { + if (typeof func != 'function') { + if (typeof n == 'function') { var temp = n; n = func; func = temp; @@ -6714,8 +6714,8 @@ */ function before(n, func) { var result; - if (!isFunction(func)) { - if (isFunction(n)) { + if (typeof func != 'function') { + if (typeof n == 'function') { var temp = n; n = func; func = temp; @@ -7037,7 +7037,7 @@ maxWait = false, trailing = true; - if (!isFunction(func)) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } wait = wait < 0 ? 0 : wait; @@ -7322,7 +7322,7 @@ * // => { 'user': 'barney' } */ function memoize(func, resolver) { - if (!isFunction(func) || (resolver && !isFunction(resolver))) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { @@ -7360,7 +7360,7 @@ * // => [1, 3, 5] */ function negate(predicate) { - if (!isFunction(predicate)) { + if (typeof predicate != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return function() { @@ -7540,7 +7540,7 @@ var leading = true, trailing = true; - if (!isFunction(func)) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } if (options === false) { @@ -8818,12 +8818,12 @@ var Ctor = object.constructor, index = -1, - proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto, + proto = (isFunction(Ctor) && Ctor.prototype) || objectProto, isProto = proto === object, result = Array(length), skipIndexes = length > 0, skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), - skipProto = support.enumPrototypes && typeof object == 'function'; + skipProto = support.enumPrototypes && isFunction(object); while (++index < length) { result[index] = (index + ''); @@ -9137,7 +9137,7 @@ if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(typeof Ctor == 'function' && Ctor.prototype); + accumulator = baseCreate(isFunction(Ctor) && Ctor.prototype); } } else { accumulator = {}; From ee09425cfbd6cf8acca89444dee337c93048347c Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 7 Feb 2015 20:32:05 -0800 Subject: [PATCH 13/61] Simplify travis.yml. --- .travis.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ac63bbcab..22da53cf1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ node_js: - "0.12" env: global: - - BIN="node" BUILD="compat" ISTANBUL=false NODE_BIN=$BIN OPTION="" + - 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=" matrix: @@ -11,14 +11,16 @@ env: - BUILD="modern" - BUILD="modern" - BUILD="modern" ISTANBUL=true - - BIN="iojs" BUILD="compat" NODE_BIN=$BIN - - BIN="iojs" BUILD="modern" NODE_BIN=$BIN - BIN="phantomjs" - BIN="rhino" - BIN="rhino" OPTION="-require" - BIN="ringo" matrix: include: + - node_js: "io.js" + env: BUILD="compat" + - node_js: "io.js" + env: BUILD="modern" - node_js: "0.8" env: NPM_VERSION="~1.4.0" - node_js: "0.8" @@ -42,17 +44,16 @@ before_install: - "npm i -g npm@\"$NPM_VERSION\"" - "[ $SAUCE_LABS == false ] || npm i chalk@\"0.5.1\" ecstatic@\"0.5.8\" request@\"^2.0.0\" sauce-tunnel@\"2.1.1\"" - "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.5\")" - - "[ $BIN != 'iojs' ] || nvm install iojs" - "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7R5 && sudo wget --no-check-certificate -O $_/js.jar https://lodash.com/_travis/rhino-1.7R5.jar)" - "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7R5/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)" - "[ $BIN != 'ringo' ] || (wget --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 $_)" - "sed -i'' '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 ../../" - - "$NODE_BIN ./node_modules/lodash-cli/bin/lodash $BUILD -o ./lodash.$BUILD.js" + - "node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./lodash.$BUILD.js" script: - - "[ $ISTANBUL == false ] || (nvm install 0.11.11 && cp ./lodash.$BUILD.js ./lodash.js && $BIN --harmony ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./lodash.js)" - - "([ $ISTANBUL == true ] && [ $TRAVIS_SECURE_ENV_VARS == true ] && nvm use $TRAVIS_NODE_VERSION && cat ./coverage/lcov.info | coveralls) || true" + - "[ $ISTANBUL == false ] || (cp ./lodash.$BUILD.js ./lodash.js && node ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./lodash.js)" + - "([ $ISTANBUL == true ] && [ $TRAVIS_SECURE_ENV_VARS == true ] && 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 ] || $BIN $OPTION ./test.js ../lodash.$BUILD.min.js" From dd45fea732041b5efaed41c05e32747f26a97dd0 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sat, 7 Feb 2015 20:43:46 -0800 Subject: [PATCH 14/61] Add `_#commit`, `_#plant`, & `_#run`. --- lodash.src.js | 201 +++++++++++++++++++++++++++++++++++--------------- test/test.js | 70 ++++++++++++++++-- 2 files changed, 207 insertions(+), 64 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 35e2b2a834..4048721294 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -834,7 +834,7 @@ /*------------------------------------------------------------------------*/ /** - * Creates a `lodash` object which wraps `value` to enable intuitive chaining. + * 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 @@ -897,7 +897,7 @@ * @constructor * @category Chain * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var wrapped = _([1, 2, 3]); @@ -916,12 +916,12 @@ * // => true */ function lodash(value) { - if (isObjectLike(value) && !isArray(value)) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { if (value instanceof LodashWrapper) { return value; } - if (hasOwnProperty.call(value, '__wrapped__')) { - return new LodashWrapper(value.__wrapped__, value.__chain__, arrayCopy(value.__actions__)); + if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); } } return new LodashWrapper(value); @@ -936,9 +936,9 @@ * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. */ function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; this.__actions__ = actions || []; this.__chain__ = !!chainAll; - this.__wrapped__ = value; } /** @@ -1172,14 +1172,14 @@ * @param {*} value The value to wrap. */ function LazyWrapper(value) { - this.actions = null; - this.dir = 1; - this.dropCount = 0; - this.filtered = false; - this.iteratees = null; - this.takeCount = POSITIVE_INFINITY; - this.views = null; - this.wrapped = value; + this.__wrapped__ = value; + this.__actions__ = null; + this.__dir__ = 1; + this.__dropCount__ = 0; + this.__filtered__ = false; + this.__iteratees__ = null; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = null; } /** @@ -1191,18 +1191,18 @@ * @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; - result.dir = this.dir; - result.dropCount = this.dropCount; - result.filtered = this.filtered; - result.iteratees = iteratees ? arrayCopy(iteratees) : null; - result.takeCount = this.takeCount; - result.views = views ? arrayCopy(views) : null; + var actions = this.__actions__, + iteratees = this.__iteratees__, + views = this.__views__, + result = new LazyWrapper(this.__wrapped__); + + result.__actions__ = actions ? arrayCopy(actions) : null; + result.__dir__ = this.__dir__; + result.__dropCount__ = this.__dropCount__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__takeCount__ = this.__takeCount__; + result.__views__ = views ? arrayCopy(views) : null; return result; } @@ -1215,13 +1215,13 @@ * @returns {Object} Returns the new reversed `LazyWrapper` object. */ function lazyReverse() { - if (this.filtered) { + if (this.__filtered__) { var result = new LazyWrapper(this); - result.dir = -1; - result.filtered = true; + result.__dir__ = -1; + result.__filtered__ = true; } else { result = this.clone(); - result.dir *= -1; + result.__dir__ *= -1; } return result; } @@ -1235,20 +1235,20 @@ * @returns {*} Returns the unwrapped value. */ function lazyValue() { - var array = this.wrapped.value(); + var array = this.__wrapped__.value(); if (!isArray(array)) { - return baseWrapperValue(array, this.actions); + return baseWrapperValue(array, this.__actions__); } - var dir = this.dir, + var dir = this.__dir__, isRight = dir < 0, - view = getView(0, array.length, this.views), + view = getView(0, array.length, this.__views__), start = view.start, end = view.end, length = end - start, - dropCount = this.dropCount, - takeCount = nativeMin(length, this.takeCount - dropCount), + dropCount = this.__dropCount__, + takeCount = nativeMin(length, this.__takeCount__ - dropCount), index = isRight ? end : start - 1, - iteratees = this.iteratees, + iteratees = this.__iteratees__, iterLength = iteratees ? iteratees.length : 0, resIndex = 0, result = []; @@ -4077,6 +4077,19 @@ return isObject(value) ? value : Object(value); } + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper + ? wrapper.clone() + : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + /*------------------------------------------------------------------------*/ /** @@ -5383,7 +5396,7 @@ * @memberOf _ * @category Chain * @param {*} value The value to wrap. - * @returns {Object} Returns the new `lodash` object. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var users = [ @@ -5459,7 +5472,7 @@ * @name chain * @memberOf _ * @category Chain - * @returns {*} Returns the `lodash` object. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var users = [ @@ -5482,6 +5495,74 @@ return chain(this); } + /** + * Executes the chained sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapper = wrapper.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapper.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value()); + } + + /** + * Creates a clone of the chained sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).map(_.partial(Math.pow, _, 2)); + * + * var other = [3, 4]; + * var otherWrapper = wrapper.plant(other); + * + * otherWrapper.value(); + * // => [9, 16] + * + * wrapper.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof LodashWrapper) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + /** * Reverses the wrapped array so the first element becomes the last, the * second element becomes the second to last, and so on. @@ -5491,7 +5572,7 @@ * @name reverse * @memberOf _ * @category Chain - * @returns {Object} Returns the new reversed `lodash` object. + * @returns {Object} Returns the new reversed `lodash` wrapper instance. * @example * * var array = [1, 2, 3]; @@ -5536,7 +5617,7 @@ * * @name value * @memberOf _ - * @alias toJSON, valueOf + * @alias run, toJSON, valueOf * @category Chain * @returns {*} Returns the resolved unwrapped value. * @example @@ -10578,7 +10659,11 @@ /*------------------------------------------------------------------------*/ // Ensure `new LodashWrapper` is an instance of `lodash`. - LodashWrapper.prototype = lodash.prototype; + LodashWrapper.prototype = baseCreate(lodash.prototype); + + // Ensure `new LazyWraper` is an instance of `LodashWrapper` + LazyWrapper.prototype = baseCreate(LodashWrapper.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; // Add functions to the `Map` cache. MapCache.prototype['delete'] = mapDelete; @@ -10840,14 +10925,15 @@ // Add `LazyWrapper` methods that accept an `iteratee` value. arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { - var isFilter = index == LAZY_FILTER_FLAG; + var isFilter = index == LAZY_FILTER_FLAG, + isWhile = index == LAZY_WHILE_FLAG; LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { var result = this.clone(), - filtered = result.filtered, - iteratees = result.iteratees || (result.iteratees = []); + filtered = result.__filtered__, + iteratees = result.__iteratees__ || (result.__iteratees__ = []); - result.filtered = filtered || isFilter || (index == LAZY_WHILE_FLAG && result.dir < 0); + result.__filtered__ = filtered || isFilter || (isWhile && result.__dir__ < 0); iteratees.push({ 'iteratee': getCallback(iteratee, thisArg, 3), 'type': index }); return result; }; @@ -10855,19 +10941,19 @@ // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. arrayEach(['drop', 'take'], function(methodName, index) { - var countName = methodName + 'Count', + var countName = '__' + methodName + 'Count__', whileName = methodName + 'While'; LazyWrapper.prototype[methodName] = function(n) { n = n == null ? 1 : nativeMax(+n || 0, 0); var result = this.clone(); - if (result.filtered) { + if (result.__filtered__) { var value = result[countName]; result[countName] = index ? nativeMin(value, n) : (value + n); } else { - var views = result.views || (result.views = []); - views.push({ 'size': n, 'type': methodName + (result.dir < 0 ? 'Right' : '') }); + var views = result.__views__ || (result.__views__ = []); + views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); } return result; }; @@ -10910,14 +10996,9 @@ }); LazyWrapper.prototype.dropWhile = function(iteratee, thisArg) { - var done, - lastIndex, - isRight = this.dir < 0; - + var done; iteratee = getCallback(iteratee, thisArg, 3); return this.filter(function(value, index, array) { - done = done && (isRight ? index < lastIndex : index > lastIndex); - lastIndex = index; return done || (done = !iteratee(value, index, array)); }); }; @@ -10967,8 +11048,8 @@ var wrapper = onlyLazy ? value : new LazyWrapper(this), result = func.apply(wrapper, args); - if (!retUnwrapped && (isHybrid || result.actions)) { - var actions = result.actions || (result.actions = []); + if (!retUnwrapped && (isHybrid || result.__actions__)) { + var actions = result.__actions__ || (result.__actions__ = []); actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); } return new LodashWrapper(result, chainAll); @@ -11012,9 +11093,11 @@ // Add chaining functions to the lodash wrapper. lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.plant = wrapperPlant; lodash.prototype.reverse = wrapperReverse; lodash.prototype.toString = wrapperToString; - lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; // Add function aliases to the lodash wrapper. lodash.prototype.collect = lodash.prototype.map; diff --git a/test/test.js b/test/test.js index ba59dfa431..d173075497 100644 --- a/test/test.js +++ b/test/test.js @@ -14240,6 +14240,29 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash(...).commit'); + + (function() { + test('should execute the chained sequence and returns the wrapped result', 4, function() { + if (!isNpm) { + var array = [1], + wrapped = _(array).push(2).push(3); + + deepEqual(array, [1]); + + var otherWrapper = wrapped.commit(); + ok(otherWrapper instanceof _); + deepEqual(otherWrapper.value(), [1, 2, 3]); + deepEqual(wrapped.value(), [1, 2, 3, 2, 3]); + } + else { + skipTest(4); + } + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash(...).concat'); (function() { @@ -14281,6 +14304,27 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash(...).plant'); + + (function() { + test('should clone the chained sequence planting `value` as the wrapped value', 2, function() { + if (!isNpm) { + var array1 = [1, 2], + array2 = [3, 4], + wrapper1 = _(array1).map(_.partial(Math.pow, _, 2)), + wrapper2 = wrapper1.plant(array2); + + deepEqual(wrapper2.value(), [9, 16]); + deepEqual(wrapper1.value(), [1, 4]); + } + else { + skipTest(2); + } + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash(...).pop'); (function() { @@ -14542,9 +14586,24 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash(...).valueOf'); + QUnit.module('lodash(...).value'); (function() { + test('should execute the chained sequence and extract the unwrapped value', 4, function() { + if (!isNpm) { + var array = [1], + wrapped = _(array).push(2).push(3); + + deepEqual(array, [1]); + deepEqual(wrapped.value(), [1, 2, 3]); + deepEqual(wrapped.value(), [1, 2, 3, 2, 3]); + deepEqual(array, [1, 2, 3, 2, 3]); + } + else { + skipTest(4); + } + }); + test('should return the `valueOf` result of the wrapped value', 1, function() { if (!isNpm) { var wrapped = _(123); @@ -14565,14 +14624,15 @@ } }); - test('should be aliased', 2, function() { + test('should be aliased', 3, function() { if (!isNpm) { - var expected = _.prototype.valueOf; + var expected = _.prototype.value; + strictEqual(_.prototype.run, expected); strictEqual(_.prototype.toJSON, expected); - strictEqual(_.prototype.value, expected); + strictEqual(_.prototype.valueOf, expected); } else { - skipTest(2); + skipTest(3); } }); }()); From 6b63009b1417a5483c37613f873e6fc56b612560 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 01:21:05 -0800 Subject: [PATCH 15/61] Expand `_.takeWhile`, `_.takeRightWhile`, `_.dropWhile`, & `_.dropRightWhile` tests. --- test/test.js | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/test/test.js b/test/test.js index d173075497..0f3cdadc0a 100644 --- a/test/test.js +++ b/test/test.js @@ -3710,7 +3710,7 @@ QUnit.module('lodash.dropRightWhile'); (function() { - var array = [1, 2, 3]; + var array = [1, 2, 3, 4]; var objects = [ { 'a': 0, 'b': 0 }, @@ -3720,10 +3720,10 @@ test('should drop elements while `predicate` returns truthy', 1, function() { var actual = _.dropRightWhile(array, function(num) { - return num > 1; + return num > 2; }); - deepEqual(actual, [1]); + deepEqual(actual, [1, 2]); }); test('should provide the correct `predicate` arguments', 1, function() { @@ -3733,15 +3733,15 @@ args = slice.call(arguments); }); - deepEqual(args, [3, 2, array]); + deepEqual(args, [4, 3, array]); }); test('should support the `thisArg` argument', 1, function() { var actual = _.dropRightWhile(array, function(num, index) { - return this[index] > 1; + return this[index] > 2; }, array); - deepEqual(actual, [1]); + deepEqual(actual, [1, 2]); }); test('should work with a "_.pluck" style `predicate`', 1, function() { @@ -3754,12 +3754,13 @@ test('should return a wrapped value when chaining', 2, function() { if (!isNpm) { + var wrapped = _(array).dropRightWhile(function(num) { - return num > 1; + return num > 2; }); ok(wrapped instanceof _); - deepEqual(wrapped.value(), [1]); + deepEqual(wrapped.value(), [1, 2]); } else { skipTest(2); @@ -3772,7 +3773,7 @@ QUnit.module('lodash.dropWhile'); (function() { - var array = [1, 2, 3]; + var array = [1, 2, 3, 4]; var objects = [ { 'a': 2, 'b': 2 }, @@ -3785,7 +3786,7 @@ return num < 3; }); - deepEqual(actual, [3]); + deepEqual(actual, [3, 4]); }); test('should provide the correct `predicate` arguments', 1, function() { @@ -3803,7 +3804,7 @@ return this[index] < 3; }, array); - deepEqual(actual, [3]); + deepEqual(actual, [3, 4]); }); test('should work with a "_.pluck" style `predicate`', 1, function() { @@ -3821,7 +3822,7 @@ }); ok(wrapped instanceof _); - deepEqual(wrapped.value(), [3]); + deepEqual(wrapped.value(), [3, 4]); } else { skipTest(2); @@ -4422,7 +4423,7 @@ QUnit.module('lodash.takeRightWhile'); (function() { - var array = [1, 2, 3]; + var array = [1, 2, 3, 4]; var objects = [ { 'a': 0, 'b': 0 }, @@ -4432,10 +4433,10 @@ test('should take elements while `predicate` returns truthy', 1, function() { var actual = _.takeRightWhile(array, function(num) { - return num > 1; + return num > 2; }); - deepEqual(actual, [2, 3]); + deepEqual(actual, [3, 4]); }); test('should provide the correct `predicate` arguments', 1, function() { @@ -4445,15 +4446,15 @@ args = slice.call(arguments); }); - deepEqual(args, [3, 2, array]); + deepEqual(args, [4, 3, array]); }); test('should support the `thisArg` argument', 1, function() { var actual = _.takeRightWhile(array, function(num, index) { - return this[index] > 1; + return this[index] > 2; }, array); - deepEqual(actual, [2, 3]); + deepEqual(actual, [3, 4]); }); test('should work with a "_.pluck" style `predicate`', 1, function() { @@ -4467,11 +4468,11 @@ test('should return a wrapped value when chaining', 2, function() { if (!isNpm) { var wrapped = _(array).takeRightWhile(function(num) { - return num > 1; + return num > 2; }); ok(wrapped instanceof _); - deepEqual(wrapped.value(), [2, 3]); + deepEqual(wrapped.value(), [3, 4]); } else { skipTest(2); @@ -4484,7 +4485,7 @@ QUnit.module('lodash.takeWhile'); (function() { - var array = [1, 2, 3]; + var array = [1, 2, 3, 4]; var objects = [ { 'a': 2, 'b': 2 }, From 70378432b7366fcc08a4658d40985c312dd0ff06 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 01:23:57 -0800 Subject: [PATCH 16/61] Minor cleanup of istanbul command in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 22da53cf1d..3c09dc1aa1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,7 +53,7 @@ before_install: - "node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./lodash.$BUILD.js" script: - "[ $ISTANBUL == false ] || (cp ./lodash.$BUILD.js ./lodash.js && node ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./lodash.js)" - - "([ $ISTANBUL == true ] && [ $TRAVIS_SECURE_ENV_VARS == true ] && cat ./coverage/lcov.info | coveralls) || true" + - "[ $ISTANBUL == false ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || (cat ./coverage/lcov.info | coveralls)" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || cd ./test" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || $BIN $OPTION ./test.js ../lodash.$BUILD.js" - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || $BIN $OPTION ./test.js ../lodash.$BUILD.min.js" From ba4da249846ffff1743e84dae84ce41b99ad2ecb Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 13:56:12 -0800 Subject: [PATCH 17/61] Add tests for arguments provided to callbacks of `_.takeWhile` and friends when in a lazy chain sequence. [closes #944] --- test/test.js | 71 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/test/test.js b/test/test.js index 0f3cdadc0a..afeab682fb 100644 --- a/test/test.js +++ b/test/test.js @@ -3754,7 +3754,6 @@ test('should return a wrapped value when chaining', 2, function() { if (!isNpm) { - var wrapped = _(array).dropRightWhile(function(num) { return num > 2; }); @@ -3766,6 +3765,21 @@ skipTest(2); } }); + + test('should provide the correct `predicate` arguments in a lazy chain sequence', 1, function() { + if (!isNpm) { + var args; + + _(array).map(function(n) { return n * n; }).dropRightWhile(function() { + args = slice.call(arguments); + }).value(); + + deepEqual(args, [16, 3, array]); + } + else { + skipTest(1); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -3828,6 +3842,21 @@ skipTest(2); } }); + + test('should provide the correct `predicate` arguments in a lazy chain sequence', 1, function() { + if (!isNpm) { + var args; + + _(array).map(function(n) { return n * n; }).dropWhile(function() { + args = slice.call(arguments); + }).value(); + + deepEqual(args, [1, 0, array]); + } + else { + skipTest(1); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -4478,6 +4507,21 @@ skipTest(2); } }); + + test('should provide the correct `predicate` arguments in a lazy chain sequence', 1, function() { + if (!isNpm) { + var args; + + _(array).map(function(n) { return n * n; }).takeRightWhile(function() { + args = slice.call(arguments); + }).value(); + + deepEqual(args, [16, 3, array]); + } + else { + skipTest(1); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -4540,6 +4584,21 @@ skipTest(2); } }); + + test('should provide the correct `predicate` arguments in a lazy chain sequence', 1, function() { + if (!isNpm) { + var args; + + _(array).map(function(n) { return n * n; }).takeWhile(function() { + args = slice.call(arguments); + }).value(); + + deepEqual(args, [1, 0, array]); + } + else { + skipTest(1); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -14310,13 +14369,13 @@ (function() { test('should clone the chained sequence planting `value` as the wrapped value', 2, function() { if (!isNpm) { - var array1 = [1, 2], - array2 = [3, 4], - wrapper1 = _(array1).map(_.partial(Math.pow, _, 2)), + var array1 = [5, null, 3, null, 1], + array2 = [10, null, 8, null, 6], + wrapper1 = _(array1).compact().map(_.partial(Math.pow, _, 2)).takeRight(2).sort(), wrapper2 = wrapper1.plant(array2); - deepEqual(wrapper2.value(), [9, 16]); - deepEqual(wrapper1.value(), [1, 4]); + deepEqual(wrapper2.value(), [36, 64]); + deepEqual(wrapper1.value(), [1, 9]); } else { skipTest(2); From e91a662491146da1c25e25e4da234c8bcafd00b3 Mon Sep 17 00:00:00 2001 From: Nicolas Chambrier Date: Sat, 7 Feb 2015 20:28:34 +0100 Subject: [PATCH 18/61] Add _.spread. --- lodash.src.js | 40 ++++++++++++++++++++++++++++++++++++++++ test/test.js | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/lodash.src.js b/lodash.src.js index 4048721294..dbe7c46d17 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7579,6 +7579,45 @@ return createWrapper(func, REARG_FLAG, null, null, null, indexes); } + /** + * Creates a function accepting an array as argument, that invokes `func` + * with arguments taken from this array, like `Function#apply`. + * This works obviously well with `Promise.all`. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} The function to alter. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {*} Returns the new function. + * @example + * + * var spread = _.spread(function (who, what) { + * return who + ' says ' + what; + * }); + * + * spread(['John', 'hello']) // => 'John says hello' + * + * // With Promise + * var numbers = Promise.all([ + * Promise.resolve(42), + * Promise.resolve(33) + * ]) + * + * numbers.then(_.spread(function (a, b) { return a + b })) // Promise of 75 + * // instead of... + * numbers.then(function (nums) { return nums[0] + nums[1] }) + */ + function spread (func, thisArg) { + if (typeof func !== 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + + return function(array) { + return func.apply(thisArg, array); + }; + } + /** * Creates a function that only invokes `func` at most once per every `wait` * milliseconds. The created function comes with a `cancel` method to cancel @@ -10752,6 +10791,7 @@ lodash.slice = slice; lodash.sortBy = sortBy; lodash.sortByAll = sortByAll; + lodash.spread = spread; lodash.take = take; lodash.takeRight = takeRight; lodash.takeRightWhile = takeRightWhile; diff --git a/test/test.js b/test/test.js index afeab682fb..03b30c98f2 100644 --- a/test/test.js +++ b/test/test.js @@ -12240,6 +12240,53 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.spread'); + + (function() { + function Pair(x, y) { + this.x = x; + this.y = y; + + return 42; + } + + function divide(n, d) { + return n / d; + } + + test('should pass arguments to `func`', 1, function() { + var spread = _.spread(divide); + strictEqual(spread([4, 2]), 2); + }); + + test('should fail when receiving non-array argument', 1, function() { + var spread = _.spread(divide); + var err; + try { + spread(4, 2); + } catch (e) { + err = e; + } + strictEqual(_.isError(err), true); + }); + + test('should dynamically `func` to `thisArg`', 2, function() { + var self = {z: 3}; + var spread = _.spread(Pair, self); + var result = spread([1, 2]); + strictEqual(result, 42); + deepEqual(self, {x: 1, y: 2, z: 3}); + }); + + test('should use `undefined` for extra values', 1, function() { + var self = {}; + _.spread(Pair, self)([1]); + deepEqual(self, {x: 1, y: undefined}); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.support'); (function() { @@ -14960,6 +15007,7 @@ 'partial', 'partialRight', 'rearg', + 'spread', 'throttle' ]; @@ -15078,7 +15126,7 @@ }); }); - test('should throw an error for falsey arguments', 22, function() { + test('should throw an error for falsey arguments', 23, function() { _.each(rejectFalsey, function(methodName) { var expected = _.map(falsey, _.constant(true)), func = _[methodName]; From 396023542839e737113956f8b649259e57e9b27a Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 15:22:38 -0800 Subject: [PATCH 19/61] Cleanup `_.spread` docs & tests. --- lodash.src.js | 35 ++++++++++++++++++---------------- test/test.js | 53 +++++++++++++++++++++------------------------------ 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index dbe7c46d17..387a367281 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -7580,39 +7580,42 @@ } /** - * Creates a function accepting an array as argument, that invokes `func` - * with arguments taken from this array, like `Function#apply`. - * This works obviously well with `Promise.all`. + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and the array of arguments provided to the created function much like + * [Function#apply](http://es5.github.io/#x15.3.4.3). * * @static * @memberOf _ * @category Function - * @param {Function} The function to alter. + * @param {Function} The function to spread arguments over. * @param {*} [thisArg] The `this` binding of `func`. * @returns {*} Returns the new function. * @example * - * var spread = _.spread(function (who, what) { + * var spread = _.spread(function(who, what) { * return who + ' says ' + what; * }); * - * spread(['John', 'hello']) // => 'John says hello' + * spread(['Fred', 'hello']); + * // => 'Fred says hello' * - * // With Promise + * // with a Promise * var numbers = Promise.all([ - * Promise.resolve(42), - * Promise.resolve(33) - * ]) + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * var add = function(x, y) { + * return x + y; + * }; * - * numbers.then(_.spread(function (a, b) { return a + b })) // Promise of 75 - * // instead of... - * numbers.then(function (nums) { return nums[0] + nums[1] }) + * numbers.then(_.spread(add)); + * // => a Promise of 76 */ - function spread (func, thisArg) { - if (typeof func !== 'function') { + function spread(func, thisArg) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - return function(array) { return func.apply(thisArg, array); }; diff --git a/test/test.js b/test/test.js index 03b30c98f2..10bba4d21a 100644 --- a/test/test.js +++ b/test/test.js @@ -12243,45 +12243,36 @@ QUnit.module('lodash.spread'); (function() { - function Pair(x, y) { - this.x = x; - this.y = y; - - return 42; - } - - function divide(n, d) { - return n / d; + function add(x, y) { + return x + y; } - test('should pass arguments to `func`', 1, function() { - var spread = _.spread(divide); - strictEqual(spread([4, 2]), 2); + test('should spread arguments to `func`', 1, function() { + var spread = _.spread(add); + strictEqual(spread([4, 2]), 6); }); - test('should fail when receiving non-array argument', 1, function() { - var spread = _.spread(divide); - var err; - try { - spread(4, 2); - } catch (e) { - err = e; - } - strictEqual(_.isError(err), true); + test('should throw a TypeError when receiving a non-array `array` argument', 1, function() { + raises(function() { _.spread(4, 2); }, TypeError); }); - test('should dynamically `func` to `thisArg`', 2, function() { - var self = {z: 3}; - var spread = _.spread(Pair, self); - var result = spread([1, 2]); - strictEqual(result, 42); - deepEqual(self, {x: 1, y: 2, z: 3}); + test('should provide the correct `func` arguments', 1, function() { + var args; + + var spread = _.spread(function() { + args = slice.call(arguments); + }); + + spread([4, 2], 'ignored'); + deepEqual(args, [4, 2]); }); - test('should use `undefined` for extra values', 1, function() { - var self = {}; - _.spread(Pair, self)([1]); - deepEqual(self, {x: 1, y: undefined}); + test('should support the `thisArg` argument', 1, function() { + var spread = _.spread(function(x, y) { + return this[x] + this[y]; + }, [4, 2]); + + strictEqual(spread([0, 1]), 6); }); }()); From b8293838646b608e35ab4e5168e70ec4c7d9d658 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 15:23:10 -0800 Subject: [PATCH 20/61] Cleanup docs for `_.callback`. [ci skip] --- lodash.src.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 387a367281..c7b92396ce 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -10291,10 +10291,11 @@ } /** - * Creates a function bound to an optional `thisArg`. If `func` is a property - * name the created callback returns the property value for a given element. - * If `func` is an object the created callback returns `true` for elements - * that contain the equivalent object properties, otherwise it returns `false`. + * 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 + * created callback returns the property value for a given element. If `func` + * is an object the created callback returns `true` for elements that contain + * the equivalent object properties, otherwise it returns `false`. * * @static * @memberOf _ From 34eec362e5fdc48a6572002615ba9c47c04cf702 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 15:23:24 -0800 Subject: [PATCH 21/61] Add methods to `lodash` docs. [ci skip] --- lodash.src.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index c7b92396ce..2377d3a3fd 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -860,17 +860,17 @@ * * The chainable wrapper functions are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, - * `callback`, `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, - * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, - * `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, - * `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, - * `initial`, `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, - * `mapValues`, `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, + * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, + * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, + * `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, + * `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, `keysIn`, + * `map`, `mapValues`, `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, - * `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, + * `plant`, `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, * `rearg`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `sortByAll`, `splice`, `take`, `takeRight`, `takeRightWhile`, + * `sortBy`, `sortByAll`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` From 0b922b1ed1f87824795ae85d26f4fd2150c6a9fc Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 15:43:39 -0800 Subject: [PATCH 22/61] Move `_.support` tests to be in alphebetic API order. --- test/test.js | 70 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/test/test.js b/test/test.js index 10bba4d21a..5e7f53aec9 100644 --- a/test/test.js +++ b/test/test.js @@ -12278,41 +12278,6 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.support'); - - (function() { - test('should contain properties with boolean values', 1, function() { - ok(_.every(_.values(_.support), function(value) { - return value === true || value === false; - })); - }); - - 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' - ]; - - ok(_.isEmpty(_.difference(_.keys(_.support), props))); - }); - }()); - - /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.startsWith'); (function() { @@ -12390,6 +12355,41 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.support'); + + (function() { + test('should contain properties with boolean values', 1, function() { + ok(_.every(_.values(_.support), function(value) { + return value === true || value === false; + })); + }); + + 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' + ]; + + ok(_.isEmpty(_.difference(_.keys(_.support), props))); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.tap'); (function() { From 1c9290aded577ce25b6056d0427c50a8523422f6 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 20:36:51 -0800 Subject: [PATCH 23/61] Add `_.includes`, `_.indexOf`, `_.lastIndexOf`, `_.map`, `_.mapValues`, & a few other tests. --- test/test.js | 89 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 24 deletions(-) diff --git a/test/test.js b/test/test.js index 5e7f53aec9..88bd320c9e 100644 --- a/test/test.js +++ b/test/test.js @@ -1781,8 +1781,8 @@ var object = { 'a': value, 'b': { 'c': value } }, actual = func(object); - notStrictEqual(actual, object); deepEqual(actual, object); + notStrictEqual(actual, object); var expected = typeof value == 'function' ? { 'c': Foo.c } : (value && {}); deepEqual(func(value), expected); @@ -4059,8 +4059,10 @@ QUnit.module('lodash.filter'); (function() { + var array = [1, 2, 3]; + test('should return elements `predicate` returns truthy for', 1, function() { - var actual = _.filter([1, 2, 3], function(num) { + var actual = _.filter(array, function(num) { return num % 2; }); @@ -4134,13 +4136,12 @@ }); test('should return `' + expected[1] + '` for empty collections', 1, function() { - var actual = [], - emptyValues = _.endsWith(methodName, 'Index') ? _.reject(empties, _.isPlainObject) : empties, - expecting = _.map(emptyValues, function() { return expected[1]; }); + var emptyValues = _.endsWith(methodName, 'Index') ? _.reject(empties, _.isPlainObject) : empties, + expecting = _.map(emptyValues, _.constant(expected[1])); - _.each(emptyValues, function(value) { + var actual = _.map(emptyValues, function(value) { try { - actual.push(func(value, { 'a': 3 })); + return func(value, { 'a': 3 }); } catch(e) {} }); @@ -4806,9 +4807,12 @@ 'groupBy', 'indexBy', 'map', + 'mapValues', 'max', 'min', + 'omit', 'partition', + 'pick', 'reject', 'some' ]; @@ -4840,7 +4844,9 @@ var forInMethods = [ 'forIn', - 'forInRight' + 'forInRight', + 'omit', + 'pick' ]; var iterationMethods = [ @@ -4858,7 +4864,10 @@ 'forIn', 'forInRight', 'forOwn', - 'forOwnRight' + 'forOwnRight', + 'mapValues', + 'omit', + 'pick' ]; var rightMethods = [ @@ -5603,6 +5612,10 @@ strictEqual(_.includes([1, NaN, 3], NaN), true); }); + test('should match `-0` as `0`', 1, function() { + strictEqual(_.includes([-0], 0), true); + }); + test('should be aliased', 2, function() { strictEqual(_.contains, _.includes); strictEqual(_.include, _.includes); @@ -8435,6 +8448,10 @@ strictEqual(func([1, NaN, 3], NaN), 1); strictEqual(func([1, 3, NaN], NaN, true), 2); }); + + test('`_.' + methodName + '` should match `-0` as `0`', 1, function() { + strictEqual(func([-0], 0), 0); + }); }); /*--------------------------------------------------------------------------*/ @@ -8444,6 +8461,14 @@ (function() { var array = [1, 2, 3]; + test('should map values in `collection` to a new array', 2, function() { + var object = { 'a': 1, 'b': 2, 'c': 3 }, + expected = ['1', '2', '3']; + + deepEqual(_.map(array, String), expected); + deepEqual(_.map(object, String), expected); + }); + test('should provide the correct `iteratee` arguments', 1, function() { var args; @@ -8537,16 +8562,29 @@ QUnit.module('lodash.mapValues'); (function() { - var object = { 'a': 1, 'b': 2, 'c': 3 }; + var array = [1, 2], + object = { 'a': 1, 'b': 2, 'c': 3 }; - test('should provide the correct `iteratee` arguments', 1, function() { - var args; + test('should map values in `object` to a new object', 1, function() { + var actual = _.mapValues(object, String); + deepEqual(actual, { 'a': '1', 'b': '2', 'c': '3' }); + }); - _.mapValues(object, function() { - args || (args = slice.call(arguments)); - }); + test('should treat arrays like objects', 1, function() { + var actual = _.mapValues(array, String); + deepEqual(actual, { '0': '1', '1': '2' }); + }); + + test('should provide the correct `iteratee` arguments', 2, function() { + _.each([object, array], function(value, index) { + var args; + + _.mapValues(value, function() { + args || (args = slice.call(arguments)); + }); - deepEqual(args, [1, 'a', object]); + deepEqual(args, [1, index ? '0' : 'a', value]); + }); }); test('should support the `thisArg` argument', 2, function() { @@ -8574,9 +8612,10 @@ deepEqual(actual, { 'a': 'a' }); }); - test('should work on an object with no `iteratee`', 1, function() { + test('should work on an object with no `iteratee`', 2, function() { var actual = _.mapValues({ 'a': 1, 'b': 2, 'c': 3 }); deepEqual(actual, object); + notStrictEqual(actual, object); }); test('should accept a falsey `object` argument', 1, function() { @@ -11176,8 +11215,10 @@ QUnit.module('lodash.reject'); (function() { + var array = [1, 2, 3]; + test('should return elements the `predicate` returns falsey for', 1, function() { - var actual = _.reject([1, 2, 3], function(num) { + var actual = _.reject(array, function(num) { return num % 2; }); @@ -13407,8 +13448,8 @@ test('should return a shallow clone of arrays', 2, function() { var actual = func(array); + deepEqual(actual, array); notStrictEqual(actual, array); - deepEqual(func(array), array); }); test('should work with a node list for `collection` (test in IE < 9)', 1, function() { @@ -13611,8 +13652,8 @@ result[key] = this[key]; }, null, object); - notStrictEqual(actual, object); deepEqual(actual, object); + notStrictEqual(actual, object); }); }); @@ -14370,9 +14411,9 @@ wrapped = _(array).concat([2, 3]), actual = wrapped.value(); - notStrictEqual(actual, array); - deepEqual(actual, [1, 2, 3]); deepEqual(array, [1]); + deepEqual(actual, [1, 2, 3]); + notStrictEqual(actual, array); } else { skipTest(3); @@ -14569,9 +14610,9 @@ wrapped = _(array).slice(0, 2), actual = wrapped.value(); - notStrictEqual(actual, array); - deepEqual(actual, [1, 2]); deepEqual(array, [1, 2, 3]); + deepEqual(actual, [1, 2]); + notStrictEqual(actual, array); } else { skipTest(3); From 7dcd690f611db50fc79396b5911a36cfe1ee3e10 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 8 Feb 2015 22:19:57 -0800 Subject: [PATCH 24/61] Add object test for `_.max` and `_.min` being used as an iteratee for `_.map`. --- test/test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test.js b/test/test.js index 88bd320c9e..32df251ede 100644 --- a/test/test.js +++ b/test/test.js @@ -9329,14 +9329,14 @@ strictEqual(func(array), isMax ? 499999 : 0); }); - test('`_.' + methodName + '` should work as an iteratee for `_.map`', 2, function() { - var array = [[2, 3, 1], [5, 6, 4], [8, 9, 7]], - actual = _.map(array, func); - - deepEqual(actual, isMax ? [3, 6, 9] : [1, 4, 7]); - - actual = _.map('abc', func); - deepEqual(actual, ['a', 'b', 'c']); + test('`_.' + methodName + '` should work as an iteratee for `_.map`', 3, function() { + var arrays = [[2, 1], [5, 4], [7, 8]], + objects = [{ 'a': 2, 'b': 1 }, { 'a': 5, 'b': 4 }, { 'a': 7, 'b': 8 }], + expected = isMax ? [2, 5, 8] : [1, 4, 7]; + + deepEqual(_.map(arrays, func), expected); + deepEqual(_.map(objects, func), expected); + deepEqual(_.map('abc', func), ['a', 'b', 'c']); }); test('`_.' + methodName + '` should work when chaining on an array with only one value', 1, function() { From 035ed5f49b246d260579b3f3cbcf6797a2905f30 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 00:07:39 -0800 Subject: [PATCH 25/61] Add `_.fill`. --- lodash.src.js | 54 +++++++++++++++++++++ test/test.js | 127 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 2 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 2377d3a3fd..9243399688 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -2027,6 +2027,36 @@ return result; } + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = start == null ? 0 : (+start || 0); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + + while (start < length) { + array[start++] = value; + } + return array; + } + /** * The base implementation of `_.filter` without support for callback * shorthands or `this` binding. @@ -4365,6 +4395,29 @@ return baseSlice(array, index); } + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + /** * This method is like `_.find` except that it returns the index of the first * element `predicate` returns truthy for, instead of the element itself. @@ -10747,6 +10800,7 @@ lodash.dropRight = dropRight; lodash.dropRightWhile = dropRightWhile; lodash.dropWhile = dropWhile; + lodash.fill = fill; lodash.filter = filter; lodash.flatten = flatten; lodash.flattenDeep = flattenDeep; diff --git a/test/test.js b/test/test.js index 32df251ede..30376a7ac4 100644 --- a/test/test.js +++ b/test/test.js @@ -4056,6 +4056,124 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.fill'); + + (function() { + test('should work with a positive `start`', 1, function() { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', 1), [1, 'a', 'a']); + }); + + test('should work with a `start` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(start) { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', start), [1, 2, 3]); + }); + }); + + test('should treat falsey `start` values as `0`', 1, function() { + var expected = _.map(falsey, _.constant(['a', 'a', 'a'])); + + var actual = _.map(falsey, function(start) { + var array = [1, 2, 3]; + return _.fill(array, 'a', start); + }); + + deepEqual(actual, expected); + }); + + test('should work with a negative `start`', 1, function() { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', -1), [1, 2, 'a']); + }); + + test('should work with a negative `start` <= negative `array.length`', 3, function() { + _.each([-3, -4, -Infinity], function(start) { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', start), ['a', 'a', 'a']); + }); + }); + + test('should work with `start` >= `end`', 2, function() { + _.each([2, 3], function(start) { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', start, 2), [1, 2, 3]); + }); + }); + + test('should work with a positive `end`', 1, function() { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', 0, 1), ['a', 2, 3]); + }); + + test('should work with a `end` >= `array.length`', 4, function() { + _.each([3, 4, Math.pow(2, 32), Infinity], function(end) { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', 0, end), ['a', 'a', 'a']); + }); + }); + + test('should treat falsey `end` values, except `undefined`, as `0`', 1, function() { + var expected = _.map(falsey, function(value) { + return value === undefined ? ['a', 'a', 'a'] : [1, 2, 3]; + }); + + var actual = _.map(falsey, function(end) { + var array = [1, 2, 3]; + return _.fill(array, 'a', 0, end); + }); + + deepEqual(actual, expected); + }); + + test('should work with a negative `end`', 1, function() { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', 0, -1), ['a', 'a', 3]); + }); + + test('should work with a negative `end` <= negative `array.length`', 3, function() { + _.each([-3, -4, -Infinity], function(end) { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a', 0, end), [1, 2, 3]); + }); + }); + + test('should coerce `start` and `end` to integers', 1, function() { + var positions = [[0.1, 1.1], ['0', 1], [0, '1'], ['1'], [NaN, 1], [1, NaN]]; + + var actual = _.map(positions, function(pos) { + var array = [1, 2, 3]; + return _.fill.apply(_, [array, 'a'].concat(pos)); + }); + + deepEqual(actual, [['a', 2, 3], ['a', 2, 3], ['a', 2, 3], [1, 'a', 'a'], ['a', 2, 3], [1, 2, 3]]); + }); + + test('should work as an iteratee for `_.map`', 1, function() { + var array = [[1, 2], [3, 4]], + actual = _.map(array, _.fill); + + deepEqual(actual, [[0, 0], [1, 1]]); + }); + + test('should return a wrapped value when chaining', 3, function() { + if (!isNpm) { + var array = [1, 2, 3], + wrapped = _(array).fill('a'), + actual = wrapped.value(); + + ok(wrapped instanceof _); + deepEqual(actual, ['a', 'a', 'a']); + strictEqual(actual, array); + } + else { + skipTest(3); + } + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.filter'); (function() { @@ -11881,7 +11999,12 @@ }); test('should coerce `start` and `end` to integers', 1, function() { - var actual = [_.slice(array, 0.1, 1.1), _.slice(array, '0', 1), _.slice(array, 0, '1'), _.slice(array, '1'), _.slice(array, NaN, 1), _.slice(array, 1, NaN)]; + var positions = [[0.1, 1.1], ['0', 1], [0, '1'], ['1'], [NaN, 1], [1, NaN]]; + + var actual = _.map(positions, function(pos) { + return _.slice.apply(_, [array].concat(pos)); + }); + deepEqual(actual, [[1], [1], [1], [2, 3], [1], []]); }); @@ -15092,7 +15215,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 206, function() { + test('should accept falsey arguments', 207, function() { var emptyArrays = _.map(falsey, _.constant([])), isExposed = '_' in root, oldDash = root._; From ee489fa8c02257aa63fa2472c31c818c493d79f7 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 00:08:13 -0800 Subject: [PATCH 26/61] Cleanup tests. --- test/test.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/test.js b/test/test.js index 30376a7ac4..ec4245a67b 100644 --- a/test/test.js +++ b/test/test.js @@ -11765,10 +11765,10 @@ test('should return a wrapped value when chaining and `n` is provided', 2, function() { if (!isNpm) { - var wrapped = _(array).sample(2); - ok(wrapped instanceof _); + var wrapped = _(array).sample(2), + actual = wrapped.value(); - var actual = wrapped.value(); + ok(wrapped instanceof _); ok(actual.length == 2 && actual[0] !== actual[1] && _.includes(array, actual[0]) && _.includes(array, actual[1])); } else { @@ -14600,8 +14600,8 @@ strictEqual(wrapped.pop(), 1); var actual = wrapped.value(); - strictEqual(actual, array); deepEqual(actual, []); + strictEqual(actual, array); } else { skipTest(5); @@ -14713,8 +14713,8 @@ strictEqual(wrapped.shift(), 2); var actual = wrapped.value(); - strictEqual(actual, array); deepEqual(actual, []); + strictEqual(actual, array); } else { skipTest(5); @@ -14775,12 +14775,11 @@ deepEqual(wrapped.splice(1, 1, 3).value(), [2]); deepEqual(wrapped.value(), [1, 3]); - deepEqual(wrapped.splice(0, 2).value(), [1, 3]); var actual = wrapped.value(); - strictEqual(actual, array); deepEqual(actual, []); + strictEqual(actual, array); } else { skipTest(5); From 044dd2af94a2541f88bda95e52ecb25b4bd302dd Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 00:09:24 -0800 Subject: [PATCH 27/61] Remove unneeded jsdoc Function type tags. [ci skip] --- lodash.src.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 9243399688..eb8ee9bd13 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -4226,7 +4226,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. @@ -4262,7 +4261,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. @@ -4308,7 +4306,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -4358,7 +4355,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -5032,7 +5028,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. @@ -5068,7 +5063,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. @@ -5114,7 +5108,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -5164,7 +5157,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -7509,7 +7501,6 @@ * * @static * @memberOf _ - * @type Function * @category Function * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. From d073e2a881b9f4a5e7c475840a71d38d7498c280 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 00:09:40 -0800 Subject: [PATCH 28/61] Add `_.fill` to `lodash` docs. [ci skip] --- lodash.src.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index eb8ee9bd13..935fc5319f 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -862,18 +862,19 @@ * `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`, `filter`, - * `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, - * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, - * `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, `keysIn`, - * `map`, `mapValues`, `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, - * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, - * `plant`, `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, - * `rearg`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `sortByAll`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, - * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, - * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, - * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` + * `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`, `mapValues`, `matches`, `memoize`, `merge`, `mixin`, + * `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `splice`, `spread`, + * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, + * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, + * `unshift`, `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, + * `zip`, and `zipObject` * * The wrapper functions that are **not** chainable by default are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, From 954b4d8075ea76b7bfd854e0be0df973236c25fe Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 00:32:07 -0800 Subject: [PATCH 29/61] Add mutation note to `_.fill` docs. [ci skip] --- lodash.src.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lodash.src.js b/lodash.src.js index 935fc5319f..39412b1a16 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -4396,6 +4396,8 @@ * Fills elements of `array` with `value` from `start` up to, but not * including, `end`. * + * **Note:** This method mutates `array`. + * * @private * @param {Array} array The array to fill. * @param {*} value The value to fill `array` with. From 3b805f1a24aab0bed6ac0c261d4272c7f5e195c0 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 01:14:55 -0800 Subject: [PATCH 30/61] Rebuild lodash. --- lodash.js | 399 ++++++++++++++++++++++++++++++++++++-------------- lodash.min.js | 157 ++++++++++---------- 2 files changed, 368 insertions(+), 188 deletions(-) diff --git a/lodash.js b/lodash.js index 11b3e2cd6c..052424f99e 100644 --- a/lodash.js +++ b/lodash.js @@ -728,7 +728,6 @@ setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, - unshift = arrayProto.unshift, WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers. */ @@ -780,7 +779,7 @@ /*------------------------------------------------------------------------*/ /** - * Creates a `lodash` object which wraps `value` to enable intuitive chaining. + * 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 @@ -806,20 +805,21 @@ * * The chainable wrapper functions are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, - * `callback`, `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, - * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, - * `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, - * `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, - * `initial`, `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, - * `mapValues`, `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, - * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, - * `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, - * `rearg`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `sortByAll`, `splice`, `take`, `takeRight`, `takeRightWhile`, - * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, - * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, - * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` + * `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`, `mapValues`, `matches`, `memoize`, `merge`, `mixin`, + * `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `splice`, `spread`, + * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, + * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, + * `unshift`, `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, + * `zip`, and `zipObject` * * The wrapper functions that are **not** chainable by default are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, @@ -843,7 +843,7 @@ * @constructor * @category Chain * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var wrapped = _([1, 2, 3]); @@ -862,12 +862,12 @@ * // => true */ function lodash(value) { - if (isObjectLike(value) && !isArray(value)) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { if (value instanceof LodashWrapper) { return value; } - if (hasOwnProperty.call(value, '__wrapped__')) { - return new LodashWrapper(value.__wrapped__, value.__chain__, arrayCopy(value.__actions__)); + if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); } } return new LodashWrapper(value); @@ -882,9 +882,9 @@ * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. */ function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; this.__actions__ = actions || []; this.__chain__ = !!chainAll; - this.__wrapped__ = value; } /** @@ -1017,14 +1017,14 @@ * @param {*} value The value to wrap. */ function LazyWrapper(value) { - this.actions = null; - this.dir = 1; - this.dropCount = 0; - this.filtered = false; - this.iteratees = null; - this.takeCount = POSITIVE_INFINITY; - this.views = null; - this.wrapped = value; + this.__wrapped__ = value; + this.__actions__ = null; + this.__dir__ = 1; + this.__dropCount__ = 0; + this.__filtered__ = false; + this.__iteratees__ = null; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = null; } /** @@ -1036,18 +1036,18 @@ * @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; - result.dir = this.dir; - result.dropCount = this.dropCount; - result.filtered = this.filtered; - result.iteratees = iteratees ? arrayCopy(iteratees) : null; - result.takeCount = this.takeCount; - result.views = views ? arrayCopy(views) : null; + var actions = this.__actions__, + iteratees = this.__iteratees__, + views = this.__views__, + result = new LazyWrapper(this.__wrapped__); + + result.__actions__ = actions ? arrayCopy(actions) : null; + result.__dir__ = this.__dir__; + result.__dropCount__ = this.__dropCount__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__takeCount__ = this.__takeCount__; + result.__views__ = views ? arrayCopy(views) : null; return result; } @@ -1060,13 +1060,13 @@ * @returns {Object} Returns the new reversed `LazyWrapper` object. */ function lazyReverse() { - if (this.filtered) { + if (this.__filtered__) { var result = new LazyWrapper(this); - result.dir = -1; - result.filtered = true; + result.__dir__ = -1; + result.__filtered__ = true; } else { result = this.clone(); - result.dir *= -1; + result.__dir__ *= -1; } return result; } @@ -1080,20 +1080,20 @@ * @returns {*} Returns the unwrapped value. */ function lazyValue() { - var array = this.wrapped.value(); + var array = this.__wrapped__.value(); if (!isArray(array)) { - return baseWrapperValue(array, this.actions); + return baseWrapperValue(array, this.__actions__); } - var dir = this.dir, + var dir = this.__dir__, isRight = dir < 0, - view = getView(0, array.length, this.views), + view = getView(0, array.length, this.__views__), start = view.start, end = view.end, length = end - start, - dropCount = this.dropCount, - takeCount = nativeMin(length, this.takeCount - dropCount), + dropCount = this.__dropCount__, + takeCount = nativeMin(length, this.__takeCount__ - dropCount), index = isRight ? end : start - 1, - iteratees = this.iteratees, + iteratees = this.__iteratees__, iterLength = iteratees ? iteratees.length : 0, resIndex = 0, result = []; @@ -1749,7 +1749,7 @@ * @returns {number} Returns the timer id. */ function baseDelay(func, wait, args, fromIndex) { - if (!isFunction(func)) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); @@ -1869,6 +1869,36 @@ return result; } + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = start == null ? 0 : (+start || 0); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + + while (start < length) { + array[start++] = value; + } + return array; + } + /** * The base implementation of `_.filter` without support for callback * shorthands or `this` binding. @@ -2201,7 +2231,7 @@ * shorthands or `this` binding. * * @private - * @param {Object} source The object to inspect. + * @param {Object} object The object to inspect. * @param {Array} props The source property names to match. * @param {Array} values The source values to match. * @param {Array} strictCompareFlags Strict comparison flags for source values. @@ -3173,7 +3203,7 @@ */ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { var isBindKey = bitmask & BIND_KEY_FLAG; - if (!isBindKey && !isFunction(func)) { + if (!isBindKey && typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } var length = partials ? partials.length : 0; @@ -3203,9 +3233,9 @@ if (bitmask == BIND_FLAG) { var result = createBindWrapper(newData[0], newData[2]); } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { - result = createPartialWrapper.apply(null, newData); + result = createPartialWrapper.apply(undefined, newData); } else { - result = createHybridWrapper.apply(null, newData); + result = createHybridWrapper.apply(undefined, newData); } var setter = data ? baseSetData : setData; return setter(result, newData); @@ -3893,6 +3923,19 @@ return isObject(value) ? value : Object(value); } + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper + ? wrapper.clone() + : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + /*------------------------------------------------------------------------*/ /** @@ -3904,7 +3947,7 @@ * @memberOf _ * @category Array * @param {Array} array The array to process. - * @param {numer} [size=1] The length of each chunk. + * @param {number} [size=1] The length of each chunk. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the new array containing chunks. * @example @@ -3999,7 +4042,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. @@ -4035,7 +4077,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. @@ -4081,7 +4122,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -4131,7 +4171,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -4168,6 +4207,31 @@ return baseSlice(array, index); } + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + /** * This method is like `_.find` except that it returns the index of the first * element `predicate` returns truthy for, instead of the element itself. @@ -4782,7 +4846,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. @@ -4818,7 +4881,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. @@ -4864,7 +4926,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -4914,7 +4975,6 @@ * * @static * @memberOf _ - * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked @@ -5199,7 +5259,7 @@ * @memberOf _ * @category Chain * @param {*} value The value to wrap. - * @returns {Object} Returns the new `lodash` object. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var users = [ @@ -5275,7 +5335,7 @@ * @name chain * @memberOf _ * @category Chain - * @returns {*} Returns the `lodash` object. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var users = [ @@ -5298,6 +5358,74 @@ return chain(this); } + /** + * Executes the chained sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapper = wrapper.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapper.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value()); + } + + /** + * Creates a clone of the chained sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).map(_.partial(Math.pow, _, 2)); + * + * var other = [3, 4]; + * var otherWrapper = wrapper.plant(other); + * + * otherWrapper.value(); + * // => [9, 16] + * + * wrapper.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof LodashWrapper) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + /** * Reverses the wrapped array so the first element becomes the last, the * second element becomes the second to last, and so on. @@ -5307,7 +5435,7 @@ * @name reverse * @memberOf _ * @category Chain - * @returns {Object} Returns the new reversed `lodash` object. + * @returns {Object} Returns the new reversed `lodash` wrapper instance. * @example * * var array = [1, 2, 3]; @@ -5352,7 +5480,7 @@ * * @name value * @memberOf _ - * @alias toJSON, valueOf + * @alias run, toJSON, valueOf * @category Chain * @returns {*} Returns the resolved unwrapped value. * @example @@ -6471,8 +6599,8 @@ * // => logs 'done saving!' after the two async saves have completed */ function after(n, func) { - if (!isFunction(func)) { - if (isFunction(n)) { + if (typeof func != 'function') { + if (typeof n == 'function') { var temp = n; n = func; func = temp; @@ -6530,8 +6658,8 @@ */ function before(n, func) { var result; - if (!isFunction(func)) { - if (isFunction(n)) { + if (typeof func != 'function') { + if (typeof n == 'function') { var temp = n; n = func; func = temp; @@ -6853,7 +6981,7 @@ maxWait = false, trailing = true; - if (!isFunction(func)) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } wait = wait < 0 ? 0 : wait; @@ -7023,7 +7151,7 @@ length = funcs.length; if (!length) { - return function() {}; + return function() { return arguments[0]; }; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); @@ -7068,7 +7196,7 @@ fromIndex = funcs.length - 1; if (fromIndex < 0) { - return function() {}; + return function() { return arguments[0]; }; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); @@ -7138,7 +7266,7 @@ * // => { 'user': 'barney' } */ function memoize(func, resolver) { - if (!isFunction(func) || (resolver && !isFunction(resolver))) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { @@ -7176,7 +7304,7 @@ * // => [1, 3, 5] */ function negate(predicate) { - if (!isFunction(predicate)) { + if (typeof predicate != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return function() { @@ -7191,7 +7319,6 @@ * * @static * @memberOf _ - * @type Function * @category Function * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. @@ -7314,6 +7441,48 @@ return createWrapper(func, REARG_FLAG, null, null, null, indexes); } + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and the array of arguments provided to the created function much like + * [Function#apply](http://es5.github.io/#x15.3.4.3). + * + * @static + * @memberOf _ + * @category Function + * @param {Function} The function to spread arguments over. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {*} Returns the new function. + * @example + * + * var spread = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * spread(['Fred', 'hello']); + * // => 'Fred says hello' + * + * // with a Promise + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * var add = function(x, y) { + * return x + y; + * }; + * + * numbers.then(_.spread(add)); + * // => a Promise of 76 + */ + function spread(func, thisArg) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(thisArg, array); + }; + } + /** * Creates a function that only invokes `func` at most once per every `wait` * milliseconds. The created function comes with a `cancel` method to cancel @@ -7356,7 +7525,7 @@ var leading = true, trailing = true; - if (!isFunction(func)) { + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } if (options === false) { @@ -7832,7 +8001,7 @@ * @static * @memberOf _ * @category Lang - * @param {Object} source The object to inspect. + * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Function} [customizer] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `customizer`. @@ -8620,7 +8789,7 @@ var Ctor = object.constructor, index = -1, - isProto = typeof Ctor == 'function' && Ctor.prototype == object, + isProto = typeof Ctor == 'function' && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; @@ -8913,7 +9082,7 @@ if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(typeof Ctor == 'function' && Ctor.prototype); + accumulator = baseCreate(isFunction(Ctor) && Ctor.prototype); } } else { accumulator = {}; @@ -9916,8 +10085,8 @@ /*------------------------------------------------------------------------*/ /** - * Attempts to invoke `func`, returning either the result or the caught - * error object. + * Attempts to invoke `func`, returning either the result or the caught error + * object. Any additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ @@ -9927,9 +10096,9 @@ * @example * * // avoid throwing errors for invalid selectors - * var elements = _.attempt(function() { + * var elements = _.attempt(function(selector) { * return document.querySelectorAll(selector); - * }); + * }, '>_>'); * * if (_.isError(elements)) { * elements = []; @@ -9937,17 +10106,18 @@ */ function attempt(func) { try { - return func(); + return func.apply(undefined, baseSlice(arguments, 1)); } catch(e) { return isError(e) ? e : Error(e); } } /** - * Creates a function bound to an optional `thisArg`. If `func` is a property - * name the created callback returns the property value for a given element. - * If `func` is an object the created callback returns `true` for elements - * that contain the equivalent object properties, otherwise it returns `false`. + * 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 + * created callback returns the property value for a given element. If `func` + * is an object the created callback returns `true` for elements that contain + * the equivalent object properties, otherwise it returns `false`. * * @static * @memberOf _ @@ -10077,6 +10247,9 @@ * }); * } * + * // use `_.runInContext` to avoid potential conflicts (esp. in Node.js) + * var _ = require('lodash').runInContext(); + * * _.mixin({ 'vowels': vowels }); * _.vowels('fred'); * // => ['e'] @@ -10351,7 +10524,11 @@ /*------------------------------------------------------------------------*/ // Ensure `new LodashWrapper` is an instance of `lodash`. - LodashWrapper.prototype = lodash.prototype; + LodashWrapper.prototype = baseCreate(lodash.prototype); + + // Ensure `new LazyWraper` is an instance of `LodashWrapper` + LazyWrapper.prototype = baseCreate(LodashWrapper.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; // Add functions to the `Map` cache. MapCache.prototype['delete'] = mapDelete; @@ -10392,6 +10569,7 @@ lodash.dropRight = dropRight; lodash.dropRightWhile = dropRightWhile; lodash.dropWhile = dropWhile; + lodash.fill = fill; lodash.filter = filter; lodash.flatten = flatten; lodash.flattenDeep = flattenDeep; @@ -10440,6 +10618,7 @@ lodash.slice = slice; lodash.sortBy = sortBy; lodash.sortByAll = sortByAll; + lodash.spread = spread; lodash.take = take; lodash.takeRight = takeRight; lodash.takeRightWhile = takeRightWhile; @@ -10613,14 +10792,15 @@ // Add `LazyWrapper` methods that accept an `iteratee` value. arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { - var isFilter = index == LAZY_FILTER_FLAG; + var isFilter = index == LAZY_FILTER_FLAG, + isWhile = index == LAZY_WHILE_FLAG; LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { var result = this.clone(), - filtered = result.filtered, - iteratees = result.iteratees || (result.iteratees = []); + filtered = result.__filtered__, + iteratees = result.__iteratees__ || (result.__iteratees__ = []); - result.filtered = filtered || isFilter || (index == LAZY_WHILE_FLAG && result.dir < 0); + result.__filtered__ = filtered || isFilter || (isWhile && result.__dir__ < 0); iteratees.push({ 'iteratee': getCallback(iteratee, thisArg, 3), 'type': index }); return result; }; @@ -10628,19 +10808,19 @@ // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. arrayEach(['drop', 'take'], function(methodName, index) { - var countName = methodName + 'Count', + var countName = '__' + methodName + 'Count__', whileName = methodName + 'While'; LazyWrapper.prototype[methodName] = function(n) { n = n == null ? 1 : nativeMax(+n || 0, 0); var result = this.clone(); - if (result.filtered) { + if (result.__filtered__) { var value = result[countName]; result[countName] = index ? nativeMin(value, n) : (value + n); } else { - var views = result.views || (result.views = []); - views.push({ 'size': n, 'type': methodName + (result.dir < 0 ? 'Right' : '') }); + var views = result.__views__ || (result.__views__ = []); + views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); } return result; }; @@ -10683,14 +10863,9 @@ }); LazyWrapper.prototype.dropWhile = function(iteratee, thisArg) { - var done, - lastIndex, - isRight = this.dir < 0; - + var done; iteratee = getCallback(iteratee, thisArg, 3); return this.filter(function(value, index, array) { - done = done && (isRight ? index < lastIndex : index > lastIndex); - lastIndex = index; return done || (done = !iteratee(value, index, array)); }); }; @@ -10740,8 +10915,8 @@ var wrapper = onlyLazy ? value : new LazyWrapper(this), result = func.apply(wrapper, args); - if (!retUnwrapped && (isHybrid || result.actions)) { - var actions = result.actions || (result.actions = []); + if (!retUnwrapped && (isHybrid || result.__actions__)) { + var actions = result.__actions__ || (result.__actions__ = []); actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); } return new LodashWrapper(result, chainAll); @@ -10774,9 +10949,11 @@ // Add chaining functions to the lodash wrapper. lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.plant = wrapperPlant; lodash.prototype.reverse = wrapperReverse; lodash.prototype.toString = wrapperToString; - lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; // Add function aliases to the lodash wrapper. lodash.prototype.collect = lodash.prototype.map; diff --git a/lodash.min.js b/lodash.min.js index b83eca6055..7592d76e39 100644 --- a/lodash.min.js +++ b/lodash.min.js @@ -4,82 +4,85 @@ * Build: `lodash modern -o ./lodash.js` */ ;(function(){function n(n,t){if(n!==t){var r=n===n,e=t===t;if(n>t||!r||typeof n=="undefined"&&e)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=[];++re&&(e=u)}return e}function Yt(n,t,r,e){var u=-1,o=n.length;for(e&&o&&(r=n[++u]);++ui(r,f)&&u.push(f);return u}function or(n,t){var r=n?n.length:0;if(!ue(r))return gr(n,t);for(var e=-1,u=se(n);++et&&(t=-t>u?0:u+t),r=typeof r=="undefined"||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=_u(u);++eu(f,s)&&((r||a)&&f.push(s),c.push(l))}return c}function Or(n,t){for(var r=-1,e=t.length,u=_u(e);++r>>1,i=n[o]; -(r?i<=t:it||null==r)return r;if(3=o&&a<=i&&(e=O&&t>u||e>u&&t>=O)||o)&&(t&x&&(r[2]=p[2],a|=e&x?0:j),(e=p[3])&&(u=r[3],r[3]=u?Ur(u,e,p[4]):zt(e),r[4]=u?v(r[3],B):zt(p[4])),(e=p[5])&&(u=r[5],r[5]=u?Fr(u,e,p[6]):zt(e),r[6]=u?v(r[5],B):zt(p[6])),(e=p[7])&&(r[7]=zt(e)),t&C&&(r[8]=null==r[8]?p[8]:eo(r[8],p[8])),null==r[9]&&(r[9]=p[9]),r[0]=p[0],r[1]=a),t=r[1],a=r[9]}return r[9]=null==a?f?0:n.length:ro(a-c,0)||0,(p?mo:xo)(t==x?Br(r[0],r[2]):t!=R&&t!=(x|R)||r[4].length?qr.apply(null,r):Kr.apply(null,r),r) -}function Yr(n,t,r,e,u,o,i){var a=-1,f=n.length,c=t.length,l=true;if(f!=c&&(!u||c<=f))return false;for(;l&&++au)||i===e&&i===o)&&(u=i,o=n) -}),o}function Xr(n,t,r){var e=Wt.callback||pu,e=e===pu?tr:e;return r?e(n,t,r):e}function Hr(n,r,e){var u=Wt.indexOf||de,u=u===de?t:u;return n?u(n,r,e):u}function Qr(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&Wu.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function ne(n){return n=n.constructor,typeof n=="function"&&n instanceof n||(n=ju),new n}function te(n,t,r){var e=n.constructor;switch(t){case J:return Nr(n);case M:case q:return new e(+n);case X:case H:case Q:case nt:case tt:case rt:case et:case ut:case ot:return t=n.buffer,new e(r?Nr(t):t,n.byteOffset,n.length); -case V:case G:return new e(n);case Z:var u=new e(n.source,yt.exec(n));u.lastIndex=n.lastIndex}return u}function re(n,t){return n=+n,t=null==t?go:t,-1t?0:t)):[]}function he(n,t,r){var e=n?n.length:0;return e?((r?ee(n,t,r):null==t)&&(t=1),t=e-(+t||0),Er(n,0,0>t?0:t)):[]}function ge(n,t,r){var e=-1,u=n?n.length:0;for(t=Xr(t,r,3);++ee?ro(u+e,0):e||0;else if(e)return e=Tr(n,r),n=n[e],(r===r?r===n:n!==n)?e:-1; -return t(n,r,e)}function ye(n){return pe(n,1)}function _e(n,r,e,u){if(!n||!n.length)return[];typeof r!="boolean"&&null!=r&&(u=e,e=ee(n,r,u)?null:r,r=false);var o=Xr();if((o!==tr||null!=e)&&(e=o(e,u,3)),r&&Hr()==t){r=e;var i;e=-1,u=n.length;for(var o=-1,a=[];++e>>0,e=_u(r);++tr?ro(e+r,0):r||0:0,typeof n=="string"||!Co(n)&&Qe(n)?rarguments.length,or)}function Te(n,t,r,e){return(Co(n)?Zt:kr)(n,Xr(t,e,4),r,3>arguments.length,ir)}function Se(n,t,r){return(r?ee(n,t,r):null==t)?(n=le(n),t=n.length,0t?0:+t||0,n.length),n) -}function We(n){n=le(n);for(var t=-1,r=n.length,e=_u(r);++t=r||r>t?(a&&Du(a),r=p,a=s=p=b,r&&(h=Oo(),f=n.apply(l,i),s||a||(i=l=null))):s=Yu(e,r)}function u(){s&&Du(s),a=s=p=b,(v||g!==t)&&(h=Oo(),f=n.apply(l,i),s||a||(i=l=null)) -}function o(){if(i=arguments,c=Oo(),l=this,p=v&&(s||!d),false===g)var r=d&&!s;else{a||d||(h=c);var o=g-(c-h),y=0>=o||o>g;y?(a&&(a=Du(a)),h=c,f=n.apply(l,i)):a||(a=Yu(u,o))}return y&&s?s=Du(s):s||t===g||(s=Yu(e,t)),r&&(y=true,f=n.apply(l,i)),!y||s||a||(i=l=null),f}var i,a,f,c,l,s,p,h=0,g=false,v=true;if(!Ze(n))throw new Ru($);if(t=0>t?0:t,true===r)var d=true,v=false;else Ge(r)&&(d=r.leading,g="maxWait"in r&&ro(+r.maxWait||0,t),v="trailing"in r?r.trailing:v);return o.cancel=function(){s&&Du(s),a&&Du(a),a=s=p=b},o}function De(){var n=arguments,t=n.length-1; -if(0>t)return function(){};if(!qt(n,Ze))throw new Ru($);return function(){for(var r=t,e=n[r].apply(this,arguments);r--;)e=n[r].call(this,e);return e}}function Me(n,t){function r(){var e=r.cache,u=t?t.apply(this,arguments):arguments[0];if(e.has(u))return e.get(u);var o=n.apply(this,arguments);return e.set(u,o),o}if(!Ze(n)||t&&!Ze(t))throw new Ru($);return r.cache=new Me.Cache,r}function qe(n){var t=Er(arguments,1),r=v(t,qe.placeholder);return Vr(n,R,null,t,r)}function Pe(n){var t=Er(arguments,1),r=v(t,Pe.placeholder); -return Vr(n,I,null,t,r)}function Ke(n){return ue(h(n)?n.length:b)&&Uu.call(n)==z||false}function Ve(n){return n&&1===n.nodeType&&h(n)&&-1t||!n||!no(t))return r;do t%2&&(r+=n),t=Mu(t/2),n+=n;while(t);return r}function cu(n,t,r){var u=n;return(n=e(n))?(r?ee(u,t,r):null==t)?n.slice(d(n),y(n)+1):(t+="",n.slice(o(n,t),i(n,t)+1)):n}function lu(n,t,r){return r&&ee(n,t,r)&&(t=null),n=e(n),n.match(t||Rt)||[] -}function su(n){try{return n()}catch(t){return Ye(t)?t:bu(t)}}function pu(n,t,r){return r&&ee(n,t,r)&&(t=null),h(n)?vu(n):tr(n,t)}function hu(n){return function(){return n}}function gu(n){return n}function vu(n){return wr(rr(n,true))}function du(n,t,r){if(null==r){var e=Ge(t),u=e&&No(t);((u=u&&u.length&&dr(t,u))?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=dr(t,No(t)));var o=true,e=-1,i=Ze(n),a=u.length;false===r?o=false:Ge(r)&&"chain"in r&&(o=r.chain);for(;++e>>1,ho=Xu?Xu.BYTES_PER_ELEMENT:0,go=xu.pow(2,53)-1,vo=Ju&&new Ju,yo=Wt.support={};!function(n){yo.funcDecomp=!Je(g.WinRTError)&&kt.test(m),yo.funcNames=typeof wu.name=="string";try{yo.dom=11===Cu.createDocumentFragment().nodeType -}catch(t){yo.dom=false}try{yo.nonEnumArgs=!Ku.call(arguments,1)}catch(r){yo.nonEnumArgs=true}}(0,0),Wt.templateSettings={escape:ht,evaluate:gt,interpolate:vt,variable:"",imports:{_:Wt}};var _o=function(){function n(){}return function(t){if(Ge(t)){n.prototype=t;var r=new n;n.prototype=null}return r||g.Object()}}(),mo=vo?function(n,t){return vo.set(n,t),n}:gu;Bu||(Nr=$u&&Gu?function(n){var t=n.byteLength,r=Xu?Mu(t/ho):0,e=r*ho,u=new $u(t);if(r){var o=new Xu(u,0,r);o.set(new Xu(n,0,r))}return t!=e&&(o=new Gu(u,e),o.set(new Gu(n,e))),u -}:hu(null));var bo=Qu&&Vu?function(n){return new Lt(n)}:hu(null),wo=vo?function(n){return vo.get(n)}:yu,xo=function(){var n=0,t=0;return function(r,e){var u=Oo(),o=N-(u-t);if(t=u,0=W)return r}else n=0;return mo(r,e)}}(),Ao=Lr(function(n,t,r){Wu.call(n,r)?++n[r]:n[r]=1}),jo=Lr(function(n,t,r){Wu.call(n,r)?n[r].push(t):n[r]=[t]}),ko=Lr(function(n,t,r){n[r]=t}),Eo=Mr(Vt),Ro=Mr(function(n){for(var t=-1,r=n.length,e=co;++t--n?t.apply(this,arguments):void 0}},Wt.ary=function(n,t,r){return r&&ee(n,t,r)&&(t=null),t=n&&null==t?n.length:ro(+t||0,0),Vr(n,C,null,null,null,null,t)},Wt.assign=Wo,Wt.at=function(n){return ue(n?n.length:0)&&(n=le(n)),Qt(n,lr(arguments,false,false,1))},Wt.before=Ue,Wt.bind=Fe,Wt.bindAll=function(n){for(var t=n,r=1(s?Bt(s,a):o(l,a))){for(r=e;--r;){var p=u[r];if(0>(p?Bt(p,a):o(n[r],a)))continue n}s&&s.push(a),l.push(a) -}return l},Wt.invert=function(n,t,r){r&&ee(n,t,r)&&(t=null),r=-1;for(var e=No(n),u=e.length,o={};++rt?0:t)):[] -},Wt.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?ee(n,t,r):null==t)&&(t=1),t=e-(+t||0),Er(n,0>t?0:t)):[]},Wt.takeRightWhile=function(n,t,r){var e=n?n.length:0;if(!e)return[];for(t=Xr(t,r,3);e--&&t(n[e],e,n););return Er(n,e+1)},Wt.takeWhile=function(n,t,r){var e=n?n.length:0;if(!e)return[];var u=-1;for(t=Xr(t,r,3);++un||!no(n))return[];var e=-1,u=_u(eo(n,lo));for(t=Wr(t,r,1);++er?0:+r||0,u))-t.length,0<=r&&n.indexOf(t,r)==r},Wt.escape=function(n){return(n=e(n))&&pt.test(n)?n.replace(lt,l):n},Wt.escapeRegExp=iu,Wt.every=je,Wt.find=Ee,Wt.findIndex=ge,Wt.findKey=function(n,t,r){return t=Xr(t,r,3),cr(n,t,gr,true) -},Wt.findLast=function(n,t,r){return t=Xr(t,r,3),cr(n,t,ir)},Wt.findLastIndex=function(n,t,r){var e=n?n.length:0;for(t=Xr(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},Wt.findLastKey=function(n,t,r){return t=Xr(t,r,3),cr(n,t,vr,true)},Wt.findWhere=function(n,t){return Ee(n,wr(t))},Wt.first=ve,Wt.has=function(n,t){return n?Wu.call(n,t):false},Wt.identity=gu,Wt.includes=Ae,Wt.indexOf=de,Wt.isArguments=Ke,Wt.isArray=Co,Wt.isBoolean=function(n){return true===n||false===n||h(n)&&Uu.call(n)==M||false},Wt.isDate=function(n){return h(n)&&Uu.call(n)==q||false -},Wt.isElement=Ve,Wt.isEmpty=function(n){if(null==n)return true;var t=n.length;return ue(t)&&(Co(n)||Qe(n)||Ke(n)||h(n)&&Ze(n.splice))?!t:!No(n).length},Wt.isEqual=function(n,t,r,e){return r=typeof r=="function"&&Wr(r,e,3),!r&&oe(n)&&oe(t)?n===t:(e=r?r(n,t):b,typeof e=="undefined"?_r(n,t,r):!!e)},Wt.isError=Ye,Wt.isFinite=To,Wt.isFunction=Ze,Wt.isMatch=function(n,t,r,e){var u=No(t),o=u.length;if(r=typeof r=="function"&&Wr(r,e,3),!r&&1==o){var i=u[0];if(e=t[i],oe(e))return null!=n&&e===n[i]&&Wu.call(n,i) -}for(var i=_u(o),a=_u(o);o--;)e=i[o]=t[u[o]],a[o]=oe(e);return mr(n,u,i,a,r)},Wt.isNaN=function(n){return Xe(n)&&n!=+n},Wt.isNative=Je,Wt.isNull=function(n){return null===n},Wt.isNumber=Xe,Wt.isObject=Ge,Wt.isPlainObject=So,Wt.isRegExp=He,Wt.isString=Qe,Wt.isTypedArray=nu,Wt.isUndefined=function(n){return typeof n=="undefined"},Wt.kebabCase=Lo,Wt.last=function(n){var t=n?n.length:0;return t?n[t-1]:b},Wt.lastIndexOf=function(n,t,r){var e=n?n.length:0;if(!e)return-1;var u=e;if(typeof r=="number")u=(0>r?ro(e+r,0):eo(r||0,e-1))+1; -else if(r)return u=Tr(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},Wt.max=Eo,Wt.min=Ro,Wt.noConflict=function(){return g._=Fu,this},Wt.noop=yu,Wt.now=Oo,Wt.pad=function(n,t,r){n=e(n),t=+t;var u=n.length;return ur?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Wt.template=function(n,t,r){var u=Wt.templateSettings;r&&ee(n,t,r)&&(t=r=null),n=e(n),t=Ht(Ht({},r||t),u,Xt),r=Ht(Ht({},t.imports),u.imports,Xt);var o,i,a=No(r),f=Or(r,a),c=0;r=t.interpolate||xt;var l="__p+='";r=ku((t.escape||xt).source+"|"+r.source+"|"+(r===vt?dt:xt).source+"|"+(t.evaluate||xt).source+"|$","g"); -var p="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,u,a,f){return e||(e=u),l+=n.slice(c,f).replace(Et,s),r&&(o=true,l+="'+__e("+r+")+'"),a&&(i=true,l+="';"+a+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),c=f+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(i?l.replace(it,""):l).replace(at,"$1").replace(ft,"$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=su(function(){return wu(a,p+"return "+l).apply(b,f) -}),t.source=l,Ye(t))throw t;return t},Wt.trim=cu,Wt.trimLeft=function(n,t,r){var u=n;return(n=e(n))?n.slice((r?ee(u,t,r):null==t)?d(n):o(n,t+"")):n},Wt.trimRight=function(n,t,r){var u=n;return(n=e(n))?(r?ee(u,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+"")+1):n},Wt.trunc=function(n,t,r){r&&ee(n,t,r)&&(t=null);var u=T;if(r=S,null!=t)if(Ge(t)){var o="separator"in t?t.separator:o,u="length"in t?+t.length||0:u;r="omission"in t?e(t.omission):r}else u=+t||0;if(n=e(n),u>=n.length)return n;if(u-=r.length,1>u)return r; -if(t=n.slice(0,u),null==o)return t+r;if(He(o)){if(n.slice(u).search(o)){var i,a=n.slice(0,u);for(o.global||(o=ku(o.source,(yt.exec(o)||"")+"g")),o.lastIndex=0;n=o.exec(a);)i=n.index;t=t.slice(0,null==i?u:i)}}else n.indexOf(o,u)!=u&&(o=t.lastIndexOf(o),-1u.dir,i.push({iteratee:Xr(n,e,3),type:t}),u -}}),Mt(["drop","take"],function(n,t){var r=n+"Count",e=n+"While";Ut.prototype[n]=function(e){e=null==e?1:ro(+e||0,0);var u=this.clone();if(u.filtered){var o=u[r];u[r]=t?eo(o,e):o+e}else(u.views||(u.views=[])).push({size:e,type:n+(0>u.dir?"Right":"")});return u},Ut.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()},Ut.prototype[n+"RightWhile"]=function(n,t){return this.reverse()[e](n,t).reverse()}}),Mt(["first","last"],function(n,t){var r="take"+(t?"Right":"");Ut.prototype[n]=function(){return this[r](1).value()[0] -}}),Mt(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right");Ut.prototype[n]=function(){return this[r](1)}}),Mt(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?wr:Ar;Ut.prototype[n]=function(n){return this[r](e(t?n:n+""))}}),Ut.prototype.dropWhile=function(n,t){var r,e,u=0>this.dir;return n=Xr(n,t,3),this.filter(function(t,o,i){return r=r&&(u?oe),e=o,r||(r=!n(t,o,i))})},Ut.prototype.reject=function(n,t){return n=Xr(n,t,3),this.filter(function(t,r,e){return!n(t,r,e)})},Ut.prototype.slice=function(n,t){n=null==n?0:+n||0; -var r=0>n?this.takeRight(-n):this.drop(n);return typeof t!="undefined"&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r},gr(Ut.prototype,function(n,t){var r=Wt[t],e=/^(?:first|last)$/.test(t);Wt.prototype[t]=function(){function t(n){return n=[n],Pu.apply(n,o),r.apply(Wt,n)}var u=this.__wrapped__,o=arguments,i=this.__chain__,a=!!this.__actions__.length,f=u instanceof Ut,c=f&&!a;return e&&!i?c?n.call(u):r.call(Wt,this.value()):f||Co(u)?(u=n.apply(c?u:new Ut(this),o),e||!a&&!u.actions||(u.actions||(u.actions=[])).push({func:xe,args:[t],thisArg:Wt}),new Nt(u,i)):this.thru(t) -}}),Mt("concat join pop push shift sort splice unshift".split(" "),function(n){var t=Iu[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|shift)$/.test(n);Wt.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),Ut.prototype.clone=function(){var n=this.actions,t=this.iteratees,r=this.views,e=new Ut(this.wrapped);return e.actions=n?zt(n):null,e.dir=this.dir,e.dropCount=this.dropCount,e.filtered=this.filtered,e.iteratees=t?zt(t):null,e.takeCount=this.takeCount,e.views=r?zt(r):null,e -},Ut.prototype.reverse=function(){if(this.filtered){var n=new Ut(this);n.dir=-1,n.filtered=true}else n=this.clone(),n.dir*=-1;return n},Ut.prototype.value=function(){var n=this.wrapped.value();if(!Co(n))return Cr(n,this.actions);var t,r=this.dir,e=0>r;t=n.length;for(var u=this.views,o=0,i=-1,a=u?u.length:0;++i"'`]/g,st=RegExp(ct.source),pt=RegExp(lt.source),ht=/<%-([\s\S]+?)%>/g,gt=/<%([\s\S]+?)%>/g,vt=/<%=([\s\S]+?)%>/g,dt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,yt=/\w*$/,_t=/^\s*function[ \n\r\t]+\w/,mt=/^0[xX]/,bt=/^\[object .+?Constructor\]$/,wt=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,xt=/($^)/,At=/[.*+?^${}()|[\]\/\\]/g,jt=RegExp(At.source),kt=/\bthis\b/,Et=/['\n\r\u2028\u2029\\]/g,Rt=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]{2,}(?=[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"),It=" \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",Ot="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),Ct={}; +}function i(n,t){for(var r=n.length;r--&&-1=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n) +}function g(n,t){for(var r=-1,e=n.length,u=-1,o=[];++re&&(e=u)}return e}function Yt(n,t,r,e){var u=-1,o=n.length;for(e&&o&&(r=n[++u]);++ui(r,a)&&u.push(a);return u}function or(n,t){var r=n?n.length:0;if(!ue(r))return _r(n,t);for(var e=-1,u=se(n);++et&&(t=-t>u?0:u+t),r=typeof r=="undefined"||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=mu(u);++eu(a,s)&&((r||f)&&a.push(s),c.push(l))}return c}function Or(n,t){for(var r=-1,e=t.length,u=mu(e);++r>>1,i=n[o]; +(r?i<=t:it||null==r)return r;if(3=o&&f<=i&&(e=O&&t>u||e>u&&t>=O)||o)&&(t&x&&(r[2]=p[2],f|=e&x?0:j),(e=p[3])&&(u=r[3],r[3]=u?Ur(u,e,p[4]):zt(e),r[4]=u?g(r[3],B):zt(p[4])),(e=p[5])&&(u=r[5],r[5]=u?Fr(u,e,p[6]):zt(e),r[6]=u?g(r[5],B):zt(p[6])),(e=p[7])&&(r[7]=zt(e)),t&C&&(r[8]=null==r[8]?p[8]:uo(r[8],p[8])),null==r[9]&&(r[9]=p[9]),r[0]=p[0],r[1]=f),t=r[1],f=r[9]}return r[9]=null==f?a?0:n.length:eo(f-c,0)||0,(p?wo:Ao)(t==x?Br(r[0],r[2]):t!=R&&t!=(x|R)||r[4].length?qr.apply(w,r):Kr.apply(w,r),r)}function Yr(n,t,r,e,u,o,i){var f=-1,a=n.length,c=t.length,l=true; +if(a!=c&&(!u||c<=a))return false;for(;l&&++fu)||i===e&&i===o)&&(u=i,o=n)}),o}function Xr(n,t,r){var e=Wt.callback||hu,e=e===hu?tr:e; +return r?e(n,t,r):e}function Hr(n,r,e){var u=Wt.indexOf||ye,u=u===ye?t:u;return n?u(n,r,e):u}function Qr(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&Nu.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function ne(n){return n=n.constructor,typeof n=="function"&&n instanceof n||(n=ku),new n}function te(n,t,r){var e=n.constructor;switch(t){case J:return Nr(n);case M:case q:return new e(+n);case X:case H:case Q:case nt:case tt:case rt:case et:case ut:case ot:return t=n.buffer,new e(r?Nr(t):t,n.byteOffset,n.length); +case V:case G:return new e(n);case Z:var u=new e(n.source,yt.exec(n));u.lastIndex=n.lastIndex}return u}function re(n,t){return n=+n,t=null==t?go:t,-1t?0:t)):[]}function _e(n,t,r){var e=n?n.length:0;return e?((r?ee(n,t,r):null==t)&&(t=1),t=e-(+t||0),Er(n,0,0>t?0:t)):[]}function ge(n,t,r){var e=-1,u=n?n.length:0;for(t=Xr(t,r,3);++ee?eo(u+e,0):e||0;else if(e)return e=Tr(n,r),n=n[e],(r===r?r===n:n!==n)?e:-1;return t(n,r,e)}function de(n){return he(n,1)}function me(n,r,e,u){if(!n||!n.length)return[];typeof r!="boolean"&&null!=r&&(u=e,e=ee(n,r,u)?null:r,r=false);var o=Xr();if((o!==tr||null!=e)&&(e=o(e,u,3)),r&&Hr()==t){r=e;var i;e=-1,u=n.length;for(var o=-1,f=[];++e>>0,e=mu(r);++tr?eo(e+r,0):r||0:0,typeof n=="string"||!To(n)&&nu(n)?rarguments.length,or) +}function Se(n,t,r,e){return(To(n)?Zt:kr)(n,Xr(t,e,4),r,3>arguments.length,ir)}function We(n,t,r){return(r?ee(n,t,r):null==t)?(n=le(n),t=n.length,0t?0:+t||0,n.length),n)}function Ne(n){n=le(n);for(var t=-1,r=n.length,e=mu(r);++t=r||r>t?(f&&Mu(f),r=p,f=s=p=w,r&&(h=Co(),a=n.apply(l,i),s||f||(i=l=null))):s=Zu(e,r)}function u(){s&&Mu(s),f=s=p=w,(g||_!==t)&&(h=Co(),a=n.apply(l,i),s||f||(i=l=null))}function o(){if(i=arguments,c=Co(),l=this,p=g&&(s||!v),false===_)var r=v&&!s;else{f||v||(h=c);var o=_-(c-h),y=0>=o||o>_;y?(f&&(f=Mu(f)),h=c,a=n.apply(l,i)):f||(f=Zu(u,o))}return y&&s?s=Mu(s):s||t===_||(s=Zu(e,t)),r&&(y=true,a=n.apply(l,i)),!y||s||f||(i=l=null),a}var i,f,a,c,l,s,p,h=0,_=false,g=true; +if(typeof n!="function")throw new Iu($);if(t=0>t?0:t,true===r)var v=true,g=false;else Je(r)&&(v=r.leading,_="maxWait"in r&&eo(+r.maxWait||0,t),g="trailing"in r?r.trailing:g);return o.cancel=function(){s&&Mu(s),f&&Mu(f),f=s=p=w},o}function Me(){var n=arguments,t=n.length-1;if(0>t)return function(n){return n};if(!qt(n,Ge))throw new Iu($);return function(){for(var r=t,e=n[r].apply(this,arguments);r--;)e=n[r].call(this,e);return e}}function qe(n,t){function r(){var e=r.cache,u=t?t.apply(this,arguments):arguments[0]; +if(e.has(u))return e.get(u);var o=n.apply(this,arguments);return e.set(u,o),o}if(typeof n!="function"||t&&typeof t!="function")throw new Iu($);return r.cache=new qe.Cache,r}function Pe(n){var t=Er(arguments,1),r=g(t,Pe.placeholder);return Vr(n,R,null,t,r)}function Ke(n){var t=Er(arguments,1),r=g(t,Ke.placeholder);return Vr(n,I,null,t,r)}function Ve(n){return ue(h(n)?n.length:w)&&Fu.call(n)==z||false}function Ye(n){return n&&1===n.nodeType&&h(n)&&-1t||!n||!to(t))return r;do t%2&&(r+=n),t=qu(t/2),n+=n;while(t);return r}function lu(n,t,r){var u=n;return(n=e(n))?(r?ee(u,t,r):null==t)?n.slice(v(n),y(n)+1):(t+="",n.slice(o(n,t),i(n,t)+1)):n}function su(n,t,r){return r&&ee(n,t,r)&&(t=null),n=e(n),n.match(t||Rt)||[]}function pu(n){try{return n.apply(w,Er(arguments,1))}catch(t){return Ze(t)?t:bu(t)}}function hu(n,t,r){return r&&ee(n,t,r)&&(t=null),h(n)?vu(n):tr(n,t)}function _u(n){return function(){return n}}function gu(n){return n +}function vu(n){return br(rr(n,true))}function yu(n,t,r){if(null==r){var e=Je(t),u=e&&Uo(t);((u=u&&u.length&&vr(t,u))?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=vr(t,Uo(t)));var o=true,e=-1,i=Ge(n),f=u.length;false===r?o=false:Je(r)&&"chain"in r&&(o=r.chain);for(;++e>>1,_o=Hu?Hu.BYTES_PER_ELEMENT:0,go=Au.pow(2,53)-1,vo=Xu&&new Xu,yo=Wt.support={};!function(n){yo.funcDecomp=!Xe(_.WinRTError)&&kt.test(m),yo.funcNames=typeof xu.name=="string";try{yo.dom=11===Tu.createDocumentFragment().nodeType +}catch(t){yo.dom=false}try{yo.nonEnumArgs=!Vu.call(arguments,1)}catch(r){yo.nonEnumArgs=true}}(0,0),Wt.templateSettings={escape:ht,evaluate:_t,interpolate:gt,variable:"",imports:{_:Wt}};var mo=function(){function n(){}return function(t){if(Je(t)){n.prototype=t;var r=new n;n.prototype=null}return r||_.Object()}}(),wo=vo?function(n,t){return vo.set(n,t),n}:gu;zu||(Nr=Bu&&Ju?function(n){var t=n.byteLength,r=Hu?qu(t/_o):0,e=r*_o,u=new Bu(t);if(r){var o=new Hu(u,0,r);o.set(new Hu(n,0,r))}return t!=e&&(o=new Ju(u,e),o.set(new Ju(n,e))),u +}:_u(null));var bo=no&&Yu?function(n){return new Lt(n)}:_u(null),xo=vo?function(n){return vo.get(n)}:du,Ao=function(){var n=0,t=0;return function(r,e){var u=Co(),o=N-(u-t);if(t=u,0=W)return r}else n=0;return wo(r,e)}}(),jo=Lr(function(n,t,r){Nu.call(n,r)?++n[r]:n[r]=1}),ko=Lr(function(n,t,r){Nu.call(n,r)?n[r].push(t):n[r]=[t]}),Eo=Lr(function(n,t,r){n[r]=t}),Ro=Mr(Vt),Io=Mr(function(n){for(var t=-1,r=n.length,e=lo;++t--n?t.apply(this,arguments):void 0}},Wt.ary=function(n,t,r){return r&&ee(n,t,r)&&(t=null),t=n&&null==t?n.length:eo(+t||0,0),Vr(n,C,null,null,null,null,t)},Wt.assign=No,Wt.at=function(n){return ue(n?n.length:0)&&(n=le(n)),Qt(n,lr(arguments,false,false,1))},Wt.before=Fe,Wt.bind=Le,Wt.bindAll=function(n){for(var t=n,r=1r&&(r=-r>u?0:u+r),e=typeof e=="undefined"||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;r(s?Bt(s,f):o(l,f))){for(r=e;--r;){var p=u[r];if(0>(p?Bt(p,f):o(n[r],f)))continue n}s&&s.push(f),l.push(f)}return l},Wt.invert=function(n,t,r){r&&ee(n,t,r)&&(t=null),r=-1; +for(var e=Uo(n),u=e.length,o={};++rt?0:t)):[]},Wt.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?ee(n,t,r):null==t)&&(t=1),t=e-(+t||0),Er(n,0>t?0:t)):[]},Wt.takeRightWhile=function(n,t,r){var e=n?n.length:0;if(!e)return[];for(t=Xr(t,r,3);e--&&t(n[e],e,n););return Er(n,e+1)},Wt.takeWhile=function(n,t,r){var e=n?n.length:0;if(!e)return[];var u=-1;for(t=Xr(t,r,3);++un||!to(n))return[];var e=-1,u=mu(uo(n,so));for(t=Wr(t,r,1);++er?0:+r||0,u))-t.length,0<=r&&n.indexOf(t,r)==r},Wt.escape=function(n){return(n=e(n))&&pt.test(n)?n.replace(lt,l):n},Wt.escapeRegExp=fu,Wt.every=ke,Wt.find=Re,Wt.findIndex=ge,Wt.findKey=function(n,t,r){return t=Xr(t,r,3),cr(n,t,_r,true)},Wt.findLast=function(n,t,r){return t=Xr(t,r,3),cr(n,t,ir)},Wt.findLastIndex=function(n,t,r){var e=n?n.length:0; +for(t=Xr(t,r,3);e--;)if(t(n[e],e,n))return e;return-1},Wt.findLastKey=function(n,t,r){return t=Xr(t,r,3),cr(n,t,gr,true)},Wt.findWhere=function(n,t){return Re(n,br(t))},Wt.first=ve,Wt.has=function(n,t){return n?Nu.call(n,t):false},Wt.identity=gu,Wt.includes=je,Wt.indexOf=ye,Wt.isArguments=Ve,Wt.isArray=To,Wt.isBoolean=function(n){return true===n||false===n||h(n)&&Fu.call(n)==M||false},Wt.isDate=function(n){return h(n)&&Fu.call(n)==q||false},Wt.isElement=Ye,Wt.isEmpty=function(n){if(null==n)return true;var t=n.length; +return ue(t)&&(To(n)||nu(n)||Ve(n)||h(n)&&Ge(n.splice))?!t:!Uo(n).length},Wt.isEqual=function(n,t,r,e){return r=typeof r=="function"&&Wr(r,e,3),!r&&oe(n)&&oe(t)?n===t:(e=r?r(n,t):w,typeof e=="undefined"?dr(n,t,r):!!e)},Wt.isError=Ze,Wt.isFinite=So,Wt.isFunction=Ge,Wt.isMatch=function(n,t,r,e){var u=Uo(t),o=u.length;if(r=typeof r=="function"&&Wr(r,e,3),!r&&1==o){var i=u[0];if(e=t[i],oe(e))return null!=n&&e===n[i]&&Nu.call(n,i)}for(var i=mu(o),f=mu(o);o--;)e=i[o]=t[u[o]],f[o]=oe(e);return mr(n,u,i,f,r) +},Wt.isNaN=function(n){return He(n)&&n!=+n},Wt.isNative=Xe,Wt.isNull=function(n){return null===n},Wt.isNumber=He,Wt.isObject=Je,Wt.isPlainObject=Wo,Wt.isRegExp=Qe,Wt.isString=nu,Wt.isTypedArray=tu,Wt.isUndefined=function(n){return typeof n=="undefined"},Wt.kebabCase=$o,Wt.last=function(n){var t=n?n.length:0;return t?n[t-1]:w},Wt.lastIndexOf=function(n,t,r){var e=n?n.length:0;if(!e)return-1;var u=e;if(typeof r=="number")u=(0>r?eo(e+r,0):uo(r||0,e-1))+1;else if(r)return u=Tr(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},Wt.max=Ro,Wt.min=Io,Wt.noConflict=function(){return _._=Lu,this},Wt.noop=du,Wt.now=Co,Wt.pad=function(n,t,r){n=e(n),t=+t;var u=n.length;return ur?0:+r||0,n.length),n.lastIndexOf(t,r)==r +},Wt.template=function(n,t,r){var u=Wt.templateSettings;r&&ee(n,t,r)&&(t=r=null),n=e(n),t=Ht(Ht({},r||t),u,Xt),r=Ht(Ht({},t.imports),u.imports,Xt);var o,i,f=Uo(r),a=Or(r,f),c=0;r=t.interpolate||xt;var l="__p+='";r=Eu((t.escape||xt).source+"|"+r.source+"|"+(r===gt?vt:xt).source+"|"+(t.evaluate||xt).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(Et,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(it,""):l).replace(ft,"$1").replace(at,"$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=pu(function(){return xu(f,p+"return "+l).apply(w,a)}),t.source=l,Ze(t))throw t;return t},Wt.trim=lu,Wt.trimLeft=function(n,t,r){var u=n;return(n=e(n))?n.slice((r?ee(u,t,r):null==t)?v(n):o(n,t+"")):n +},Wt.trimRight=function(n,t,r){var u=n;return(n=e(n))?(r?ee(u,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+"")+1):n},Wt.trunc=function(n,t,r){r&&ee(n,t,r)&&(t=null);var u=T;if(r=S,null!=t)if(Je(t)){var o="separator"in t?t.separator:o,u="length"in t?+t.length||0:u;r="omission"in t?e(t.omission):r}else u=+t||0;if(n=e(n),u>=n.length)return n;if(u-=r.length,1>u)return r;if(t=n.slice(0,u),null==o)return t+r;if(Qe(o)){if(n.slice(u).search(o)){var i,f=n.slice(0,u);for(o.global||(o=Eu(o.source,(yt.exec(o)||"")+"g")),o.lastIndex=0;n=o.exec(f);)i=n.index; +t=t.slice(0,null==i?u:i)}}else n.indexOf(o,u)!=u&&(o=t.lastIndexOf(o),-1o.__dir__,f.push({iteratee:Xr(n,u,3),type:t}),o}}),Mt(["drop","take"],function(n,t){var r="__"+n+"Count__",e=n+"While";Ut.prototype[n]=function(e){e=null==e?1:eo(+e||0,0); +var u=this.clone();if(u.__filtered__){var o=u[r];u[r]=t?uo(o,e):o+e}else(u.__views__||(u.__views__=[])).push({size:e,type:n+(0>u.__dir__?"Right":"")});return u},Ut.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()},Ut.prototype[n+"RightWhile"]=function(n,t){return this.reverse()[e](n,t).reverse()}}),Mt(["first","last"],function(n,t){var r="take"+(t?"Right":"");Ut.prototype[n]=function(){return this[r](1).value()[0]}}),Mt(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right"); +Ut.prototype[n]=function(){return this[r](1)}}),Mt(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?br:Ar;Ut.prototype[n]=function(n){return this[r](e(t?n:n+""))}}),Ut.prototype.dropWhile=function(n,t){var r;return n=Xr(n,t,3),this.filter(function(t,e,u){return r||(r=!n(t,e,u))})},Ut.prototype.reject=function(n,t){return n=Xr(n,t,3),this.filter(function(t,r,e){return!n(t,r,e)})},Ut.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=0>n?this.takeRight(-n):this.drop(n);return typeof t!="undefined"&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r +},_r(Ut.prototype,function(n,t){var r=Wt[t],e=/^(?:first|last)$/.test(t);Wt.prototype[t]=function(){function t(n){return n=[n],Ku.apply(n,o),r.apply(Wt,n)}var u=this.__wrapped__,o=arguments,i=this.__chain__,f=!!this.__actions__.length,a=u instanceof Ut,c=a&&!f;return e&&!i?c?n.call(u):r.call(Wt,this.value()):a||To(u)?(u=n.apply(c?u:new Ut(this),o),e||!f&&!u.__actions__||(u.__actions__||(u.__actions__=[])).push({func:Ae,args:[t],thisArg:Wt}),new Nt(u,i)):this.thru(t)}}),Mt("concat join pop push shift sort splice unshift".split(" "),function(n){var t=Ou[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|shift)$/.test(n); +Wt.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),Ut.prototype.clone=function(){var n=this.__actions__,t=this.__iteratees__,r=this.__views__,e=new Ut(this.__wrapped__);return e.__actions__=n?zt(n):null,e.__dir__=this.__dir__,e.__dropCount__=this.__dropCount__,e.__filtered__=this.__filtered__,e.__iteratees__=t?zt(t):null,e.__takeCount__=this.__takeCount__,e.__views__=r?zt(r):null,e},Ut.prototype.reverse=function(){if(this.__filtered__){var n=new Ut(this); +n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},Ut.prototype.value=function(){var n=this.__wrapped__.value();if(!To(n))return Cr(n,this.__actions__);var t,r=this.__dir__,e=0>r;t=n.length;for(var u=this.__views__,o=0,i=-1,f=u?u.length:0;++i"'`]/g,st=RegExp(ct.source),pt=RegExp(lt.source),ht=/<%-([\s\S]+?)%>/g,_t=/<%([\s\S]+?)%>/g,gt=/<%=([\s\S]+?)%>/g,vt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,yt=/\w*$/,dt=/^\s*function[ \n\r\t]+\w/,mt=/^0[xX]/,wt=/^\[object .+?Constructor\]$/,bt=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,xt=/($^)/,At=/[.*+?^${}()|[\]\/\\]/g,jt=RegExp(At.source),kt=/\bthis\b/,Et=/['\n\r\u2028\u2029\\]/g,Rt=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]{2,}(?=[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"),It=" \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",Ot="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout document isFinite parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap window WinRTError".split(" "),Ct={}; Ct[X]=Ct[H]=Ct[Q]=Ct[nt]=Ct[tt]=Ct[rt]=Ct[et]=Ct[ut]=Ct[ot]=true,Ct[z]=Ct[D]=Ct[J]=Ct[M]=Ct[q]=Ct[P]=Ct[K]=Ct["[object Map]"]=Ct[V]=Ct[Y]=Ct[Z]=Ct["[object Set]"]=Ct[G]=Ct["[object WeakMap]"]=false;var Tt={};Tt[z]=Tt[D]=Tt[J]=Tt[M]=Tt[q]=Tt[X]=Tt[H]=Tt[Q]=Tt[nt]=Tt[tt]=Tt[V]=Tt[Y]=Tt[Z]=Tt[G]=Tt[rt]=Tt[et]=Tt[ut]=Tt[ot]=true,Tt[P]=Tt[K]=Tt["[object Map]"]=Tt["[object Set]"]=Tt["[object WeakMap]"]=false;var St={leading:false,maxWait:0,trailing:false},Wt={"\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"},Nt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Ut={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ft={"function":true,object:true},Lt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$t=Ft[typeof window]&&window!==(this&&this.window)?window:this,Bt=Ft[typeof exports]&&exports&&!exports.nodeType&&exports,Ft=Ft[typeof module]&&module&&!module.nodeType&&module,zt=Bt&&Ft&&typeof global=="object"&&global; !zt||zt.global!==zt&&zt.window!==zt&&zt.self!==zt||($t=zt);var zt=Ft&&Ft.exports===Bt&&Bt,Dt=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($t._=Dt, define(function(){return Dt})):Bt&&Ft?zt?(Ft.exports=Dt)._=Dt:Bt._=Dt:$t._=Dt}).call(this); \ No newline at end of file From b1a33edf0f48be46a14a8f9f07825a46933f9440 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 01:24:40 -0800 Subject: [PATCH 31/61] Cleanup io.js testing in travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3c09dc1aa1..f294006555 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ env: matrix: include: - node_js: "io.js" - env: BUILD="compat" + env: - node_js: "io.js" env: BUILD="modern" - node_js: "0.8" From fc369c3448249b13cfd499cf2bc17e4434ea9516 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 08:39:09 -0800 Subject: [PATCH 32/61] Add `_.fill` and `_.slice` tests for default `start` and `end` params. --- test/test.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index ec4245a67b..d70b42850f 100644 --- a/test/test.js +++ b/test/test.js @@ -4059,6 +4059,19 @@ QUnit.module('lodash.fill'); (function() { + test('should use a default `start` of `0` and a default `end` of `array.length`', 1, function() { + var array = [1, 2, 3]; + deepEqual(_.fill(array, 'a'), ['a', 'a', 'a']); + }); + + test('should use `undefined` for `value` if not provided', 2, function() { + var array = [1, 2, 3], + actual = _.fill(array); + + deepEqual(actual, [undefined, undefined, undefined]); + ok(_.every(actual, function(value, index) { return index in actual; })); + }); + test('should work with a positive `start`', 1, function() { var array = [1, 2, 3]; deepEqual(_.fill(array, 'a', 1), [1, 'a', 'a']); @@ -11930,6 +11943,12 @@ (function() { var array = [1, 2, 3]; + test('should use a default `start` of `0` and a default `end` of `array.length`', 2, function() { + var actual = _.slice(array); + deepEqual(actual, array); + notStrictEqual(actual, array); + }); + test('should work with a positive `start`', 1, function() { deepEqual(_.slice(array, 1), [2, 3]); }); @@ -12013,7 +12032,7 @@ actual = _.map(array, _.slice); deepEqual(actual, array); - notStrictEqual(actual, array) + notStrictEqual(actual, array); }); test('should work in a lazy chain sequence', 12, function() { From 16a9c7d49211025d7f0e5cb0301a015b5abc2611 Mon Sep 17 00:00:00 2001 From: jdalton Date: Mon, 9 Feb 2015 08:58:08 -0800 Subject: [PATCH 33/61] Improve label of unstable test. --- test/test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index d70b42850f..f66c17ed92 100644 --- a/test/test.js +++ b/test/test.js @@ -1920,8 +1920,11 @@ }); test('`_.' + methodName + '` should create an object from the same realm as `value`', 1, function() { + var props = []; + var objects = _.transform(_, function(result, value, key) { if (_.startsWith(key, '_') && _.isObject(value) && !_.isArguments(value) && !_.isElement(value) && !_.isFunction(value)) { + props.push(_.capitalize(_.camelCase(key))); result.push(value); } }, []); @@ -1935,7 +1938,7 @@ return result !== object && (result instanceof Ctor || !(new Ctor instanceof Ctor)); }); - deepEqual(actual, expected); + deepEqual(actual, expected, props.join(', ')); }); test('`_.' + methodName + '` should return a unwrapped value when chaining', 2, function() { From ce44f7e4b0c062ae6dbca9083e38bbaadcf346e1 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 10 Feb 2015 00:08:09 -0800 Subject: [PATCH 34/61] Add lazy `compact` and `toArray`. --- lodash.src.js | 8 +++++ test/test.js | 89 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 62 insertions(+), 35 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 39412b1a16..c3f7abe289 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -11087,6 +11087,10 @@ }; }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.dropWhile = function(iteratee, thisArg) { var done; iteratee = getCallback(iteratee, thisArg, 3); @@ -11113,6 +11117,10 @@ return result; }; + LazyWrapper.prototype.toArray = function() { + return this.drop(0); + }; + // Add `LazyWrapper` methods to `lodash.prototype`. baseForOwn(LazyWrapper.prototype, function(func, methodName) { var lodashFunc = lodash[methodName], diff --git a/test/test.js b/test/test.js index f66c17ed92..8d79e8f8cf 100644 --- a/test/test.js +++ b/test/test.js @@ -49,14 +49,18 @@ freeze = Object.freeze, hasOwnProperty = objectProto.hasOwnProperty, JSON = root.JSON, - noop = function() {}, objToString = objectProto.toString, + noop = function() {}, params = root.arguments, push = arrayProto.push, slice = arrayProto.slice, system = root.system, Uint8Array = root.Uint8Array; + /** Math helpers. */ + var add = function(x, y) { return x + y; }, + square = function(n) { return n * n; }; + /** Used to set property descriptors. */ var defineProperty = (function() { try { @@ -1979,16 +1983,28 @@ test('should work when in between lazy operators', 2, function() { if (!isNpm) { - var actual = _(falsey).slice().compact().slice().value(); + var actual = _(falsey).thru(_.slice).compact().thru(_.slice).value(); deepEqual(actual, []); - actual = _(falsey).slice().push(true, 1).compact().push('a').slice().value(); + actual = _(falsey).thru(_.slice).push(true, 1).compact().push('a').value(); deepEqual(actual, [true, 1, 'a']); } else { skipTest(2); } }); + + 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(); + + deepEqual(actual, [9]); + } + else { + skipTest(); + } + }); }()); /*--------------------------------------------------------------------------*/ @@ -2011,19 +2027,9 @@ isFlow = methodName == 'flow'; test('`_.' + methodName + '` should supply each function with the return value of the previous', 1, function() { - function add(x, y) { - return x + y; - } - - function square(n) { - return n * n; - } + var fixed = function(n) { return n.toFixed(1); }, + combined = isFlow ? func(add, square, fixed) : func(fixed, square, add); - function fixed(n) { - return n.toFixed(1); - } - - var combined = isFlow ? func(add, square, fixed) : func(fixed, square, add); strictEqual(combined(1, 2), '9.0'); }); @@ -2183,10 +2189,10 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { var array = [1, 2, 1, 3], - predicate = function(value) { return value > 1; }, - actual = _(array).countBy(_.identity).map(String).filter(predicate).take().value(); + predicate = function(value) { return value > 2; }, + actual = _(array).countBy(_.identity).map(square).filter(predicate).take().value(); - deepEqual(actual, ['2']); + deepEqual(actual, [4]); } else { skipTest(); @@ -5817,10 +5823,10 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { var array = [1, 2, 1, 3], - predicate = function(value) { return value > 1; }, - actual = _(array).indexBy(_.identity).map(String).filter(predicate).take().value(); + predicate = function(value) { return value > 2; }, + actual = _(array).indexBy(_.identity).map(square).filter(predicate).take().value(); - deepEqual(actual, ['2']); + deepEqual(actual, [4]); } else { skipTest(); @@ -9690,11 +9696,11 @@ test('should produce methods that work in a lazy chain sequence', 1, function() { if (!isNpm) { - var predicate = function(value) { return value > 1; }; + var predicate = function(value) { return value > 2; }; _.mixin({ 'a': _.countBy, 'b': _.filter }); - var actual = _([1, 2, 1, 3]).a(_.identity).map(String).b(predicate).take().value(); - deepEqual(actual, ['2']); + var actual = _([1, 2, 1, 3]).a(_.identity).map(square).b(predicate).take().value(); + deepEqual(actual, [4]); delete _.a; delete _.prototype.a; @@ -13553,15 +13559,28 @@ (function() { test('should return the values of objects', 1, function() { - var array = [1, 2, 3], - object = { 'a': 1, 'b': 2, 'c': 3 }; + var array = [1, 2], + object = { 'a': 1, 'b': 2 }; deepEqual(_.toArray(object), array); }); test('should work with a string for `collection` (test in Opera < 10.52)', 2, function() { - deepEqual(_.toArray('abc'), ['a', 'b', 'c']); - deepEqual(_.toArray(Object('abc')), ['a', 'b', 'c']); + deepEqual(_.toArray('ab'), ['a', 'b']); + deepEqual(_.toArray(Object('ab')), ['a', 'b']); + }); + + test('should work in a lazy chain sequence', 2, function() { + if (!isNpm) { + var actual = _([1, 2]).map(String).toArray().value(); + deepEqual(actual, ['1', '2']); + + actual = _({ 'a': 1, 'b': 2 }).toArray().map(String).value(); + deepEqual(actual, ['1', '2']); + } + else { + skipTest(2); + } }); }()); @@ -14507,10 +14526,10 @@ test('should work in a lazy chain sequence', 1, function() { if (!isNpm) { var array = [['a', 1], ['b', 2]], - predicate = function(value) { return value > 1; }, - actual = _(array).zipObject().map(String).filter(predicate).take().value(); + predicate = function(value) { return value > 2; }, + actual = _(array).zipObject().map(square).filter(predicate).take().value(); - deepEqual(actual, ['2']); + deepEqual(actual, [4]); } else { skipTest(); @@ -14595,7 +14614,7 @@ if (!isNpm) { var array1 = [5, null, 3, null, 1], array2 = [10, null, 8, null, 6], - wrapper1 = _(array1).compact().map(_.partial(Math.pow, _, 2)).takeRight(2).sort(), + wrapper1 = _(array1).thru(_.compact).map(square).takeRight(2).sort(), wrapper2 = wrapper1.plant(array2); deepEqual(wrapper2.value(), [36, 64]); @@ -14707,11 +14726,11 @@ var array = [1, 2, 3, null]; _.each(['map', 'filter'], function(methodName) { - var actual = _(array)[methodName](_.identity).compact().reverse().value(); + var actual = _(array)[methodName](_.identity).thru(_.compact).reverse().value(); deepEqual(actual, [3, 2, 1]); - actual = _(array.slice()).pull(2)[methodName](_.identity).compact().pull(1).push(4).reverse().value(); - deepEqual(actual, [4, 3]); + actual = _(array).thru(_.compact)[methodName](_.identity).pull(1).push(4).reverse().value(); + deepEqual(actual, [4, 3, 2]); }); } else { From 96b663b783a4b8d74fd172a25b0f61d21d6ffa6f Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 10 Feb 2015 00:33:10 -0800 Subject: [PATCH 35/61] Ensure lazy `slice` handles floating-point `start` and `end` params. --- lodash.src.js | 2 +- test/test.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index c3f7abe289..fbe4958fbc 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -11037,7 +11037,7 @@ whileName = methodName + 'While'; LazyWrapper.prototype[methodName] = function(n) { - n = n == null ? 1 : nativeMax(+n || 0, 0); + n = n == null ? 1 : nativeMax(floor(n) || 0, 0); var result = this.clone(); if (result.__filtered__) { diff --git a/test/test.js b/test/test.js index 8d79e8f8cf..5f230f23a2 100644 --- a/test/test.js +++ b/test/test.js @@ -12044,7 +12044,7 @@ notStrictEqual(actual, array); }); - test('should work in a lazy chain sequence', 12, function() { + test('should work in a lazy chain sequence', 18, function() { if (!isNpm) { var wrapped = _(array); @@ -12063,9 +12063,16 @@ deepEqual(wrapped.slice(0, 1).value(), [1]); deepEqual(wrapped.slice(NaN, '1').value(), [1]); + + deepEqual(wrapped.slice(0.1, 1.1).value(), [1]); + deepEqual(wrapped.slice('0', 1).value(), [1]); + deepEqual(wrapped.slice(0, '1').value(), [1]); + deepEqual(wrapped.slice('1').value(), [2, 3]); + deepEqual(wrapped.slice(NaN, 1).value(), [1]); + deepEqual(wrapped.slice(1, NaN).value(), []); } else { - skipTest(12); + skipTest(18); } }); }()); From e95f5479501ef8d108ec65a3d9f312d4f8622ad6 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 10 Feb 2015 01:16:02 -0800 Subject: [PATCH 36/61] Add doc notes on guarded methods. [ci skip] --- lodash.src.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index fbe4958fbc..6b61966295 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -853,12 +853,13 @@ * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * - * The wrapper functions that support shortcut fusion are: - * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `first`, - * `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, `slice`, - * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `where` + * The wrapper methods that support shortcut fusion are: + * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, + * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, + * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`, + * and `where` * - * The chainable wrapper functions are: + * 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`, @@ -876,7 +877,7 @@ * `unshift`, `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, * `zip`, and `zipObject` * - * The wrapper functions that are **not** chainable by default are: + * The wrapper methods that are **not** chainable by default are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, @@ -891,7 +892,7 @@ * `startCase`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, * `trunc`, `unescape`, `uniqueId`, `value`, and `words` * - * The wrapper function `sample` will return a wrapped value when `n` is provided, + * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. * * @name _ @@ -6171,6 +6172,15 @@ * callback returns `true` for elements that have the properties of the given * object, else `false`. * + * Many lodash methods are guarded to work as interatees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, `drop`, + * `dropRight`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`, `slice`, + * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `random`, `range`, `sample`, `uniq`, and `words` + * * @static * @memberOf _ * @alias collect @@ -6377,6 +6387,12 @@ * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * + * Many lodash methods are guarded to work as interatees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `merge`, and `sortAllBy` + * * @static * @memberOf _ * @alias foldl, inject From faf67fae03e3026a96fd46b2992e17a073ed5c8c Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 10 Feb 2015 08:02:38 -0800 Subject: [PATCH 37/61] Update qunit to 1.17.1. --- package.json | 2 +- test/backbone.html | 7 +------ test/test.js | 10 ++-------- test/underscore.html | 7 +------ 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index a5ad81146b..f1950291ea 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "jquery": "~1.11.2", "platform": "~1.3.0", "qunit-extras": "~1.4.0", - "qunitjs": "~1.16.0", + "qunitjs": "~1.17.0", "requirejs": "~2.1.15" }, "volo": { diff --git a/test/backbone.html b/test/backbone.html index f9dc8ab96e..61834c8d05 100644 --- a/test/backbone.html +++ b/test/backbone.html @@ -42,12 +42,7 @@

Test

}()); QUnit.config.asyncRetries = 10; - - QUnit.begin(function() { - QUnit.config.hidepassed = true; - document.getElementById('qunit-tests').className += ' hidepass'; - document.getElementById('qunit-urlconfig-hidepassed').checked = true; - }); + QUnit.config.hidepassed = true; // load lodash if (!ui.isModularize) { diff --git a/test/test.js b/test/test.js index 5f230f23a2..8a8323e802 100644 --- a/test/test.js +++ b/test/test.js @@ -15437,15 +15437,9 @@ /*--------------------------------------------------------------------------*/ QUnit.config.asyncRetries = 10; + QUnit.config.hidepassed = true; - if (document) { - QUnit.begin(function() { - QUnit.config.hidepassed = true; - document.getElementById('qunit-tests').className += ' hidepass'; - document.getElementById('qunit-urlconfig-hidepassed').checked = true; - }); - } else { - QUnit.config.hidepassed = true; + if (!document) { QUnit.config.noglobals = true; QUnit.load(); } diff --git a/test/underscore.html b/test/underscore.html index c483ec6f64..43bdea2281 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -37,12 +37,7 @@