var composeArgs = require('./_composeArgs'), composeArgsRight = require('./_composeArgsRight'), createCtorWrapper = require('./_createCtorWrapper'), createRecurryWrapper = require('./_createRecurryWrapper'), reorder = require('./_reorder'), replaceHolders = require('./_replaceHolders'), root = require('./_root'); /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, ARY_FLAG = 128, FLIP_FLAG = 512; /** * Creates a function that wraps `func` to invoke it with optional `this` * binding of `thisArg`, partial application, and currying. * * @private * @param {Function|string} func The function or method name to wrap. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to prepend to those provided to the new function. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [partialsRight] The arguments to append to those provided to the new function. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, isFlip = bitmask & FLIP_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { var length = arguments.length, index = length, args = Array(length); while (index--) { args[index] = arguments[index]; } if (partials) { args = composeArgs(args, partials, holders); } if (partialsRight) { args = composeArgsRight(args, partialsRight, holdersRight); } if (isCurry || isCurryRight) { var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); length -= argsHolders.length; if (length < arity) { return createRecurryWrapper(func, bitmask, createHybridWrapper, placeholder, thisArg, args, argsHolders, argPos, ary, arity - length); } } var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; if (argPos) { args = reorder(args, argPos); } else if (isFlip && args.length > 1) { args.reverse(); } if (isAry && ary < args.length) { args.length = ary; } if (this && this !== root && this instanceof wrapper) { fn = Ctor || createCtorWrapper(fn); } return fn.apply(thisBinding, args); } return wrapper; } module.exports = createHybridWrapper;