diff --git a/lodash.src.js b/lodash.src.js index a97783930..16836e55a 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -3375,25 +3375,39 @@ */ function createFlow(fromRight) { return function() { - var length = arguments.length, - index = length, - fromIndex = fromRight ? (length - 1) : 0; - + var length = arguments.length; if (!length) { return function() { return arguments[0]; }; } - var funcs = Array(length); - while (index--) { - funcs[index] = arguments[index]; - if (typeof funcs[index] != 'function') { + var index = fromRight ? length : -1, + leftIndex = 0, + funcs = Array(length), + wrapper = new LodashWrapper([]); + + while ((fromRight ? index-- : ++index < length)) { + var func = arguments[index]; + if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } + var data = func.name === 'wrapper' && getData(func); + if (data && data !== true && isLaziable(data[0])) { + wrapper = wrapper[data[0].name].apply(wrapper, data[3]); + } else if (func.length == 1 && isLaziable(func)) { + wrapper = wrapper[func.name](); + } else { + wrapper = wrapper.thru(func); + } + funcs[leftIndex++] = func; } return function() { - var index = fromIndex, - result = funcs[index].apply(this, arguments); + var args = arguments; + if (args.length == 1 && isArray(args[0])) { + return wrapper.plant(args[0]).value(); + } + var index = 0, + result = funcs[index].apply(this, args); - while ((fromRight ? index-- : ++index < length)) { + while (++index < length) { result = funcs[index].call(this, result); } return result; @@ -3558,11 +3572,10 @@ if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } - var funcName = support.funcNames ? func.name : '', - newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity], + var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity], result = createHybridWrapper.apply(undefined, newData); - if (funcName && func === lodash[funcName] && LazyWrapper.prototype[funcName]) { + if (isLaziable(func)) { setData(result, newData); } result.placeholder = placeholder; @@ -4108,6 +4121,11 @@ return false; } + function isLaziable(func) { + var funcName = support.funcNames ? func.name : ''; + return (funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype) || false; + } + /** * Checks if `value` is a valid array-like length. * diff --git a/test/test.js b/test/test.js index bd1b45497..d317bd24b 100644 --- a/test/test.js +++ b/test/test.js @@ -2232,6 +2232,34 @@ notStrictEqual(combined, _.identity); }); + test('`_.' + methodName + '` should support shortcut fusion', 3, function() { + if (!isNpm) { + var filterCount = 0, + mapCount = 0; + + var map = _.curry(_.rearg(_.ary(_.map, 2), 1, 0), 2), + filter = _.curry(_.rearg(_.ary(_.filter, 2), 1, 0), 2), + take = _.curry(_.rearg(_.ary(_.take, 2), 1, 0), 2); + + var partialMap = map(function(value) { mapCount++; return value * value; }), + partialFilter = filter(function(value) { filterCount++; return value % 2 == 0; }), + partialTake = take(2); + + var combined = isFlow + ? func(partialMap, partialFilter, _.compact, partialTake) + : func(partialTake, _.compact, partialFilter, partialMap); + + var actual = combined(_.range(100)); + + deepEqual(actual, [4, 16]); + strictEqual(filterCount, 5, 'filterCount'); + strictEqual(mapCount, 5, 'mapCount'); + } + else { + skipTest(3); + } + }); + test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() { if (!isNpm) { var wrapped = _(_.noop)[methodName]();