| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 | var mapping = require('./_mapping'),    fallbackHolder = require('./placeholder');/** Built-in value reference. */var push = Array.prototype.push;/** * Creates a function, with an arity of `n`, that invokes `func` with the * arguments it receives. * * @private * @param {Function} func The function to wrap. * @param {number} n The arity of the new function. * @returns {Function} Returns the new function. */function baseArity(func, n) {  return n == 2    ? function(a, b) { return func.apply(undefined, arguments); }    : function(a) { return func.apply(undefined, arguments); };}/** * Creates a function that invokes `func`, with up to `n` arguments, ignoring * any additional arguments. * * @private * @param {Function} func The function to cap arguments for. * @param {number} n The arity cap. * @returns {Function} Returns the new function. */function baseAry(func, n) {  return n == 2    ? function(a, b) { return func(a, b); }    : function(a) { return func(a); };}/** * Creates a clone of `array`. * * @private * @param {Array} array The array to clone. * @returns {Array} Returns the cloned array. */function cloneArray(array) {  var length = array ? array.length : 0,      result = Array(length);  while (length--) {    result[length] = array[length];  }  return result;}/** * Creates a function that clones a given object using the assignment `func`. * * @private * @param {Function} func The assignment function. * @returns {Function} Returns the new cloner function. */function createCloner(func) {  return function(object) {    return func({}, object);  };}/** * A specialized version of `_.spread` which flattens the spread array into * the arguments of the invoked `func`. * * @private * @param {Function} func The function to spread arguments over. * @param {number} start The start position of the spread. * @returns {Function} Returns the new function. */function flatSpread(func, start) {  return function() {    var length = arguments.length,        lastIndex = length - 1,        args = Array(length);    while (length--) {      args[length] = arguments[length];    }    var array = args[start],        otherArgs = args.slice(0, start);    if (array) {      push.apply(otherArgs, array);    }    if (start != lastIndex) {      push.apply(otherArgs, args.slice(start + 1));    }    return func.apply(this, otherArgs);  };}/** * Creates a function that wraps `func` and uses `cloner` to clone the first * argument it receives. * * @private * @param {Function} func The function to wrap. * @param {Function} cloner The function to clone arguments. * @returns {Function} Returns the new immutable function. */function wrapImmutable(func, cloner) {  return function() {    var length = arguments.length;    if (!length) {      return;    }    var args = Array(length);    while (length--) {      args[length] = arguments[length];    }    var result = args[0] = cloner.apply(undefined, args);    func.apply(undefined, args);    return result;  };}/** * The base implementation of `convert` which accepts a `util` object of methods * required to perform conversions. * * @param {Object} util The util object. * @param {string} name The name of the function to convert. * @param {Function} func The function to convert. * @param {Object} [options] The options object. * @param {boolean} [options.cap=true] Specify capping iteratee arguments. * @param {boolean} [options.curry=true] Specify currying. * @param {boolean} [options.fixed=true] Specify fixed arity. * @param {boolean} [options.immutable=true] Specify immutable operations. * @param {boolean} [options.rearg=true] Specify rearranging arguments. * @returns {Function|Object} Returns the converted function or object. */function baseConvert(util, name, func, options) {  var isLib = typeof name == 'function',      isObj = name === Object(name);  if (isObj) {    options = func;    func = name;    name = undefined;  }  if (func == null) {    throw new TypeError;  }  options || (options = {});  var config = {    'cap': 'cap' in options ? options.cap : true,    'curry': 'curry' in options ? options.curry : true,    'fixed': 'fixed' in options ? options.fixed : true,    'immutable': 'immutable' in options ? options.immutable : true,    'rearg': 'rearg' in options ? options.rearg : true  };  var defaultHolder = isLib ? func : fallbackHolder,      forceCurry = ('curry' in options) && options.curry,      forceFixed = ('fixed' in options) && options.fixed,      forceRearg = ('rearg' in options) && options.rearg,      pristine = isLib ? func.runInContext() : undefined;  var helpers = isLib ? func : {    'ary': util.ary,    'assign': util.assign,    'clone': util.clone,    'curry': util.curry,    'forEach': util.forEach,    'isArray': util.isArray,    'isError': util.isError,    'isFunction': util.isFunction,    'isWeakMap': util.isWeakMap,    'iteratee': util.iteratee,    'keys': util.keys,    'rearg': util.rearg,    'toInteger': util.toInteger,    'toPath': util.toPath  };  var ary = helpers.ary,      assign = helpers.assign,      clone = helpers.clone,      curry = helpers.curry,      each = helpers.forEach,      isArray = helpers.isArray,      isError = helpers.isError,      isFunction = helpers.isFunction,      isWeakMap = helpers.isWeakMap,      keys = helpers.keys,      rearg = helpers.rearg,      toInteger = helpers.toInteger,      toPath = helpers.toPath;  var aryMethodKeys = keys(mapping.aryMethod);  var wrappers = {    'castArray': function(castArray) {      return function() {        var value = arguments[0];        return isArray(value)          ? castArray(cloneArray(value))          : castArray.apply(undefined, arguments);      };    },    'iteratee': function(iteratee) {      return function() {        var func = arguments[0],            arity = arguments[1],            result = iteratee(func, arity),            length = result.length;        if (config.cap && typeof arity == 'number') {          arity = arity > 2 ? (arity - 2) : 1;          return (length && length <= arity) ? result : baseAry(result, arity);        }        return result;      };    },    'mixin': function(mixin) {      return function(source) {        var func = this;        if (!isFunction(func)) {          return mixin(func, Object(source));        }        var pairs = [];        each(keys(source), function(key) {          if (isFunction(source[key])) {            pairs.push([key, func.prototype[key]]);          }        });        mixin(func, Object(source));        each(pairs, function(pair) {          var value = pair[1];          if (isFunction(value)) {            func.prototype[pair[0]] = value;          } else {            delete func.prototype[pair[0]];          }        });        return func;      };    },    'nthArg': function(nthArg) {      return function(n) {        var arity = n < 0 ? 1 : (toInteger(n) + 1);        return curry(nthArg(n), arity);      };    },    'rearg': function(rearg) {      return function(func, indexes) {        var arity = indexes ? indexes.length : 0;        return curry(rearg(func, indexes), arity);      };    },    'runInContext': function(runInContext) {      return function(context) {        return baseConvert(util, runInContext(context), options);      };    }  };  /*--------------------------------------------------------------------------*/  /**   * Casts `func` to a function with an arity capped iteratee if needed.   *   * @private   * @param {string} name The name of the function to inspect.   * @param {Function} func The function to inspect.   * @returns {Function} Returns the cast function.   */  function castCap(name, func) {    if (config.cap) {      var indexes = mapping.iterateeRearg[name];      if (indexes) {        return iterateeRearg(func, indexes);      }      var n = !isLib && mapping.iterateeAry[name];      if (n) {        return iterateeAry(func, n);      }    }    return func;  }  /**   * Casts `func` to a curried function if needed.   *   * @private   * @param {string} name The name of the function to inspect.   * @param {Function} func The function to inspect.   * @param {number} n The arity of `func`.   * @returns {Function} Returns the cast function.   */  function castCurry(name, func, n) {    return (forceCurry || (config.curry && n > 1))      ? curry(func, n)      : func;  }  /**   * Casts `func` to a fixed arity function if needed.   *   * @private   * @param {string} name The name of the function to inspect.   * @param {Function} func The function to inspect.   * @param {number} n The arity cap.   * @returns {Function} Returns the cast function.   */  function castFixed(name, func, n) {    if (config.fixed && (forceFixed || !mapping.skipFixed[name])) {      var data = mapping.methodSpread[name],          start = data && data.start;      return start  === undefined ? ary(func, n) : flatSpread(func, start);    }    return func;  }  /**   * Casts `func` to an rearged function if needed.   *   * @private   * @param {string} name The name of the function to inspect.   * @param {Function} func The function to inspect.   * @param {number} n The arity of `func`.   * @returns {Function} Returns the cast function.   */  function castRearg(name, func, n) {    return (config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name]))      ? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n])      : func;  }  /**   * Creates a clone of `object` by `path`.   *   * @private   * @param {Object} object The object to clone.   * @param {Array|string} path The path to clone by.   * @returns {Object} Returns the cloned object.   */  function cloneByPath(object, path) {    path = toPath(path);    var index = -1,        length = path.length,        lastIndex = length - 1,        result = clone(Object(object)),        nested = result;    while (nested != null && ++index < length) {      var key = path[index],          value = nested[key];      if (value != null &&          !(isFunction(value) || isError(value) || isWeakMap(value))) {        nested[key] = clone(index == lastIndex ? value : Object(value));      }      nested = nested[key];    }    return result;  }  /**   * Converts `lodash` to an immutable auto-curried iteratee-first data-last   * version with conversion `options` applied.   *   * @param {Object} [options] The options object. See `baseConvert` for more details.   * @returns {Function} Returns the converted `lodash`.   */  function convertLib(options) {    return _.runInContext.convert(options)(undefined);  }  /**   * Create a converter function for `func` of `name`.   *   * @param {string} name The name of the function to convert.   * @param {Function} func The function to convert.   * @returns {Function} Returns the new converter function.   */  function createConverter(name, func) {    var realName = mapping.aliasToReal[name] || name,        methodName = mapping.remap[realName] || realName,        oldOptions = options;    return function(options) {      var newUtil = isLib ? pristine : helpers,          newFunc = isLib ? pristine[methodName] : func,          newOptions = assign(assign({}, oldOptions), options);      return baseConvert(newUtil, realName, newFunc, newOptions);    };  }  /**   * Creates a function that wraps `func` to invoke its iteratee, with up to `n`   * arguments, ignoring any additional arguments.   *   * @private   * @param {Function} func The function to cap iteratee arguments for.   * @param {number} n The arity cap.   * @returns {Function} Returns the new function.   */  function iterateeAry(func, n) {    return overArg(func, function(func) {      return typeof func == 'function' ? baseAry(func, n) : func;    });  }  /**   * Creates a function that wraps `func` to invoke its iteratee with arguments   * arranged according to the specified `indexes` where the argument value at   * the first index is provided as the first argument, the argument value at   * the second index is provided as the second argument, and so on.   *   * @private   * @param {Function} func The function to rearrange iteratee arguments for.   * @param {number[]} indexes The arranged argument indexes.   * @returns {Function} Returns the new function.   */  function iterateeRearg(func, indexes) {    return overArg(func, function(func) {      var n = indexes.length;      return baseArity(rearg(baseAry(func, n), indexes), n);    });  }  /**   * Creates a function that invokes `func` with its first argument transformed.   *   * @private   * @param {Function} func The function to wrap.   * @param {Function} transform The argument transform.   * @returns {Function} Returns the new function.   */  function overArg(func, transform) {    return function() {      var length = arguments.length;      if (!length) {        return func();      }      var args = Array(length);      while (length--) {        args[length] = arguments[length];      }      var index = config.rearg ? 0 : (length - 1);      args[index] = transform(args[index]);      return func.apply(undefined, args);    };  }  /**   * Creates a function that wraps `func` and applys the conversions   * rules by `name`.   *   * @private   * @param {string} name The name of the function to wrap.   * @param {Function} func The function to wrap.   * @returns {Function} Returns the converted function.   */  function wrap(name, func, placeholder) {    var result,        realName = mapping.aliasToReal[name] || name,        wrapped = func,        wrapper = wrappers[realName];    if (wrapper) {      wrapped = wrapper(func);    }    else if (config.immutable) {      if (mapping.mutate.array[realName]) {        wrapped = wrapImmutable(func, cloneArray);      }      else if (mapping.mutate.object[realName]) {        wrapped = wrapImmutable(func, createCloner(func));      }      else if (mapping.mutate.set[realName]) {        wrapped = wrapImmutable(func, cloneByPath);      }    }    each(aryMethodKeys, function(aryKey) {      each(mapping.aryMethod[aryKey], function(otherName) {        if (realName == otherName) {          var data = mapping.methodSpread[realName],              afterRearg = data && data.afterRearg;          result = afterRearg            ? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey)            : castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey);          result = castCap(realName, result);          result = castCurry(realName, result, aryKey);          return false;        }      });      return !result;    });    result || (result = wrapped);    if (result == func) {      result = forceCurry ? curry(result, 1) : function() {        return func.apply(this, arguments);      };    }    result.convert = createConverter(realName, func);    result.placeholder = func.placeholder = placeholder;    return result;  }  /*--------------------------------------------------------------------------*/  if (!isObj) {    return wrap(name, func, defaultHolder);  }  var _ = func;  // Convert methods by ary cap.  var pairs = [];  each(aryMethodKeys, function(aryKey) {    each(mapping.aryMethod[aryKey], function(key) {      var func = _[mapping.remap[key] || key];      if (func) {        pairs.push([key, wrap(key, func, _)]);      }    });  });  // Convert remaining methods.  each(keys(_), function(key) {    var func = _[key];    if (typeof func == 'function') {      var length = pairs.length;      while (length--) {        if (pairs[length][0] == key) {          return;        }      }      func.convert = createConverter(key, func);      pairs.push([key, func]);    }  });  // Assign to `_` leaving `_.prototype` unchanged to allow chaining.  each(pairs, function(pair) {    _[pair[0]] = pair[1];  });  _.convert = convertLib;  _.placeholder = _;  // Assign aliases.  each(keys(_), function(key) {    each(mapping.realToAlias[key] || [], function(alias) {      _[alias] = _[key];    });  });  return _;}module.exports = baseConvert;
 |