_createHybrid.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. var composeArgs = require('./_composeArgs'),
  2. composeArgsRight = require('./_composeArgsRight'),
  3. countHolders = require('./_countHolders'),
  4. createCtor = require('./_createCtor'),
  5. createRecurry = require('./_createRecurry'),
  6. getHolder = require('./_getHolder'),
  7. reorder = require('./_reorder'),
  8. replaceHolders = require('./_replaceHolders'),
  9. root = require('./_root');
  10. /** Used to compose bitmasks for function metadata. */
  11. var WRAP_BIND_FLAG = 1,
  12. WRAP_BIND_KEY_FLAG = 2,
  13. WRAP_CURRY_FLAG = 8,
  14. WRAP_CURRY_RIGHT_FLAG = 16,
  15. WRAP_ARY_FLAG = 128,
  16. WRAP_FLIP_FLAG = 512;
  17. /**
  18. * Creates a function that wraps `func` to invoke it with optional `this`
  19. * binding of `thisArg`, partial application, and currying.
  20. *
  21. * @private
  22. * @param {Function|string} func The function or method name to wrap.
  23. * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
  24. * @param {*} [thisArg] The `this` binding of `func`.
  25. * @param {Array} [partials] The arguments to prepend to those provided to
  26. * the new function.
  27. * @param {Array} [holders] The `partials` placeholder indexes.
  28. * @param {Array} [partialsRight] The arguments to append to those provided
  29. * to the new function.
  30. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
  31. * @param {Array} [argPos] The argument positions of the new function.
  32. * @param {number} [ary] The arity cap of `func`.
  33. * @param {number} [arity] The arity of `func`.
  34. * @returns {Function} Returns the new wrapped function.
  35. */
  36. function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
  37. var isAry = bitmask & WRAP_ARY_FLAG,
  38. isBind = bitmask & WRAP_BIND_FLAG,
  39. isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
  40. isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
  41. isFlip = bitmask & WRAP_FLIP_FLAG,
  42. Ctor = isBindKey ? undefined : createCtor(func);
  43. function wrapper() {
  44. var length = arguments.length,
  45. args = Array(length),
  46. index = length;
  47. while (index--) {
  48. args[index] = arguments[index];
  49. }
  50. if (isCurried) {
  51. var placeholder = getHolder(wrapper),
  52. holdersCount = countHolders(args, placeholder);
  53. }
  54. if (partials) {
  55. args = composeArgs(args, partials, holders, isCurried);
  56. }
  57. if (partialsRight) {
  58. args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
  59. }
  60. length -= holdersCount;
  61. if (isCurried && length < arity) {
  62. var newHolders = replaceHolders(args, placeholder);
  63. return createRecurry(
  64. func, bitmask, createHybrid, wrapper.placeholder, thisArg,
  65. args, newHolders, argPos, ary, arity - length
  66. );
  67. }
  68. var thisBinding = isBind ? thisArg : this,
  69. fn = isBindKey ? thisBinding[func] : func;
  70. length = args.length;
  71. if (argPos) {
  72. args = reorder(args, argPos);
  73. } else if (isFlip && length > 1) {
  74. args.reverse();
  75. }
  76. if (isAry && ary < length) {
  77. args.length = ary;
  78. }
  79. if (this && this !== root && this instanceof wrapper) {
  80. fn = Ctor || createCtor(fn);
  81. }
  82. return fn.apply(thisBinding, args);
  83. }
  84. return wrapper;
  85. }
  86. module.exports = createHybrid;