_createHybridWrapper.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. var composeArgs = require('./_composeArgs'),
  2. composeArgsRight = require('./_composeArgsRight'),
  3. countHolders = require('./_countHolders'),
  4. createCtorWrapper = require('./_createCtorWrapper'),
  5. createRecurryWrapper = require('./_createRecurryWrapper'),
  6. getHolder = require('./_getHolder'),
  7. reorder = require('./_reorder'),
  8. replaceHolders = require('./_replaceHolders'),
  9. root = require('./_root');
  10. /** Used to compose bitmasks for wrapper metadata. */
  11. var BIND_FLAG = 1,
  12. BIND_KEY_FLAG = 2,
  13. CURRY_FLAG = 8,
  14. CURRY_RIGHT_FLAG = 16,
  15. ARY_FLAG = 128,
  16. 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 of wrapper flags. See `createWrapper`
  24. * for more details.
  25. * @param {*} [thisArg] The `this` binding of `func`.
  26. * @param {Array} [partials] The arguments to prepend to those provided to
  27. * the new function.
  28. * @param {Array} [holders] The `partials` placeholder indexes.
  29. * @param {Array} [partialsRight] The arguments to append to those provided
  30. * to the new function.
  31. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
  32. * @param {Array} [argPos] The argument positions of the new function.
  33. * @param {number} [ary] The arity cap of `func`.
  34. * @param {number} [arity] The arity of `func`.
  35. * @returns {Function} Returns the new wrapped function.
  36. */
  37. function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
  38. var isAry = bitmask & ARY_FLAG,
  39. isBind = bitmask & BIND_FLAG,
  40. isBindKey = bitmask & BIND_KEY_FLAG,
  41. isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
  42. isFlip = bitmask & FLIP_FLAG,
  43. Ctor = isBindKey ? undefined : createCtorWrapper(func);
  44. function wrapper() {
  45. var length = arguments.length,
  46. args = Array(length),
  47. index = length;
  48. while (index--) {
  49. args[index] = arguments[index];
  50. }
  51. if (isCurried) {
  52. var placeholder = getHolder(wrapper),
  53. holdersCount = countHolders(args, placeholder);
  54. }
  55. if (partials) {
  56. args = composeArgs(args, partials, holders, isCurried);
  57. }
  58. if (partialsRight) {
  59. args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
  60. }
  61. length -= holdersCount;
  62. if (isCurried && length < arity) {
  63. var newHolders = replaceHolders(args, placeholder);
  64. return createRecurryWrapper(
  65. func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg,
  66. args, newHolders, argPos, ary, arity - length
  67. );
  68. }
  69. var thisBinding = isBind ? thisArg : this,
  70. fn = isBindKey ? thisBinding[func] : func;
  71. length = args.length;
  72. if (argPos) {
  73. args = reorder(args, argPos);
  74. } else if (isFlip && length > 1) {
  75. args.reverse();
  76. }
  77. if (isAry && ary < length) {
  78. args.length = ary;
  79. }
  80. if (this && this !== root && this instanceof wrapper) {
  81. fn = Ctor || createCtorWrapper(fn);
  82. }
  83. return fn.apply(thisBinding, args);
  84. }
  85. return wrapper;
  86. }
  87. module.exports = createHybridWrapper;