1 var mapping = require('./_mapping'),
2 mutateMap = mapping.mutate,
6 * The base implementation of `convert` which accepts a `util` object of methods
7 * required to perform conversions.
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.
20 function baseConvert(util, name, func, options) {
22 isLib = typeof name == 'function',
23 isObj = name === Object(name);
33 options || (options = {});
36 'cap': 'cap' in options ? options.cap : true,
37 'curry': 'curry' in options ? options.curry : true,
38 'fixed': 'fixed' in options ? options.fixed : true,
39 'immutable': 'immutable' in options ? options.immutable : true,
40 'rearg': 'rearg' in options ? options.rearg : true
43 var forceRearg = ('rearg' in options) && options.rearg;
45 var helpers = isLib ? func : {
49 'forEach': util.forEach,
50 'isArray': util.isArray,
51 'isFunction': util.isFunction,
52 'iteratee': util.iteratee,
55 'spread': util.spread,
59 var ary = helpers.ary,
60 clone = helpers.clone,
61 curry = helpers.curry,
62 each = helpers.forEach,
63 isArray = helpers.isArray,
64 isFunction = helpers.isFunction,
66 rearg = helpers.rearg,
67 spread = helpers.spread,
68 toPath = helpers.toPath;
70 var aryMethodKeys = keys(mapping.aryMethod);
72 var baseArity = function(func, n) {
74 ? function(a, b) { return func.apply(undefined, arguments); }
75 : function(a) { return func.apply(undefined, arguments); };
78 var baseAry = function(func, n) {
80 ? function(a, b) { return func(a, b); }
81 : function(a) { return func(a); };
84 var cloneArray = function(array) {
85 var length = array ? array.length : 0,
86 result = Array(length);
89 result[length] = array[length];
94 var cloneByPath = function(object, path) {
99 result = clone(Object(object)),
102 while (nested != null && ++index < length) {
103 var key = path[index],
107 nested[key] = clone(Object(value));
109 nested = nested[key];
114 var createCloner = function(func) {
115 return function(object) {
116 return func({}, object);
120 var immutWrap = function(func, cloner) {
122 var length = arguments.length;
126 var args = Array(length);
128 args[length] = arguments[length];
130 var result = args[0] = cloner.apply(undefined, args);
131 func.apply(undefined, args);
136 var iterateeAry = function(func, n) {
137 return overArg(func, function(func) {
138 return typeof func == 'function' ? baseAry(func, n) : func;
142 var iterateeRearg = function(func, indexes) {
143 return overArg(func, function(func) {
144 var n = indexes.length;
145 return baseArity(rearg(baseAry(func, n), indexes), n);
149 var overArg = function(func, iteratee, retArg) {
151 var length = arguments.length;
155 var args = Array(length);
157 args[length] = arguments[length];
159 var index = config.rearg ? 0 : (length - 1);
160 args[index] = iteratee(args[index]);
161 return func.apply(undefined, args);
166 'castArray': function(castArray) {
168 var value = arguments[0];
169 return isArray(value)
170 ? castArray(cloneArray(value))
171 : castArray.apply(undefined, arguments);
174 'iteratee': function(iteratee) {
176 var func = arguments[0],
177 arity = arguments[1],
178 result = iteratee(func, arity),
179 length = result.length;
181 if (config.cap && typeof arity == 'number') {
182 arity = arity > 2 ? (arity - 2) : 1;
183 return (length && length <= arity) ? result : baseAry(result, arity);
188 'mixin': function(mixin) {
189 return function(source) {
191 if (!isFunction(func)) {
192 return mixin(func, Object(source));
197 each(keys(source), function(key) {
198 var value = source[key];
199 if (isFunction(value)) {
200 methodNames.push(key);
201 methods.push(func.prototype[key]);
205 mixin(func, Object(source));
207 each(methodNames, function(methodName, index) {
208 var method = methods[index];
209 if (isFunction(method)) {
210 func.prototype[methodName] = method;
212 delete func.prototype[methodName];
218 'runInContext': function(runInContext) {
219 return function(context) {
220 return baseConvert(util, runInContext(context), options);
225 var wrap = function(name, func) {
226 name = mapping.aliasToReal[name] || name;
227 var wrapper = wrappers[name];
229 return wrapper(func);
232 if (config.immutable) {
233 if (mutateMap.array[name]) {
234 wrapped = immutWrap(func, cloneArray);
236 else if (mutateMap.object[name]) {
237 wrapped = immutWrap(func, createCloner(func));
239 else if (mutateMap.set[name]) {
240 wrapped = immutWrap(func, cloneByPath);
244 each(aryMethodKeys, function(aryKey) {
245 each(mapping.aryMethod[aryKey], function(otherName) {
246 if (name == otherName) {
247 var aryN = !isLib && mapping.iterateeAry[name],
248 reargIndexes = mapping.iterateeRearg[name],
249 spreadStart = mapping.methodSpread[name];
253 result = spreadStart === undefined
254 ? ary(result, aryKey)
255 : spread(result, spreadStart);
257 if (config.rearg && aryKey > 1 && (forceRearg || !mapping.skipRearg[name])) {
258 result = rearg(result, mapping.methodRearg[name] || mapping.aryRearg[aryKey]);
262 result = iterateeRearg(result, reargIndexes);
264 result = iterateeAry(result, aryN);
267 if (config.curry && aryKey > 1) {
268 result = curry(result, aryKey);
276 result || (result = wrapped);
277 if (mapping.placeholder[name]) {
278 setPlaceholder = true;
279 func.placeholder = result.placeholder = placeholder;
285 return wrap(name, func);
289 // Iterate over methods for the current ary cap.
291 each(aryMethodKeys, function(aryKey) {
292 each(mapping.aryMethod[aryKey], function(key) {
293 var func = _[mapping.remap[key] || key];
295 pairs.push([key, wrap(key, func)]);
300 // Assign to `_` leaving `_.prototype` unchanged to allow chaining.
301 each(pairs, function(pair) {
302 _[pair[0]] = pair[1];
305 if (setPlaceholder) {
306 _.placeholder = placeholder;
308 // Wrap the lodash method and its aliases.
309 each(keys(_), function(key) {
310 each(mapping.realToAlias[key] || [], function(alias) {
318 module.exports = baseConvert;