SIGN IN SIGN UP

A modern JavaScript utility library delivering modularity, performance, & extras.

0 0 2 JavaScript
2016-07-24 09:52:04 -07:00
define(['./_composeArgs', './_composeArgsRight', './_countHolders', './_createCtor', './_createRecurry', './_getHolder', './_reorder', './_replaceHolders', './_root'], function(composeArgs, composeArgsRight, countHolders, createCtor, createRecurry, getHolder, reorder, replaceHolders, root) {
2015-12-16 17:49:07 -08:00
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
var undefined;
2015-01-08 00:37:01 -08:00
2016-07-24 09:52:04 -07:00
/** Used to compose bitmasks for function metadata. */
2016-11-13 22:49:46 -08:00
var WRAP_BIND_FLAG = 1,
WRAP_BIND_KEY_FLAG = 2,
WRAP_CURRY_FLAG = 8,
WRAP_CURRY_RIGHT_FLAG = 16,
WRAP_ARY_FLAG = 128,
WRAP_FLIP_FLAG = 512;
2015-01-08 00:37:01 -08:00
/**
2015-12-16 17:53:20 -08:00
* Creates a function that wraps `func` to invoke it with optional `this`
* binding of `thisArg`, partial application, and currying.
2015-01-08 00:37:01 -08:00
*
* @private
2015-12-16 17:53:20 -08:00
* @param {Function|string} func The function or method name to wrap.
2016-07-24 09:52:04 -07:00
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
2015-01-08 00:37:01 -08:00
* @param {*} [thisArg] The `this` binding of `func`.
2016-03-26 00:00:01 -07:00
* @param {Array} [partials] The arguments to prepend to those provided to
* the new function.
2015-01-08 00:37:01 -08:00
* @param {Array} [holders] The `partials` placeholder indexes.
2016-03-26 00:00:01 -07:00
* @param {Array} [partialsRight] The arguments to append to those provided
* to the new function.
2015-01-08 00:37:01 -08:00
* @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.
*/
2016-07-24 09:52:04 -07:00
function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
2016-11-13 22:49:46 -08:00
var isAry = bitmask & WRAP_ARY_FLAG,
isBind = bitmask & WRAP_BIND_FLAG,
isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
isFlip = bitmask & WRAP_FLIP_FLAG,
2016-07-24 09:52:04 -07:00
Ctor = isBindKey ? undefined : createCtor(func);
2015-01-08 00:37:01 -08:00
function wrapper() {
var length = arguments.length,
2016-05-07 11:49:46 -07:00
args = Array(length),
index = length;
2015-01-08 00:37:01 -08:00
while (index--) {
args[index] = arguments[index];
}
2016-02-21 20:40:07 -08:00
if (isCurried) {
2016-05-07 11:49:46 -07:00
var placeholder = getHolder(wrapper),
2016-02-21 20:40:07 -08:00
holdersCount = countHolders(args, placeholder);
}
2015-01-08 00:37:01 -08:00
if (partials) {
2016-02-21 20:40:07 -08:00
args = composeArgs(args, partials, holders, isCurried);
2015-01-08 00:37:01 -08:00
}
if (partialsRight) {
2016-02-21 20:40:07 -08:00
args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
2015-01-08 00:37:01 -08:00
}
2016-02-21 20:40:07 -08:00
length -= holdersCount;
if (isCurried && length < arity) {
var newHolders = replaceHolders(args, placeholder);
2016-07-24 09:52:04 -07:00
return createRecurry(
func, bitmask, createHybrid, wrapper.placeholder, thisArg,
2016-02-21 20:40:07 -08:00
args, newHolders, argPos, ary, arity - length
);
2015-01-08 00:37:01 -08:00
}
2015-12-16 17:50:42 -08:00
var thisBinding = isBind ? thisArg : this,
fn = isBindKey ? thisBinding[func] : func;
2016-02-21 20:40:07 -08:00
length = args.length;
2015-01-08 00:37:01 -08:00
if (argPos) {
args = reorder(args, argPos);
2016-02-21 20:40:07 -08:00
} else if (isFlip && length > 1) {
2015-12-16 17:53:20 -08:00
args.reverse();
2015-01-08 00:37:01 -08:00
}
2016-02-21 20:40:07 -08:00
if (isAry && ary < length) {
2015-01-08 00:37:01 -08:00
args.length = ary;
}
2015-12-16 17:50:42 -08:00
if (this && this !== root && this instanceof wrapper) {
2016-07-24 09:52:04 -07:00
fn = Ctor || createCtor(fn);
2015-12-16 17:50:42 -08:00
}
2015-12-16 17:48:35 -08:00
return fn.apply(thisBinding, args);
2015-01-08 00:37:01 -08:00
}
return wrapper;
}
2016-07-24 09:52:04 -07:00
return createHybrid;
2015-01-08 00:37:01 -08:00
});