_createFlow.js 2.4 KB

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