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) {
21 options || (options = {});
23 if (typeof func != 'function') {
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
38 var forceRearg = ('rearg' in options) && options.rearg;
40 var isLib = name === undefined && typeof func.VERSION == 'string';
42 var _ = isLib ? func : {
44 'cloneDeep': util.cloneDeep,
46 'forEach': util.forEach,
47 'isFunction': util.isFunction,
48 'iteratee': util.iteratee,
55 cloneDeep = _.cloneDeep,
58 isFunction = _.isFunction,
63 var baseArity = function(func, n) {
65 ? function(a, b) { return func.apply(undefined, arguments); }
66 : function(a) { return func.apply(undefined, arguments); };
69 var baseAry = function(func, n) {
71 ? function(a, b) { return func(a, b); }
72 : function(a) { return func(a); };
75 var cloneArray = function(array) {
76 var length = array ? array.length : 0,
77 result = Array(length);
80 result[length] = array[length];
85 var createCloner = function(func) {
86 return function(object) {
87 return func({}, object);
91 var immutWrap = function(func, cloner) {
92 return overArg(func, cloner, true);
95 var iterateeAry = function(func, n) {
96 return overArg(func, function(func) {
97 return baseAry(func, n);
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);
108 var overArg = function(func, iteratee, retArg) {
110 var length = arguments.length,
111 args = Array(length);
114 args[length] = arguments[length];
116 args[0] = iteratee(args[0]);
117 var result = func.apply(undefined, args);
118 return retArg ? args[0] : result;
123 'iteratee': function(iteratee) {
125 var func = arguments[0],
126 arity = arguments[1];
129 return iteratee(func, arity);
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);
137 'mixin': function(mixin) {
138 return function(source) {
140 if (!isFunction(func)) {
141 return mixin(func, Object(source));
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]);
154 mixin(func, Object(source));
156 each(methodNames, function(methodName, index) {
157 var method = methods[index];
158 if (isFunction(method)) {
159 func.prototype[methodName] = method;
161 delete func.prototype[methodName];
167 'runInContext': function(runInContext) {
168 return function(context) {
169 return baseConvert(util, runInContext(context), undefined, options);
174 var wrap = function(name, func) {
175 name = mapping.aliasToReal[name] || name;
176 var wrapper = wrappers[name];
178 return wrapper(func);
181 if (config.immutable) {
182 if (mutateMap.array[name]) {
183 wrapped = immutWrap(func, cloneArray);
185 else if (mutateMap.object[name]) {
186 wrapped = immutWrap(func, createCloner(func));
188 else if (mutateMap.set[name]) {
189 wrapped = immutWrap(func, cloneDeep);
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];
201 result = spreadStart === undefined
203 : spread(wrapped, spreadStart);
205 if (config.rearg && cap > 1 && (forceRearg || !mapping.skipRearg[name])) {
206 result = rearg(result, mapping.methodRearg[name] || mapping.aryRearg[cap]);
210 result = iterateeRearg(result, reargIndexes);
212 result = iterateeAry(result, aryN);
215 if (config.curry && cap > 1) {
216 result = curry(result, cap);
224 result || (result = func);
225 if (mapping.placeholder[name]) {
226 func.placeholder = result.placeholder = placeholder;
232 return wrap(name, func);
235 _.placeholder = placeholder;
237 // Iterate over methods for the current ary cap.
239 each(mapping.caps, function(cap) {
240 each(mapping.aryMethod[cap], function(key) {
241 var func = _[mapping.rename[key] || key];
243 pairs.push([key, wrap(key, func)]);
248 // Assign to `_` leaving `_.prototype` unchanged to allow chaining.
249 each(pairs, function(pair) {
250 _[pair[0]] = pair[1];
253 // Wrap the lodash method and its aliases.
254 each(keys(_), function(key) {
255 each(mapping.realToAlias[key] || [], function(alias) {
263 module.exports = baseConvert;