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