76cc02ce86388b588a5a620ff5ee128ce186f472
[yaffs-website] / node_modules / grunt-legacy-util / node_modules / lodash / fp / _baseConvert.js
1 var mapping = require('./_mapping'),
2     mutateMap = mapping.mutate,
3     placeholder = {};
4
5 /**
6  * The base implementation of `convert` which accepts a `util` object of methods
7  * required to perform conversions.
8  *
9  * @param {Object} util The util object.
10  * @param {string} name The name of the function to wrap.
11  * @param {Function} func The function to wrap.
12  * @param {Object} [options] The options object.
13  * @param {boolean} [options.cap=true] Specify capping iteratee arguments.
14  * @param {boolean} [options.curry=true] Specify currying.
15  * @param {boolean} [options.fixed=true] Specify fixed arity.
16  * @param {boolean} [options.immutable=true] Specify immutable operations.
17  * @param {boolean} [options.rearg=true] Specify rearranging arguments.
18  * @returns {Function|Object} Returns the converted function or object.
19  */
20 function baseConvert(util, name, func, options) {
21   options || (options = {});
22
23   if (typeof func != 'function') {
24     func = name;
25     name = undefined;
26   }
27   if (func == null) {
28     throw new TypeError;
29   }
30   var config = {
31     'cap': 'cap' in options ? options.cap : true,
32     'curry': 'curry' in options ? options.curry : true,
33     'fixed': 'fixed' in options ? options.fixed : true,
34     'immutable': 'immutable' in options ? options.immutable : true,
35     'rearg': 'rearg' in options ? options.rearg : true
36   };
37
38   var forceRearg = ('rearg' in options) && options.rearg;
39
40   var isLib = name === undefined && typeof func.VERSION == 'string';
41
42   var _ = isLib ? func : {
43     'ary': util.ary,
44     'cloneDeep': util.cloneDeep,
45     'curry': util.curry,
46     'forEach': util.forEach,
47     'isFunction': util.isFunction,
48     'iteratee': util.iteratee,
49     'keys': util.keys,
50     'rearg': util.rearg,
51     'spread': util.spread
52   };
53
54   var ary = _.ary,
55       cloneDeep = _.cloneDeep,
56       curry = _.curry,
57       each = _.forEach,
58       isFunction = _.isFunction,
59       keys = _.keys,
60       rearg = _.rearg,
61       spread = _.spread;
62
63   var baseArity = function(func, n) {
64     return n == 2
65       ? function(a, b) { return func.apply(undefined, arguments); }
66       : function(a) { return func.apply(undefined, arguments); };
67   };
68
69   var baseAry = function(func, n) {
70     return n == 2
71       ? function(a, b) { return func(a, b); }
72       : function(a) { return func(a); };
73   };
74
75   var cloneArray = function(array) {
76     var length = array ? array.length : 0,
77         result = Array(length);
78
79     while (length--) {
80       result[length] = array[length];
81     }
82     return result;
83   };
84
85   var createCloner = function(func) {
86     return function(object) {
87       return func({}, object);
88     };
89   };
90
91   var immutWrap = function(func, cloner) {
92     return overArg(func, cloner, true);
93   };
94
95   var iterateeAry = function(func, n) {
96     return overArg(func, function(func) {
97       return baseAry(func, n);
98     });
99   };
100
101   var iterateeRearg = function(func, indexes) {
102     return overArg(func, function(func) {
103       var n = indexes.length;
104       return baseArity(rearg(baseAry(func, n), indexes), n);
105     });
106   };
107
108   var overArg = function(func, iteratee, retArg) {
109     return function() {
110       var length = arguments.length,
111           args = Array(length);
112
113       while (length--) {
114         args[length] = arguments[length];
115       }
116       args[0] = iteratee(args[0]);
117       var result = func.apply(undefined, args);
118       return retArg ? args[0] : result;
119     };
120   };
121
122   var wrappers = {
123     'iteratee': function(iteratee) {
124       return function() {
125         var func = arguments[0],
126             arity = arguments[1];
127
128         if (!config.cap) {
129           return iteratee(func, arity);
130         }
131         arity = arity > 2 ? (arity - 2) : 1;
132         func = iteratee(func);
133         var length = func.length;
134         return (length && length <= arity) ? func : baseAry(func, arity);
135       };
136     },
137     'mixin': function(mixin) {
138       return function(source) {
139         var func = this;
140         if (!isFunction(func)) {
141           return mixin(func, Object(source));
142         }
143         var methods = [],
144             methodNames = [];
145
146         each(keys(source), function(key) {
147           var value = source[key];
148           if (isFunction(value)) {
149             methodNames.push(key);
150             methods.push(func.prototype[key]);
151           }
152         });
153
154         mixin(func, Object(source));
155
156         each(methodNames, function(methodName, index) {
157           var method = methods[index];
158           if (isFunction(method)) {
159             func.prototype[methodName] = method;
160           } else {
161             delete func.prototype[methodName];
162           }
163         });
164         return func;
165       };
166     },
167     'runInContext': function(runInContext) {
168       return function(context) {
169         return baseConvert(util, runInContext(context), undefined, options);
170       };
171     }
172   };
173
174   var wrap = function(name, func) {
175     name = mapping.aliasToReal[name] || name;
176     var wrapper = wrappers[name];
177     if (wrapper) {
178       return wrapper(func);
179     }
180     var wrapped = func;
181     if (config.immutable) {
182       if (mutateMap.array[name]) {
183         wrapped = immutWrap(func, cloneArray);
184       }
185       else if (mutateMap.object[name]) {
186         wrapped = immutWrap(func, createCloner(func));
187       }
188       else if (mutateMap.set[name]) {
189         wrapped = immutWrap(func, cloneDeep);
190       }
191     }
192     var result;
193     each(mapping.caps, function(cap) {
194       each(mapping.aryMethod[cap], function(otherName) {
195         if (name == otherName) {
196           var aryN = !isLib && mapping.iterateeAry[name],
197               reargIndexes = mapping.iterateeRearg[name],
198               spreadStart = mapping.methodSpread[name];
199
200           if (config.fixed) {
201             result = spreadStart === undefined
202               ? ary(wrapped, cap)
203               : spread(wrapped, spreadStart);
204           }
205           if (config.rearg && cap > 1 && (forceRearg || !mapping.skipRearg[name])) {
206             result = rearg(result, mapping.methodRearg[name] || mapping.aryRearg[cap]);
207           }
208           if (config.cap) {
209             if (reargIndexes) {
210               result = iterateeRearg(result, reargIndexes);
211             } else if (aryN) {
212               result = iterateeAry(result, aryN);
213             }
214           }
215           if (config.curry && cap > 1) {
216             result = curry(result, cap);
217           }
218           return false;
219         }
220       });
221       return !result;
222     });
223
224     result || (result = func);
225     if (mapping.placeholder[name]) {
226       func.placeholder = result.placeholder = placeholder;
227     }
228     return result;
229   };
230
231   if (!isLib) {
232     return wrap(name, func);
233   }
234   // Add placeholder.
235   _.placeholder = placeholder;
236
237   // Iterate over methods for the current ary cap.
238   var pairs = [];
239   each(mapping.caps, function(cap) {
240     each(mapping.aryMethod[cap], function(key) {
241       var func = _[mapping.rename[key] || key];
242       if (func) {
243         pairs.push([key, wrap(key, func)]);
244       }
245     });
246   });
247
248   // Assign to `_` leaving `_.prototype` unchanged to allow chaining.
249   each(pairs, function(pair) {
250     _[pair[0]] = pair[1];
251   });
252
253   // Wrap the lodash method and its aliases.
254   each(keys(_), function(key) {
255     each(mapping.realToAlias[key] || [], function(alias) {
256       _[alias] = _[key];
257     });
258   });
259
260   return _;
261 }
262
263 module.exports = baseConvert;