fb62371bf349777e0c0bcc9b1e758d0157089703
[platform/framework/web/crosswalk-tizen.git] /
1 var arrayCopy = require('./arrayCopy'),
2     composeArgs = require('./composeArgs'),
3     composeArgsRight = require('./composeArgsRight'),
4     createCtorWrapper = require('./createCtorWrapper'),
5     isLaziable = require('./isLaziable'),
6     reorder = require('./reorder'),
7     replaceHolders = require('./replaceHolders'),
8     setData = require('./setData');
9
10 /** Used to compose bitmasks for wrapper metadata. */
11 var BIND_FLAG = 1,
12     BIND_KEY_FLAG = 2,
13     CURRY_BOUND_FLAG = 4,
14     CURRY_FLAG = 8,
15     CURRY_RIGHT_FLAG = 16,
16     PARTIAL_FLAG = 32,
17     PARTIAL_RIGHT_FLAG = 64,
18     ARY_FLAG = 128;
19
20 /* Native method references for those with the same name as other `lodash` methods. */
21 var nativeMax = Math.max;
22
23 /**
24  * Creates a function that wraps `func` and invokes it with optional `this`
25  * binding of, partial application, and currying.
26  *
27  * @private
28  * @param {Function|string} func The function or method name to reference.
29  * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
30  * @param {*} [thisArg] The `this` binding of `func`.
31  * @param {Array} [partials] The arguments to prepend to those provided to the new function.
32  * @param {Array} [holders] The `partials` placeholder indexes.
33  * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
34  * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
35  * @param {Array} [argPos] The argument positions of the new function.
36  * @param {number} [ary] The arity cap of `func`.
37  * @param {number} [arity] The arity of `func`.
38  * @returns {Function} Returns the new wrapped function.
39  */
40 function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
41   var isAry = bitmask & ARY_FLAG,
42       isBind = bitmask & BIND_FLAG,
43       isBindKey = bitmask & BIND_KEY_FLAG,
44       isCurry = bitmask & CURRY_FLAG,
45       isCurryBound = bitmask & CURRY_BOUND_FLAG,
46       isCurryRight = bitmask & CURRY_RIGHT_FLAG;
47
48   var Ctor = !isBindKey && createCtorWrapper(func),
49       key = func;
50
51   function wrapper() {
52     // Avoid `arguments` object use disqualifying optimizations by
53     // converting it to an array before providing it to other functions.
54     var length = arguments.length,
55         index = length,
56         args = Array(length);
57
58     while (index--) {
59       args[index] = arguments[index];
60     }
61     if (partials) {
62       args = composeArgs(args, partials, holders);
63     }
64     if (partialsRight) {
65       args = composeArgsRight(args, partialsRight, holdersRight);
66     }
67     if (isCurry || isCurryRight) {
68       var placeholder = wrapper.placeholder,
69           argsHolders = replaceHolders(args, placeholder);
70
71       length -= argsHolders.length;
72       if (length < arity) {
73         var newArgPos = argPos ? arrayCopy(argPos) : null,
74             newArity = nativeMax(arity - length, 0),
75             newsHolders = isCurry ? argsHolders : null,
76             newHoldersRight = isCurry ? null : argsHolders,
77             newPartials = isCurry ? args : null,
78             newPartialsRight = isCurry ? null : args;
79
80         bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
81         bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
82
83         if (!isCurryBound) {
84           bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
85         }
86         var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
87             result = createHybridWrapper.apply(undefined, newData);
88
89         if (isLaziable(func)) {
90           setData(result, newData);
91         }
92         result.placeholder = placeholder;
93         return result;
94       }
95     }
96     var thisBinding = isBind ? thisArg : this;
97     if (isBindKey) {
98       func = thisBinding[key];
99     }
100     if (argPos) {
101       args = reorder(args, argPos);
102     }
103     if (isAry && ary < args.length) {
104       args.length = ary;
105     }
106     var fn = (this && this !== global && this instanceof wrapper) ? (Ctor || createCtorWrapper(func)) : func;
107     return fn.apply(thisBinding, args);
108   }
109   return wrapper;
110 }
111
112 module.exports = createHybridWrapper;