UNPKG

minifyify

Version:

Minify your browserify bundles without losing the sourcemap

1,542 lines (1,414 loc) 187 kB
;(function(window) { /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; /** Used to pool arrays and objects used internally */ var arrayPool = [], objectPool = []; /** Used to generate unique IDs */ var idCounter = 0; /** Used internally to indicate various things */ var indicatorObject = {}; /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */ var keyPrefix = +new Date + ''; /** Used as the size when optimizations are enabled for large arrays */ var largeArraySize = 75; /** Used as the max size of the `arrayPool` and `objectPool` */ var maxPoolSize = 40; /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities */ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g; /** * Used to match ES6 template delimiters * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6 */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match regexp flags from their coerced string values */ var reFlags = /\w*$/; /** Used to match "interpolate" template delimiters */ var reInterpolate = /<%=([\s\S]+?)%>/g; /** Used to detect functions containing a `this` reference */ var reThis = (reThis = /\bthis\b/) && reThis.test(runInContext) && reThis; /** Used to detect and test whitespace */ var whitespace = ( // whitespace ' \t\x0B\f\xA0\ufeff' + // line terminators '\n\r\u2028\u2029' + // unicode category "Zs" space separators '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to match leading whitespace and zeros to be removed */ var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)'); /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; /** Used to match HTML characters */ var reUnescapedHtml = /[&<>"']/g; /** Used to match unescaped characters in compiled string literals */ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; /** Used to assign default `context` object properties */ var contextProps = [ 'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object', 'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN', 'parseInt', 'setImmediate', 'setTimeout' ]; /** Used to make template sourceURLs easier to identify */ var templateCounter = 0; /** `Object#toString` result shortcuts */ var argsClass = '[object Arguments]', arrayClass = '[object Array]', boolClass = '[object Boolean]', dateClass = '[object Date]', errorClass = '[object Error]', funcClass = '[object Function]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', stringClass = '[object String]'; /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; cloneableClasses[funcClass] = false; cloneableClasses[argsClass] = cloneableClasses[arrayClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; /** Used to determine if values are of the language type Object */ var objectTypes = { 'boolean': false, 'function': true, 'object': true, 'number': false, 'string': false, 'undefined': false }; /** Used to escape characters for inclusion in compiled string literals */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', '\t': 't', '\u2028': 'u2028', '\u2029': 'u2029' }; /** Detect free variable `exports` */ var freeExports = objectTypes[typeof exports] && exports; /** Detect free variable `module` */ var freeModule = objectTypes[typeof module] && module && module.exports == freeExports && module; /** Detect free variable `global`, from Node.js or Browserified code, and use it as `window` */ var freeGlobal = objectTypes[typeof global] && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) { window = freeGlobal; } /*--------------------------------------------------------------------------*/ /** * A basic implementation of `_.indexOf` without support for binary searches * or `fromIndex` constraints. * * @private * @param {Array} array The array to search. * @param {Mixed} value The value to search for. * @param {Number} [fromIndex=0] The index to search from. * @returns {Number} Returns the index of the matched value or `-1`. */ function basicIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, length = array.length; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** * An implementation of `_.contains` for cache objects that mimics the return * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. * * @private * @param {Object} cache The cache object to inspect. * @param {Mixed} value The value to search for. * @returns {Number} Returns `0` if `value` is found, else `-1`. */ function cacheIndexOf(cache, value) { var type = typeof value; cache = cache.cache; if (type == 'boolean' || value == null) { return cache[value]; } if (type != 'number' && type != 'string') { type = 'object'; } var key = type == 'number' ? value : keyPrefix + value; cache = cache[type] || (cache[type] = {}); return type == 'object' ? (cache[key] && basicIndexOf(cache[key], value) > -1 ? 0 : -1) : (cache[key] ? 0 : -1); } /** * Adds a given `value` to the corresponding cache object. * * @private * @param {Mixed} value The value to add to the cache. */ function cachePush(value) { var cache = this.cache, type = typeof value; if (type == 'boolean' || value == null) { cache[value] = true; } else { if (type != 'number' && type != 'string') { type = 'object'; } var key = type == 'number' ? value : keyPrefix + value, typeCache = cache[type] || (cache[type] = {}); if (type == 'object') { if ((typeCache[key] || (typeCache[key] = [])).push(value) == this.array.length) { cache[type] = false; } } else { typeCache[key] = true; } } } /** * Used by `_.max` and `_.min` as the default `callback` when a given * `collection` is a string value. * * @private * @param {String} value The character to inspect. * @returns {Number} Returns the code unit of given character. */ function charAtCallback(value) { return value.charCodeAt(0); } /** * Used by `sortBy` to compare transformed `collection` values, stable sorting * them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. * @returns {Number} Returns the sort order indicator of `1` or `-1`. */ function compareAscending(a, b) { var ai = a.index, bi = b.index; a = a.criteria; b = b.criteria; // ensure a stable sort in V8 and other engines // http://code.google.com/p/v8/issues/detail?id=90 if (a !== b) { if (a > b || typeof a == 'undefined') { return 1; } if (a < b || typeof b == 'undefined') { return -1; } } return ai < bi ? -1 : 1; } /** * Creates a cache object to optimize linear searches of large arrays. * * @private * @param {Array} [array=[]] The array to search. * @returns {Null|Object} Returns the cache object or `null` if caching should not be used. */ function createCache(array) { var index = -1, length = array.length; var cache = getObject(); cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false; var result = getObject(); result.array = array; result.cache = cache; result.push = cachePush; while (++index < length) { result.push(array[index]); } return cache.object === false ? (releaseObject(result), null) : result; } /** * Used by `template` to escape characters for inclusion in compiled * string literals. * * @private * @param {String} match The matched character to escape. * @returns {String} Returns the escaped character. */ function escapeStringChar(match) { return '\\' + stringEscapes[match]; } /** * Gets an array from the array pool or creates a new one if the pool is empty. * * @private * @returns {Array} The array from the pool. */ function getArray() { return arrayPool.pop() || []; } /** * Gets an object from the object pool or creates a new one if the pool is empty. * * @private * @returns {Object} The object from the pool. */ function getObject() { return objectPool.pop() || { 'array': null, 'cache': null, 'criteria': null, 'false': false, 'index': 0, 'leading': false, 'maxWait': 0, 'null': false, 'number': null, 'object': null, 'push': null, 'string': null, 'trailing': false, 'true': false, 'undefined': false, 'value': null }; } /** * A no-operation function. * * @private */ function noop() { // no operation performed } /** * Releases the given `array` back to the array pool. * * @private * @param {Array} [array] The array to release. */ function releaseArray(array) { array.length = 0; if (arrayPool.length < maxPoolSize) { arrayPool.push(array); } } /** * Releases the given `object` back to the object pool. * * @private * @param {Object} [object] The object to release. */ function releaseObject(object) { var cache = object.cache; if (cache) { releaseObject(cache); } object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null; if (objectPool.length < maxPoolSize) { objectPool.push(object); } } /** * Slices the `collection` from the `start` index up to, but not including, * the `end` index. * * Note: This function is used, instead of `Array#slice`, to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @private * @param {Array|Object|String} collection The collection to slice. * @param {Number} start The start index. * @param {Number} end The end index. * @returns {Array} Returns the new array. */ function slice(array, start, end) { start || (start = 0); if (typeof end == 'undefined') { end = array ? array.length : 0; } var index = -1, length = end - start || 0, result = Array(length < 0 ? 0 : length); while (++index < length) { result[index] = array[start + index]; } return result; } /*--------------------------------------------------------------------------*/ /** * Create a new `lodash` function using the given `context` object. * * @static * @memberOf _ * @category Utilities * @param {Object} [context=window] The context object. * @returns {Function} Returns the `lodash` function. */ function runInContext(context) { // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. // See http://es5.github.com/#x11.1.5. context = context ? _.defaults(window.Object(), context, _.pick(window, contextProps)) : window; /** Native constructor references */ var Array = context.Array, Boolean = context.Boolean, Date = context.Date, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; /** * Used for `Array` method references. * * Normally `Array.prototype` would suffice, however, using an array literal * avoids issues in Narwhal. */ var arrayRef = []; /** Used for native method references */ var objectProto = Object.prototype, stringProto = String.prototype; /** Used to restore the original `_` reference in `noConflict` */ var oldDash = context._; /** Used to detect if a method is native */ var reNative = RegExp('^' + String(objectProto.valueOf) .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') .replace(/valueOf|for [^\]]+/g, '.+?') + '$' ); /** Native method shortcuts */ var ceil = Math.ceil, clearTimeout = context.clearTimeout, concat = arrayRef.concat, floor = Math.floor, fnToString = Function.prototype.toString, getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, hasOwnProperty = objectProto.hasOwnProperty, push = arrayRef.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, setImmediate = context.setImmediate, setTimeout = context.setTimeout, toString = objectProto.toString; /* Native method shortcuts for methods with the same name as other `lodash` methods */ var nativeBind = reNative.test(nativeBind = toString.bind) && nativeBind, nativeCreate = reNative.test(nativeCreate = Object.create) && nativeCreate, nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = context.isFinite, nativeIsNaN = context.isNaN, nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys, nativeMax = Math.max, nativeMin = Math.min, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeSlice = arrayRef.slice; /** Detect various environments */ var isIeOpera = reNative.test(context.attachEvent), isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera); /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; ctorByClass[arrayClass] = Array; ctorByClass[boolClass] = Boolean; ctorByClass[dateClass] = Date; ctorByClass[funcClass] = Function; ctorByClass[objectClass] = Object; ctorByClass[numberClass] = Number; ctorByClass[regexpClass] = RegExp; ctorByClass[stringClass] = String; /*--------------------------------------------------------------------------*/ /** * Creates a `lodash` object, which wraps the given `value`, to enable method * chaining. * * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * * Chaining is supported in custom builds as long as the `value` method is * implicitly or explicitly included in the build. * * The chainable wrapper functions are: * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, * `compose`, `concat`, `countBy`, `createCallback`, `debounce`, `defaults`, * `defer`, `delay`, `difference`, `filter`, `flatten`, `forEach`, `forIn`, * `forOwn`, `functions`, `groupBy`, `initial`, `intersection`, `invert`, * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`, * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `push`, `range`, * `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, * `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`, * `unzip`, `values`, `where`, `without`, `wrap`, and `zip` * * The non-chainable wrapper functions are: * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, * `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, * `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, * `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, * `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`, * `sortedIndex`, `runInContext`, `template`, `unescape`, `uniqueId`, and `value` * * The wrapper functions `first` and `last` return wrapped values when `n` is * passed, otherwise they return unwrapped values. * * @name _ * @constructor * @alias chain * @category Chaining * @param {Mixed} value The value to wrap in a `lodash` instance. * @returns {Object} Returns a `lodash` instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value * wrapped.reduce(function(sum, num) { * return sum + num; * }); * // => 6 * * // returns a wrapped value * var squares = wrapped.map(function(num) { * return num * num; * }); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash(value) { // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__')) ? value : new lodashWrapper(value); } /** * A fast path for creating `lodash` wrapper objects. * * @private * @param {Mixed} value The value to wrap in a `lodash` instance. * @returns {Object} Returns a `lodash` instance. */ function lodashWrapper(value) { this.__wrapped__ = value; } // ensure `new lodashWrapper` is an instance of `lodash` lodashWrapper.prototype = lodash.prototype; /** * An object used to flag environments features. * * @static * @memberOf _ * @type Object */ var support = lodash.support = {}; /** * Detect if `Function#bind` exists and is inferred to be fast (all but V8). * * @memberOf _.support * @type Boolean */ support.fastBind = nativeBind && !isV8; /** * By default, the template delimiters used by Lo-Dash are similar to those in * embedded Ruby (ERB). Change the following template settings to use alternative * delimiters. * * @static * @memberOf _ * @type Object */ lodash.templateSettings = { /** * Used to detect `data` property values to be HTML-escaped. * * @memberOf _.templateSettings * @type RegExp */ 'escape': /<%-([\s\S]+?)%>/g, /** * Used to detect code to be evaluated. * * @memberOf _.templateSettings * @type RegExp */ 'evaluate': /<%([\s\S]+?)%>/g, /** * Used to detect `data` property values to inject. * * @memberOf _.templateSettings * @type RegExp */ 'interpolate': reInterpolate, /** * Used to reference the data object in the template text. * * @memberOf _.templateSettings * @type String */ 'variable': '', /** * Used to import variables into the compiled template. * * @memberOf _.templateSettings * @type Object */ 'imports': { /** * A reference to the `lodash` function. * * @memberOf _.templateSettings.imports * @type Function */ '_': lodash } }; /*--------------------------------------------------------------------------*/ /** * Creates a function that, when called, invokes `func` with the `this` binding * of `thisArg` and prepends any `partialArgs` to the arguments passed to the * bound function. * * @private * @param {Function|String} func The function to bind or the method name. * @param {Mixed} [thisArg] The `this` binding of `func`. * @param {Array} partialArgs An array of arguments to be partially applied. * @param {Object} [idicator] Used to indicate binding by key or partially * applying arguments from the right. * @returns {Function} Returns the new bound function. */ function createBound(func, thisArg, partialArgs, indicator) { var isFunc = isFunction(func), isPartial = !partialArgs, key = thisArg; // juggle arguments if (isPartial) { var rightIndicator = indicator; partialArgs = thisArg; } else if (!isFunc) { if (!indicator) { throw new TypeError; } thisArg = func; } function bound() { // `Function#bind` spec // http://es5.github.com/#x15.3.4.5 var args = arguments, thisBinding = isPartial ? this : thisArg; if (!isFunc) { func = thisArg[key]; } if (partialArgs.length) { args = args.length ? (args = nativeSlice.call(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args)) : partialArgs; } if (this instanceof bound) { // ensure `new bound` is an instance of `func` thisBinding = createObject(func.prototype); // mimic the constructor's `return` behavior // http://es5.github.com/#x13.2.2 var result = func.apply(thisBinding, args); return isObject(result) ? result : thisBinding; } return func.apply(thisBinding, args); } return bound; } /** * Creates a new object with the specified `prototype`. * * @private * @param {Object} prototype The prototype object. * @returns {Object} Returns the new object. */ function createObject(prototype) { return isObject(prototype) ? nativeCreate(prototype) : {}; } /** * Used by `escape` to convert characters to HTML entities. * * @private * @param {String} match The matched character to escape. * @returns {String} Returns the escaped character. */ function escapeHtmlChar(match) { return htmlEscapes[match]; } /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized, this method returns the custom method, otherwise it returns * the `basicIndexOf` function. * * @private * @returns {Function} Returns the "indexOf" function. */ function getIndexOf(array, value, fromIndex) { var result = (result = lodash.indexOf) === indexOf ? basicIndexOf : result; return result; } /** * Creates a function that juggles arguments, allowing argument overloading * for `_.flatten` and `_.uniq`, before passing them to the given `func`. * * @private * @param {Function} func The function to wrap. * @returns {Function} Returns the new function. */ function overloadWrapper(func) { return function(array, flag, callback, thisArg) { // juggle arguments if (typeof flag != 'boolean' && flag != null) { thisArg = callback; callback = !(thisArg && thisArg[flag] === array) ? flag : undefined; flag = false; } if (callback != null) { callback = lodash.createCallback(callback, thisArg); } return func(array, flag, callback, thisArg); }; } /** * A fallback implementation of `isPlainObject` which checks if a given `value` * is an object created by the `Object` constructor, assuming objects created * by the `Object` constructor have no inherited enumerable properties and that * there are no `Object.prototype` extensions. * * @private * @param {Mixed} value The value to check. * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { var ctor, result; // avoid non Object objects, `arguments` objects, and DOM elements if (!(value && toString.call(value) == objectClass) || (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) { return false; } // In most environments an object's own properties are iterated before // its inherited properties. If the last iterated property is an object's // own property then there are no inherited enumerable properties. forIn(value, function(value, key) { result = key; }); return result === undefined || hasOwnProperty.call(value, result); } /** * Used by `unescape` to convert HTML entities to characters. * * @private * @param {String} match The matched character to unescape. * @returns {String} Returns the unescaped character. */ function unescapeHtmlChar(match) { return htmlUnescapes[match]; } /*--------------------------------------------------------------------------*/ /** * Checks if `value` is an `arguments` object. * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to check. * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`. * @example * * (function() { return _.isArguments(arguments); })(1, 2, 3); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { return toString.call(value) == argsClass; } /** * Checks if `value` is an array. * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to check. * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`. * @example * * (function() { return _.isArray(arguments); })(); * // => false * * _.isArray([1, 2, 3]); * // => true */ var isArray = nativeIsArray; /** * A fallback implementation of `Object.keys` which produces an array of the * given object's own enumerable property names. * * @private * @type Function * @param {Object} object The object to inspect. * @returns {Array} Returns a new array of property names. */ var shimKeys = function (object) { var index, iterable = object, result = []; if (!iterable) return result; if (!(objectTypes[typeof object])) return result; for (index in iterable) { if (hasOwnProperty.call(iterable, index)) { result.push(index); } } return result }; /** * Creates an array composed of the own enumerable property names of `object`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. * @returns {Array} Returns a new array of property names. * @example * * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); * // => ['one', 'two', 'three'] (order is not guaranteed) */ var keys = !nativeKeys ? shimKeys : function(object) { if (!isObject(object)) { return []; } return nativeKeys(object); }; /** * Used to convert characters to HTML entities: * * Though the `>` character is escaped for symmetry, characters like `>` and `/` * don't require escaping in HTML and have no special meaning unless they're part * of a tag or an unquoted attribute value. * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") */ var htmlEscapes = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }; /** Used to convert HTML entities to characters */ var htmlUnescapes = invert(htmlEscapes); /*--------------------------------------------------------------------------*/ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources will overwrite property assignments of previous * sources. If a `callback` function is passed, it will be executed to produce * the assigned values. The `callback` is bound to `thisArg` and invoked with * two arguments; (objectValue, sourceValue). * * @static * @memberOf _ * @type Function * @alias extend * @category Objects * @param {Object} object The destination object. * @param {Object} [source1, source2, ...] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. * @example * * _.assign({ 'name': 'moe' }, { 'age': 40 }); * // => { 'name': 'moe', 'age': 40 } * * var defaults = _.partialRight(_.assign, function(a, b) { * return typeof a == 'undefined' ? b : a; * }); * * var food = { 'name': 'apple' }; * defaults(food, { 'name': 'banana', 'type': 'fruit' }); * // => { 'name': 'apple', 'type': 'fruit' } */ var assign = function (object, source, guard) { var index, iterable = object, result = iterable; if (!iterable) return result; var args = arguments, argsIndex = 0, argsLength = typeof guard == 'number' ? 2 : args.length; if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { var callback = lodash.createCallback(args[--argsLength - 1], args[argsLength--], 2); } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { callback = args[--argsLength]; } while (++argsIndex < argsLength) { iterable = args[argsIndex]; if (iterable && objectTypes[typeof iterable]) { var ownIndex = -1, ownProps = objectTypes[typeof iterable] && keys(iterable), length = ownProps ? ownProps.length : 0; while (++ownIndex < length) { index = ownProps[ownIndex]; result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]; } } } return result }; /** * Creates a clone of `value`. If `deep` is `true`, nested objects will also * be cloned, otherwise they will be assigned by reference. If a `callback` * function is passed, it will be executed to produce the cloned values. If * `callback` returns `undefined`, cloning will be handled by the method instead. * The `callback` is bound to `thisArg` and invoked with one argument; (value). * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to clone. * @param {Boolean} [deep=false] A flag to indicate a deep clone. * @param {Function} [callback] The function to customize cloning values. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @param- {Array} [stackA=[]] Tracks traversed source objects. * @param- {Array} [stackB=[]] Associates clones with source counterparts. * @returns {Mixed} Returns the cloned `value`. * @example * * var stooges = [ * { 'name': 'moe', 'age': 40 }, * { 'name': 'larry', 'age': 50 } * ]; * * var shallow = _.clone(stooges); * shallow[0] === stooges[0]; * // => true * * var deep = _.clone(stooges, true); * deep[0] === stooges[0]; * // => false * * _.mixin({ * 'clone': _.partialRight(_.clone, function(value) { * return _.isElement(value) ? value.cloneNode(false) : undefined; * }) * }); * * var clone = _.clone(document.body); * clone.childNodes.length; * // => 0 */ function clone(value, deep, callback, thisArg, stackA, stackB) { var result = value; // allows working with "Collections" methods without using their `callback` // argument, `index|key`, for this method's `callback` if (typeof deep != 'boolean' && deep != null) { thisArg = callback; callback = deep; deep = false; } if (typeof callback == 'function') { callback = (typeof thisArg == 'undefined') ? callback : lodash.createCallback(callback, thisArg, 1); result = callback(result); if (typeof result != 'undefined') { return result; } result = value; } // inspect [[Class]] var isObj = isObject(result); if (isObj) { var className = toString.call(result); if (!cloneableClasses[className]) { return result; } var isArr = isArray(result); } // shallow clone if (!isObj || !deep) { return isObj ? (isArr ? slice(result) : assign({}, result)) : result; } var ctor = ctorByClass[className]; switch (className) { case boolClass: case dateClass: return new ctor(+result); case numberClass: case stringClass: return new ctor(result); case regexpClass: return ctor(result.source, reFlags.exec(result)); } // check for circular references and return corresponding clone var initedStack = !stackA; stackA || (stackA = getArray()); stackB || (stackB = getArray()); var length = stackA.length; while (length--) { if (stackA[length] == value) { return stackB[length]; } } // init cloned object result = isArr ? ctor(result.length) : {}; // add array properties assigned by `RegExp#exec` if (isArr) { if (hasOwnProperty.call(value, 'index')) { result.index = value.index; } if (hasOwnProperty.call(value, 'input')) { result.input = value.input; } } // add the source value to the stack of traversed objects // and associate it with its clone stackA.push(value); stackB.push(result); // recursively populate clone (susceptible to call stack limits) (isArr ? forEach : forOwn)(value, function(objValue, key) { result[key] = clone(objValue, deep, callback, undefined, stackA, stackB); }); if (initedStack) { releaseArray(stackA); releaseArray(stackB); } return result; } /** * Creates a deep clone of `value`. If a `callback` function is passed, * it will be executed to produce the cloned values. If `callback` returns * `undefined`, cloning will be handled by the method instead. The `callback` * is bound to `thisArg` and invoked with one argument; (value). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to deep clone. * @param {Function} [callback] The function to customize cloning values. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @returns {Mixed} Returns the deep cloned `value`. * @example * * var stooges = [ * { 'name': 'moe', 'age': 40 }, * { 'name': 'larry', 'age': 50 } * ]; * * var deep = _.cloneDeep(stooges); * deep[0] === stooges[0]; * // => false * * var view = { * 'label': 'docs', * 'node': element * }; * * var clone = _.cloneDeep(view, function(value) { * return _.isElement(value) ? value.cloneNode(true) : undefined; * }); * * clone.node == view.node; * // => false */ function cloneDeep(value, callback, thisArg) { return clone(value, true, callback, thisArg); } /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property will be ignored. * * @static * @memberOf _ * @type Function * @category Objects * @param {Object} object The destination object. * @param {Object} [source1, source2, ...] The source objects. * @param- {Object} [guard] Allows working with `_.reduce` without using its * callback's `key` and `object` arguments as sources. * @returns {Object} Returns the destination object. * @example * * var food = { 'name': 'apple' }; * _.defaults(food, { 'name': 'banana', 'type': 'fruit' }); * // => { 'name': 'apple', 'type': 'fruit' } */ var defaults = function (object, source, guard) { var index, iterable = object, result = iterable; if (!iterable) return result; var args = arguments, argsIndex = 0, argsLength = typeof guard == 'number' ? 2 : args.length; while (++argsIndex < argsLength) { iterable = args[argsIndex]; if (iterable && objectTypes[typeof iterable]) { var ownIndex = -1, ownProps = objectTypes[typeof iterable] && keys(iterable), length = ownProps ? ownProps.length : 0; while (++ownIndex < length) { index = ownProps[ownIndex]; if (typeof result[index] == 'undefined') result[index] = iterable[index]; } } } return result }; /** * This method is similar to `_.find`, except that it returns the key of the * element that passes the callback check, instead of the element itself. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|String} [callback=identity] The function called per * iteration. If a property name or object is passed, it will be used to create * a "_.pluck" or "_.where" style callback, respectively. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @returns {Mixed} Returns the key of the found element, else `undefined`. * @example * * _.findKey({ 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, function(num) { * return num % 2 == 0; * }); * // => 'b' */ function findKey(object, callback, thisArg) { var result; callback = lodash.createCallback(callback, thisArg); forOwn(object, function(value, key, object) { if (callback(value, key, object)) { result = key; return false; } }); return result; } /** * Iterates over `object`'s own and inherited enumerable properties, executing * the `callback` for each property. The `callback` is bound to `thisArg` and * invoked with three arguments; (value, key, object). Callbacks may exit iteration * early by explicitly returning `false`. * * @static * @memberOf _ * @type Function * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns `object`. * @example * * function Dog(name) { * this.name = name; * } * * Dog.prototype.bark = function() { * alert('Woof, woof!'); * }; * * _.forIn(new Dog('Dagny'), function(value, key) { * alert(key); * }); * // => alerts 'name' and 'bark' (order is not guaranteed) */ var forIn = function (collection, callback, thisArg) { var index, iterable = collection, result = iterable; if (!iterable) return result; if (!objectTypes[typeof iterable]) return result; callback = callback && typeof thisArg == 'undefined' ? callback : lodash.createCallback(callback, thisArg); for (index in iterable) { if (callback(iterable[index], index, collection) === false) return result; } return result }; /** * Iterates over an object's own enumerable properties, executing the `callback` * for each property. The `callback` is bound to `thisArg` and invoked with three * arguments; (value, key, object). Callbacks may exit iteration early by explicitly * returning `false`. * * @static * @memberOf _ * @type Function * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns `object`. * @example * * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { * alert(key); * }); * // => alerts '0', '1', and 'length' (order is not guaranteed) */ var forOwn = function (collection, callback, thisArg) { var index, iterable = collection, result = iterable; if (!iterable) return result; if (!objectTypes[typeof iterable]) return result; callback = callback && typeof thisArg == 'undefined' ? callback : lodash.createCallback(callback, thisArg); var ownIndex = -1, ownProps = objectTypes[typeof iterable] && keys(iterable), length = ownProps ? ownProps.length : 0; while (++ownIndex < length) { index = ownProps[ownIndex]; if (callback(iterable[index], index, collection) === false) return result; } return result }; /** * Creates a sorted array of all enumerable properties, own and inherited, * of `object` that have function values. * * @static * @memberOf _ * @alias methods * @category Objects * @param {Object} object The object to inspect. * @returns {Array} Returns a new array of property names that have function values. * @example * * _.functions(_); * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { var result = []; forIn(object, function(value, key) { if (isFunction(value)) { result.push(key); } }); return result.sort(); } /** * Checks if the specified object `property` exists and is a direct property, * instead of an inherited property. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to check. * @param {String} property The property to check for. * @returns {Boolean} Returns `true` if key is a direct property, else `false`. * @example * * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); * // => true */ function has(object, property) { return object ? hasOwnProperty.call(object, property) : false; } /** * Creates an object composed of the inverted keys and values of the given `object`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to invert. * @returns {Object} Returns the created inverted object. * @example * * _.invert({ 'first': 'moe', 'second': 'larry' }); * // => { 'moe': 'first', 'larry': 'second' } */ function invert(object) { var index = -1, props = keys(object), length = props.length, result = {}; while (++index < length) { var key = props[index]; result[object[key]] = key; } return result; } /** * Checks if `value` is a boolean value. * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to check. * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`. * @example * * _.isBoolean(null); * // => false */ function isBoolean(value) { return value === true || value === false || toString.call(value) == boolClass; } /** * Checks if `value` is a date. * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to check. * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`. * @example * * _.isDate(new Date); * // => true */ function isDate(value) { return value ? (typeof value == 'object' && toString.call(value) == dateClass) : false; } /** * Checks if `value` is a DOM element. * * @static * @memberOf _ * @category Objects * @param {Mixed} value The value to check. * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true */ function isElement(value) { return value ? value.nodeType === 1 : false; } /** * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a * length of `0` and objects with no own enumerable properties are considered * "empty". * * @static * @memberOf _ * @category Objects * @param {Array|Object|String} value The value to inspect. * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`. * @example * * _.isEmpty([1, 2, 3]); * // => false * * _.isEmpty({}); * // => true * * _.isEmpty(''); * // => true */ function isEmpty(value) { var result = true; if (!value) { return result; } var className = toString.call(value), length = value.length; if ((className == arrayClass || className == stringClass || className == argsClass ) || (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { return !length; } forOwn(value, function() { return (result = false); }); return result; } /** * Performs a deep comparison between two values to determine if they are * equivalent to each other. If `callback` is passed, it will be executed to * compare values. If `callback` returns `undefined`, comparisons will be handled * by the method instead. The `callback` is bound to `thisArg` and invoked with * two arguments; (a, b). * * @static * @memberOf _ * @category Objects * @param {Mixed} a The value to compare. * @param {Mixed} b The other value to compare. * @param {Function} [callback] The function to customize comparing values. * @param {Mixed} [thisArg] The `this` binding of `callback`. * @param- {Array} [stackA=[]] Tracks traversed `a` objects. * @param- {Array} [stackB=[]] Tracks traversed `b` objects. * @returns {Boolean} Returns `true`, if the values are equivalent, else `false`. * @example * * var moe = { 'name': 'moe', 'age': 40 }; * var copy = { 'name': 'moe', 'age': 40 }; * * moe == copy; * // => false * * _.isEqual(moe, copy); * // => true * * var words = ['hello', 'goodbye']; * var otherWords = ['hi', 'goodbye']; * * _.isEqual(words, otherWords, function(a, b) { * var reGreet = /^(?:hello|hi)$/i, * aGreet = _.isString(a) && reGreet.test(a), * bGreet = _.isString(b) && reGreet.test(b); * * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; * }); * // => true */ function isEqual(a, b, callback, thisArg, stackA, stackB) { // used to indicate that when comparing objects, `a` has at least the properties of `b` var whereIndicator = callback === indicatorObject; if (typeof callback == 'function' && !whereIndicator) { callback = lodash.createCallback(callback, thisArg, 2); var result = callback(a, b); if (typeof result != 'undefined') { return !!result; } } // exit early for identical values if (a === b) { // treat `+0` vs. `-0` as not equal return a !== 0 || (1 / a == 1 / b); } var type = typeof a, otherType = typeof b; // exit early for unlike primitive values if (a === a && (!a || (type != 'function' && type != 'object')) && (!b || (otherType != 'function' && otherType != 'object'))) { return false; } // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior // http://es5.github.com/#x15.3.4.4 if (a == null || b == null) { return a === b; } // compare [[Class]] names var className = toString.call(a), otherClass = toString.call(b); if (className == argsClass) { className = objectClass; } if (otherClass == argsClass) { otherClass = objectClass; } if (className != otherClass) { return false; } switch (className) { case boolClass: case dateClass: // coerce dates and booleans to numbers, dates to milli