createFlow.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. var LodashWrapper = require('./LodashWrapper'),
  2. getData = require('./getData'),
  3. getFuncName = require('./getFuncName'),
  4. isArray = require('../lang/isArray'),
  5. isLaziable = require('./isLaziable');
  6. /** Used to compose bitmasks for wrapper metadata. */
  7. var CURRY_FLAG = 8,
  8. PARTIAL_FLAG = 32,
  9. ARY_FLAG = 128,
  10. REARG_FLAG = 256;
  11. /** Used as the size to enable large array optimizations. */
  12. var LARGE_ARRAY_SIZE = 200;
  13. /** Used as the `TypeError` message for "Functions" methods. */
  14. var FUNC_ERROR_TEXT = 'Expected a function';
  15. /**
  16. * Creates a `_.flow` or `_.flowRight` function.
  17. *
  18. * @private
  19. * @param {boolean} [fromRight] Specify iterating from right to left.
  20. * @returns {Function} Returns the new flow function.
  21. */
  22. function createFlow(fromRight) {
  23. return function() {
  24. var wrapper,
  25. length = arguments.length,
  26. index = fromRight ? length : -1,
  27. leftIndex = 0,
  28. funcs = Array(length);
  29. while ((fromRight ? index-- : ++index < length)) {
  30. var func = funcs[leftIndex++] = arguments[index];
  31. if (typeof func != 'function') {
  32. throw new TypeError(FUNC_ERROR_TEXT);
  33. }
  34. if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') {
  35. wrapper = new LodashWrapper([], true);
  36. }
  37. }
  38. index = wrapper ? -1 : length;
  39. while (++index < length) {
  40. func = funcs[index];
  41. var funcName = getFuncName(func),
  42. data = funcName == 'wrapper' ? getData(func) : undefined;
  43. if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {
  44. wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
  45. } else {
  46. wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
  47. }
  48. }
  49. return function() {
  50. var args = arguments,
  51. value = args[0];
  52. if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
  53. return wrapper.plant(value).value();
  54. }
  55. var index = 0,
  56. result = length ? funcs[index].apply(this, args) : value;
  57. while (++index < length) {
  58. result = funcs[index].call(this, result);
  59. }
  60. return result;
  61. };
  62. };
  63. }
  64. module.exports = createFlow;