diff --git a/lodash.src.js b/_lodash.js
similarity index 94%
rename from lodash.src.js
rename to _lodash.js
index a87b713ee..2d3ab1a58 100644
--- a/lodash.src.js
+++ b/_lodash.js
@@ -1,6 +1,7 @@
/**
* @license
- * Lo-Dash 3.0.0-pre
+ * Lo-Dash 3.0.0-pre (Custom Build)
+ * Build: `lodash modern -o ./lodash.js`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.7.0
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
@@ -129,12 +130,6 @@
'window', 'WinRTError'
];
- /** Used to fix the JScript `[[DontEnum]]` bug. */
- var shadowProps = [
- 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
- 'toLocaleString', 'toString', 'valueOf'
- ];
-
/** Used to make template sourceURLs easier to identify. */
var templateCounter = -1;
@@ -283,6 +278,183 @@
/*--------------------------------------------------------------------------*/
+ /**
+ * A specialized version of `_.forEach` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * callback shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array.length;
+
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.every` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `_.filter` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.map` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.reduce` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the first element of
+ * `array` as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initFromArray) {
+ var index = -1,
+ length = array.length;
+
+ if (initFromArray && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * callback shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the last element of
+ * `array` as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
+ var length = array.length;
+ if (initFromArray && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.some` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* The base implementation of `compareAscending` which compares values and
* sorts them in ascending order without guaranteeing a stable sort.
@@ -331,6 +503,25 @@
return -1;
}
+ /**
+ * The base implementation of `_.slice` without support for `start` and `end`
+ * arguments.
+ *
+ * @private
+ * @param {Array} array The array to slice.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseSlice(array) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = array[index];
+ }
+ return result;
+ }
+
/**
* The base implementation of `_.sortBy` and `_.sortByAll` which uses `comparer`
* to define the sort order of `array` and replaces criteria objects with their
@@ -495,26 +686,6 @@
return -1;
}
- /**
- * Checks if `value` is a host object in IE < 9.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
- */
- var isHostObject = (function() {
- try {
- Object({ 'toString': 0 } + '');
- } catch(e) {
- return function() { return false; };
- }
- return function(value) {
- // IE < 9 presents many host objects as `Object` objects that can coerce
- // to strings despite having improperly defined `toString` methods.
- return typeof value.toString != 'function' && typeof (value + '') == 'string';
- };
- }());
-
/**
* Checks if `value` is a valid array-like index.
*
@@ -704,9 +875,7 @@
/** Used for native method references. */
var arrayProto = Array.prototype,
- errorProto = Error.prototype,
- objectProto = Object.prototype,
- stringProto = String.prototype;
+ objectProto = Object.prototype;
/** Used to detect DOM support. */
var document = (document = context.window) && document.document;
@@ -800,34 +969,6 @@
/** Used to store function metadata. */
var metaMap = WeakMap && new WeakMap;
- /** Used to lookup a built-in constructor by `toStringTag`. */
- var ctorByTag = {};
- ctorByTag[float32Tag] = context.Float32Array;
- ctorByTag[float64Tag] = context.Float64Array;
- ctorByTag[int8Tag] = context.Int8Array;
- ctorByTag[int16Tag] = context.Int16Array;
- ctorByTag[int32Tag] = context.Int32Array;
- ctorByTag[uint8Tag] = context.Uint8Array;
- ctorByTag[uint8ClampedTag] = context.Uint8ClampedArray;
- ctorByTag[uint16Tag] = context.Uint16Array;
- ctorByTag[uint32Tag] = context.Uint32Array;
-
- /** Used to avoid iterating over non-enumerable properties in IE < 9. */
- var nonEnumProps = {};
- nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
- nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true };
- nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true };
- nonEnumProps[objectTag] = { 'constructor': true };
-
- arrayEach(shadowProps, function(key) {
- for (var tag in nonEnumProps) {
- if (hasOwnProperty.call(nonEnumProps, tag)) {
- var props = nonEnumProps[tag];
- props[key] = hasOwnProperty.call(props, key);
- }
- }
- });
-
/*------------------------------------------------------------------------*/
/**
@@ -850,7 +991,7 @@
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
- * The wrapper functions that support shortcut fusion are:
+ * The wrapper functons that support shortcut fusion are:
* `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `first`,
* `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, `slice`,
* `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `where`
@@ -917,7 +1058,7 @@
return value;
}
if (hasOwnProperty.call(value, '__wrapped__')) {
- return new LodashWrapper(value.__wrapped__, value.__chain__, arrayCopy(value.__actions__));
+ return new LodashWrapper(value.__wrapped__, value.__chain__, baseSlice(value.__actions__));
}
}
return new LodashWrapper(value);
@@ -947,44 +1088,6 @@
var support = lodash.support = {};
(function(x) {
- var Ctor = function() { this.x = 1; },
- object = { '0': 1, 'length': 1 },
- props = [];
-
- Ctor.prototype = { 'valueOf': 1, 'y': 1 };
- for (var key in new Ctor) { props.push(key); }
-
- /**
- * Detect if the `toStringTag` of `arguments` objects is resolvable
- * (all but Firefox < 4, IE < 9).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.argsTag = objToString.call(arguments) == argsTag;
-
- /**
- * Detect if `name` or `message` properties of `Error.prototype` are
- * enumerable by default (IE < 9, Safari < 5.1).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') ||
- propertyIsEnumerable.call(errorProto, 'name');
-
- /**
- * Detect if `prototype` properties are enumerable by default.
- *
- * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
- * (if the prototype or a property on the prototype has been set)
- * incorrectly set the `[[Enumerable]]` value of a function's `prototype`
- * property to `true`.
- *
- * @memberOf _.support
- * @type boolean
- */
- support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype');
/**
* Detect if functions can be decompiled by `Function#toString`
@@ -1004,69 +1107,6 @@
*/
support.funcNames = typeof Function.name == 'string';
- /**
- * Detect if the `toStringTag` of DOM nodes is resolvable (all but IE < 9).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.nodeTag = objToString.call(document) != objectTag;
-
- /**
- * Detect if string indexes are non-enumerable
- * (IE < 9, RingoJS, Rhino, Narwhal).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.nonEnumStrings = !propertyIsEnumerable.call('x', 0);
-
- /**
- * Detect if properties shadowing those on `Object.prototype` are
- * non-enumerable.
- *
- * In IE < 9 an object's own properties, shadowing non-enumerable ones,
- * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.nonEnumShadows = !/valueOf/.test(props);
-
- /**
- * Detect if own properties are iterated after inherited properties (IE < 9).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.ownLast = props[0] != 'x';
-
- /**
- * Detect if `Array#shift` and `Array#splice` augment array-like objects
- * correctly.
- *
- * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array `shift()`
- * and `splice()` functions that fail to remove the last element, `value[0]`,
- * of array-like objects even though the `length` property is set to `0`.
- * The `shift()` method is buggy in compatibility modes of IE 8, while `splice()`
- * is buggy regardless of mode in IE < 9.
- *
- * @memberOf _.support
- * @type boolean
- */
- support.spliceObjects = (splice.call(object, 0, 1), !object[0]);
-
- /**
- * Detect lack of support for accessing string characters by index.
- *
- * IE < 8 can't access characters by index. IE 8 can only access characters
- * by index on string literals, not string objects.
- *
- * @memberOf _.support
- * @type boolean
- */
- support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
-
/**
* Detect if the DOM is supported.
*
@@ -1192,13 +1232,13 @@
views = this.views,
result = new LazyWrapper(this.wrapped);
- result.actions = actions ? arrayCopy(actions) : null;
+ result.actions = actions ? baseSlice(actions) : null;
result.dir = this.dir;
result.dropCount = this.dropCount;
result.filtered = this.filtered;
- result.iteratees = iteratees ? arrayCopy(iteratees) : null;
+ result.iteratees = iteratees ? baseSlice(iteratees) : null;
result.takeCount = this.takeCount;
- result.views = views ? arrayCopy(views) : null;
+ result.views = views ? baseSlice(views) : null;
return result;
}
@@ -1417,132 +1457,6 @@
return result;
}
- /**
- * Copies the values of `array` to `other`.
- *
- * @private
- * @param {Array} array The array to copy.
- * @param {Array} [other=[]] The array to copy values to.
- * @returns {Array} Returns `other`.
- */
- function arrayCopy(array, other) {
- var index = -1,
- length = array.length,
- result = other || Array(length);
-
- while (++index < length) {
- result[index] = array[index];
- }
- return result;
- }
-
- /**
- * A specialized version of `_.forEach` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
- */
- function arrayEach(array, iteratee) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (iteratee(array[index], index, array) === false) {
- break;
- }
- }
- return array;
- }
-
- /**
- * A specialized version of `_.forEachRight` for arrays without support for
- * callback shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
- */
- function arrayEachRight(array, iteratee) {
- var length = array.length;
-
- while (length--) {
- if (iteratee(array[length], length, array) === false) {
- break;
- }
- }
- return array;
- }
-
- /**
- * A specialized version of `_.every` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if all elements pass the predicate check,
- * else `false`.
- */
- function arrayEvery(array, predicate) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (!predicate(array[index], index, array)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * A specialized version of `_.filter` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {Array} Returns the new filtered array.
- */
- function arrayFilter(array, predicate) {
- var index = -1,
- length = array.length,
- resIndex = -1,
- result = [];
-
- while (++index < length) {
- var value = array[index];
- if (predicate(value, index, array)) {
- result[++resIndex] = value;
- }
- }
- return result;
- }
-
- /**
- * A specialized version of `_.map` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
- */
- function arrayMap(array, iteratee) {
- var index = -1,
- length = array.length,
- result = Array(length);
-
- while (++index < length) {
- result[index] = iteratee(array[index], index, array);
- }
- return result;
- }
-
/**
* A specialized version of `_.max` for arrays without support for iteratees.
*
@@ -1585,76 +1499,6 @@
return result;
}
- /**
- * A specialized version of `_.reduce` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the first element of
- * `array` as the initial value.
- * @returns {*} Returns the accumulated value.
- */
- function arrayReduce(array, iteratee, accumulator, initFromArray) {
- var index = -1,
- length = array.length;
-
- if (initFromArray && length) {
- accumulator = array[++index];
- }
- while (++index < length) {
- accumulator = iteratee(accumulator, array[index], index, array);
- }
- return accumulator;
- }
-
- /**
- * A specialized version of `_.reduceRight` for arrays without support for
- * callback shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the last element of
- * `array` as the initial value.
- * @returns {*} Returns the accumulated value.
- */
- function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
- var length = array.length;
- if (initFromArray && length) {
- accumulator = array[--length];
- }
- while (length--) {
- accumulator = iteratee(accumulator, array[length], length, array);
- }
- return accumulator;
- }
-
- /**
- * A specialized version of `_.some` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if any element passes the predicate check,
- * else `false`.
- */
- function arraySome(array, predicate) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (predicate(array[index], index, array)) {
- return true;
- }
- }
- return false;
- }
-
/**
* Used by `_.defaults` to customize its `_.assign` use.
*
@@ -1789,7 +1633,7 @@
}
// Handle "_.property" and "_.matches" style callback shorthands.
return type == 'object'
- ? baseMatches(func, !argCount)
+ ? baseMatches(func, argCount)
: baseProperty(argCount ? (func + '') : func);
}
@@ -1815,36 +1659,22 @@
if (typeof result != 'undefined') {
return result;
}
- if (!isObject(value)) {
- return value;
- }
var isArr = isArray(value);
+ result = value;
if (isArr) {
- result = initCloneArray(value);
- if (!isDeep) {
- return arrayCopy(value, result);
- }
- } else {
- var tag = objToString.call(value),
- isFunc = tag == funcTag;
-
- if (!lodash.support.argsTag && isArguments(value)) {
- tag = argsTag;
- }
- if (tag == objectTag || (isFunc && !object)) {
- if (isHostObject(value)) {
- return object ? value : {};
- }
- result = initCloneObject(isFunc ? {} : value);
- if (!isDeep) {
- return baseAssign(result, value);
- }
- } else {
- return cloneableTags[tag]
- ? initCloneByTag(value, tag, isDeep)
- : (object ? value : {});
+ result = initArrayClone(value, isDeep);
+ } else if (isObject(value)) {
+ result = initObjectClone(value, isDeep);
+ if (result === null) {
+ isDeep = false;
+ result = {};
+ } else if (isDeep) {
+ isDeep = objToString.call(result) == objectTag;
}
}
+ if (!isDeep || result === value) {
+ return result;
+ }
// Check for circular references and return corresponding clone.
stackA || (stackA = []);
stackB || (stackB = []);
@@ -1900,7 +1730,7 @@
if (!isFunction(func)) {
throw new TypeError(FUNC_ERROR_TEXT);
}
- return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait);
+ return setTimeout(function() { func.apply(undefined, slice(args, fromIndex)); }, wait);
}
/**
@@ -2245,8 +2075,8 @@
* `customizer` functions.
*
* @private
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
+ * @param {*} value The value to compare to `other`.
+ * @param {*} other The value to compare to `value`.
* @param {Function} [customizer] The function to customize comparing values.
* @param {boolean} [isWhere] Specify performing partial comparisons.
* @param {Array} [stackA] Tracks traversed `value` objects.
@@ -2277,8 +2107,8 @@
* objects with circular references to be compared.
*
* @private
- * @param {Array} object The object to compare.
- * @param {Array} other The other object to compare.
+ * @param {Array} object The object to compare to `other`.
+ * @param {Array} other The object to compare to `value`.
* @param {Function} equalFunc The function to determine equivalents of arbitrary values.
* @param {Function} [customizer] The function to customize comparing objects.
* @param {boolean} [isWhere] Specify performing partial comparisons.
@@ -2294,10 +2124,6 @@
othIsArg = othTag == argsTag,
othIsArr = !othIsArg && arrayLikeTags[othTag];
- if (!lodash.support.argsTag) {
- objIsArg = !objIsArr && typeof object.length == 'number' && isArguments(object);
- othIsArg = !othIsArr && typeof other.length == 'number' && isArguments(other);
- }
if (objIsArg) {
object = argsToObject(object);
objTag = objectTag;
@@ -2306,8 +2132,8 @@
other = argsToObject(other);
othTag = objectTag;
}
- var objIsObj = objTag == objectTag && !isHostObject(object),
- othIsObj = othTag == objectTag && !isHostObject(other),
+ var objIsObj = objTag == objectTag,
+ othIsObj = othTag == objectTag,
isSameTag = objTag == othTag;
if (isSameTag && !(objIsArr || objIsObj)) {
@@ -2416,7 +2242,7 @@
/**
* The base implementation of `_.matches` which supports specifying whether
- * `source` should be cloned.
+ * `source` is cloned.
*
* @private
* @param {Object} source The object of property values to match.
@@ -2437,16 +2263,16 @@
};
}
}
- if (isCloned) {
- source = baseClone(source, true);
- }
- var values = Array(length),
+ var notCloned = !isCloned,
+ values = Array(length),
strictCompareFlags = Array(length);
while (length--) {
value = source[props[length]];
- values[length] = value;
- strictCompareFlags[length] = isStrictComparable(value);
+ var isStrict = isStrictComparable(value);
+
+ values[length] = (isStrict || notCloned) ? value : baseClone(value, true, clonePassthru);
+ strictCompareFlags[length] = isStrict;
}
return function(object) {
return baseIsMatch(object, props, values, strictCompareFlags);
@@ -2606,36 +2432,6 @@
return func;
};
- /**
- * The base implementation of `_.slice` without an iteratee call guard.
- *
- * @private
- * @param {Array} array The array to slice.
- * @param {number} [start=0] The start position.
- * @param {number} [end=array.length] The end position.
- * @returns {Array} Returns the slice of `array`.
- */
- function baseSlice(array, start, end) {
- var index = -1,
- length = array.length;
-
- start = start == null ? 0 : (+start || 0);
- if (start < 0) {
- start = -start > length ? 0 : (length + start);
- }
- end = (typeof end == 'undefined' || end > length) ? length : (+end || 0);
- if (end < 0) {
- end += length;
- }
- length = start > end ? 0 : (end - start);
-
- var result = Array(length);
- while (++index < length) {
- result[index] = array[index + start];
- }
- return result;
- }
-
/**
* The base implementation of `_.some` without support for callback shorthands
* or `this` binding.
@@ -2898,6 +2694,18 @@
};
}
+ /**
+ * Used by `_.matches` to clone `source` values, letting uncloneable values
+ * passthu instead of returning empty objects.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @returns {*} Returns the cloned value.
+ */
+ function clonePassthru(value) {
+ return isCloneable(value) ? undefined : value;
+ }
+
/**
* Creates an array that is the composition of partially applied arguments,
* placeholders, and provided arguments into a single array of arguments.
@@ -3179,7 +2987,7 @@
length -= argsHolders.length;
if (length < arity) {
- var newArgPos = argPos ? arrayCopy(argPos) : null,
+ var newArgPos = argPos ? baseSlice(argPos) : null,
newArity = nativeMax(arity - length, 0),
newsHolders = isCurry ? argsHolders : null,
newHoldersRight = isCurry ? null : argsHolders,
@@ -3341,8 +3149,8 @@
* partial deep comparisons.
*
* @private
- * @param {Array} array The array to compare.
- * @param {Array} other The other array to compare.
+ * @param {Array} array The array to compare to `other`.
+ * @param {Array} other The array to compare to `value`.
* @param {Function} equalFunc The function to determine equivalents of arbitrary values.
* @param {Function} [customizer] The function to customize comparing arrays.
* @param {boolean} [isWhere] Specify performing partial comparisons.
@@ -3396,8 +3204,8 @@
* values of `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
*
* @private
- * @param {Object} value The object to compare.
- * @param {Object} other The other object to compare.
+ * @param {Object} value The object to compare to `other`.
+ * @param {Object} other The object to compare to `object`.
* @param {string} tag The `toStringTag` of the objects to compare.
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
*/
@@ -3433,8 +3241,8 @@
* partial deep comparisons.
*
* @private
- * @param {Object} object The object to compare.
- * @param {Object} other The other object to compare.
+ * @param {Object} object The object to compare to `other`.
+ * @param {Object} other The object to compare to `value`.
* @param {Function} equalFunc The function to determine equivalents of arbitrary values.
* @param {Function} [customizer] The function to customize comparing values.
* @param {boolean} [isWhere] Specify performing partial comparisons.
@@ -3591,12 +3399,19 @@
*
* @private
* @param {Array} array The array to clone.
- * @returns {Array} Returns the initialized clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Array} Returns the initialized array clone.
*/
- function initCloneArray(array) {
- var length = array.length,
+ function initArrayClone(array, isDeep) {
+ var index = -1,
+ length = array.length,
result = new array.constructor(length);
+ if (!isDeep) {
+ while (++index < length) {
+ result[index] = array[index];
+ }
+ }
// Add array properties assigned by `RegExp#exec`.
if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
result.index = array.index;
@@ -3610,37 +3425,30 @@
*
* @private
* @param {Object} object The object to clone.
- * @returns {Object} Returns the initialized clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {null|Object} Returns the initialized object clone if an object
+ * is cloneable, else `null`.
*/
- function initCloneObject(object) {
- var Ctor = object.constructor;
- if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
+ function initObjectClone(object, isDeep) {
+ if (!isCloneable(object)) {
+ return null;
+ }
+ var Ctor = object.constructor,
+ tag = objToString.call(object),
+ isArgs = tag == argsTag,
+ isObj = tag == objectTag;
+
+ if (isObj && !(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
Ctor = Object;
}
- return new Ctor;
- }
-
- /**
- * Initializes an object clone based on its `toStringTag`.
- *
- * **Note:** This function only supports cloning values with `toStringTag`
- * values of `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
- *
- *
- * @private
- * @param {Object} object The object to clone.
- * @param {string} tag The `toStringTag` of the object to clone.
- * @param {boolean} [isDeep] Specify a deep clone.
- * @returns {Object} Returns the initialized clone.
- */
- function initCloneByTag(object, tag, isDeep) {
- var Ctor = object.constructor;
- switch (tag) {
- case argsTag:
- var result = new Ctor;
+ if (isArgs || isObj) {
+ var result = isDeep ? new Ctor : baseAssign(new Ctor, object);
+ if (isArgs) {
result.length = object.length;
- return arrayCopy(object, result);
-
+ }
+ return result;
+ }
+ switch (tag) {
case arrayBufferTag:
return bufferClone(object);
@@ -3651,10 +3459,6 @@
case float32Tag: case float64Tag:
case int8Tag: case int16Tag: case int32Tag:
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
- // Safari 5 mobile incorrectly has `Object` as the constructor of typed arrays.
- if (Ctor instanceof Ctor) {
- Ctor = ctorByTag[tag];
- }
var buffer = object.buffer;
return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
@@ -3678,7 +3482,7 @@
*/
function isArrayLike(value) {
return (isObjectLike(value) && isLength(value.length) &&
- (arrayLikeTags[objToString.call(value)] || (!lodash.support.argsTag && isArguments(value)))) || false;
+ (arrayLikeTags[objToString.call(value)])) || false;
}
/**
@@ -3706,6 +3510,17 @@
return result;
}
+ /**
+ * Checks if `value` is cloneable.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is cloneable, else `false`.
+ */
+ function isCloneable(value) {
+ return (value && cloneableTags[objToString.call(value)]) || false;
+ }
+
/**
* Checks if the provided arguments are from an iteratee call.
*
@@ -3801,20 +3616,20 @@
var value = source[3];
if (value) {
var partials = data[3];
- data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
- data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
+ data[3] = partials ? composeArgs(partials, value, source[4]) : baseSlice(value);
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : baseSlice(source[4]);
}
// Compose partial right arguments.
value = source[5];
if (value) {
partials = data[5];
- data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
- data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : baseSlice(value);
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : baseSlice(source[6]);
}
// Use source `argPos` if available.
value = source[7];
if (value) {
- data[7] = arrayCopy(value);
+ data[7] = baseSlice(value);
}
// Use source `ary` if it's smaller.
if (srcBitmask & ARY_FLAG) {
@@ -3889,7 +3704,7 @@
function reorder(array, indexes) {
var arrLength = array.length,
length = nativeMin(indexes.length, arrLength),
- oldArray = arrayCopy(array);
+ oldArray = baseSlice(array);
while (length--) {
var index = indexes[length];
@@ -3944,23 +3759,15 @@
support = lodash.support;
// Exit early for non `Object` objects.
- if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value)) ||
+ if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||
(!hasOwnProperty.call(value, 'constructor') &&
- (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor))) ||
- (!support.argsTag && isArguments(value))) {
+ (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
return false;
}
// IE < 9 iterates inherited properties before own properties. If the first
// iterated property is an object's own property then there are no inherited
// enumerable properties.
var result;
- if (support.ownLast) {
- baseForIn(value, function(subValue, key, object) {
- result = hasOwnProperty.call(object, key);
- return false;
- });
- return result !== 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.
@@ -3985,8 +3792,7 @@
support = lodash.support;
var allowIndexes = length && isLength(length) &&
- (isArray(object) || (support.nonEnumStrings && isString(object)) ||
- (support.nonEnumArgs && isArguments(object)));
+ (isArray(object) || (support.nonEnumArgs && isArguments(object)));
var index = -1,
result = [];
@@ -4014,9 +3820,6 @@
if (!isLength(value.length)) {
return values(value);
}
- if (lodash.support.unindexedChars && isString(value)) {
- return value.split('');
- }
return isObject(value) ? value : Object(value);
}
@@ -4028,16 +3831,6 @@
* @returns {Object} Returns the object.
*/
function toObject(value) {
- if (lodash.support.unindexedChars && isString(value)) {
- var index = -1,
- length = value.length,
- result = Object(value);
-
- while (++index < length) {
- result[index] = value.charAt(index);
- }
- return result;
- }
return isObject(value) ? value : Object(value);
}
@@ -4090,7 +3883,7 @@
result = Array(ceil(length / size));
while (index < length) {
- result[++resIndex] = baseSlice(array, index, (index += size));
+ result[++resIndex] = slice(array, index, (index += size));
}
return result;
}
@@ -4183,14 +3976,10 @@
* // => [1, 2, 3]
*/
function drop(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- return baseSlice(array, n < 0 ? 0 : n);
+ return slice(array, n < 0 ? 0 : n);
}
/**
@@ -4219,15 +4008,11 @@
* // => [1, 2, 3]
*/
function dropRight(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- n = length - (+n || 0);
- return baseSlice(array, 0, n < 0 ? 0 : n);
+ n = array ? (array.length - (+n || 0)) : 0;
+ return slice(array, 0, n < 0 ? 0 : n);
}
/**
@@ -4272,12 +4057,10 @@
*/
function dropRightWhile(array, predicate, thisArg) {
var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
+
predicate = getCallback(predicate, thisArg, 3);
while (length-- && predicate(array[length], length, array)) {}
- return baseSlice(array, 0, length + 1);
+ return slice(array, 0, length + 1);
}
/**
@@ -4321,14 +4104,12 @@
* // => ['pebbles']
*/
function dropWhile(array, predicate, thisArg) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- var index = -1;
+ var index = -1,
+ length = array ? array.length : 0;
+
predicate = getCallback(predicate, thisArg, 3);
while (++index < length && predicate(array[index], index, array)) {}
- return baseSlice(array, index);
+ return slice(array, index);
}
/**
@@ -4850,15 +4631,32 @@
* @returns {Array} Returns the slice of `array`.
*/
function slice(array, start, end) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+ var index = -1,
+ length = array ? array.length : 0,
+ endType = typeof end;
+
+ if (end && endType != 'number' && isIterateeCall(array, start, end)) {
start = 0;
end = length;
}
- return baseSlice(array, start, end);
+ start = start == null ? 0 : (+start || 0);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (endType == 'undefined' || end > length) ? length : (+end || 0);
+ if (end < 0) {
+ end += length;
+ }
+ if (end && end == length && !start) {
+ return baseSlice(array);
+ }
+ length = start > end ? 0 : (end - start);
+
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
}
/**
@@ -4967,14 +4765,10 @@
* // => []
*/
function take(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- return baseSlice(array, 0, n < 0 ? 0 : n);
+ return slice(array, 0, n < 0 ? 0 : n);
}
/**
@@ -5003,15 +4797,11 @@
* // => []
*/
function takeRight(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- n = length - (+n || 0);
- return baseSlice(array, n < 0 ? 0 : n);
+ n = array ? (array.length - (+n || 0)) : 0;
+ return slice(array, n < 0 ? 0 : n);
}
/**
@@ -5056,12 +4846,10 @@
*/
function takeRightWhile(array, predicate, thisArg) {
var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
+
predicate = getCallback(predicate, thisArg, 3);
while (length-- && predicate(array[length], length, array)) {}
- return baseSlice(array, length + 1);
+ return slice(array, length + 1);
}
/**
@@ -5105,14 +4893,12 @@
* // => ['barney', 'fred']
*/
function takeWhile(array, predicate, thisArg) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- var index = -1;
+ var index = -1,
+ length = array ? array.length : 0;
+
predicate = getCallback(predicate, thisArg, 3);
while (++index < length && predicate(array[index], index, array)) {}
- return baseSlice(array, 0, index);
+ return slice(array, 0, index);
}
/**
@@ -5256,7 +5042,7 @@
* // => [2, 3, 4]
*/
function without(array) {
- return baseDifference(array, baseSlice(arguments, 1));
+ return baseDifference(array, slice(arguments, 1));
}
/**
@@ -6005,7 +5791,7 @@
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
- return baseInvoke(collection, methodName, baseSlice(arguments, 2));
+ return baseInvoke(collection, methodName, slice(arguments, 2));
}
/**
@@ -6582,9 +6368,7 @@
if (!length) {
return [];
}
- return (lodash.support.unindexedChars && isString(collection))
- ? collection.split('')
- : arrayCopy(collection);
+ return baseSlice(collection);
}
/**
@@ -6778,7 +6562,7 @@
function bind(func, thisArg) {
var bitmask = BIND_FLAG;
if (arguments.length > 2) {
- var partials = baseSlice(arguments, 2),
+ var partials = slice(arguments, 2),
holders = replaceHolders(partials, bind.placeholder);
bitmask |= PARTIAL_FLAG;
@@ -6867,7 +6651,7 @@
function bindKey(object, key) {
var bitmask = BIND_FLAG | BIND_KEY_FLAG;
if (arguments.length > 2) {
- var partials = baseSlice(arguments, 2),
+ var partials = slice(arguments, 2),
holders = replaceHolders(partials, bindKey.placeholder);
bitmask |= PARTIAL_FLAG;
@@ -7430,7 +7214,7 @@
* // => 'hi fred'
*/
function partial(func) {
- var partials = baseSlice(arguments, 1),
+ var partials = slice(arguments, 1),
holders = replaceHolders(partials, partial.placeholder);
return createWrapper(func, PARTIAL_FLAG, null, partials, holders);
@@ -7468,7 +7252,7 @@
* // => 'hello fred'
*/
function partialRight(func) {
- var partials = baseSlice(arguments, 1),
+ var partials = slice(arguments, 1),
holders = replaceHolders(partials, partialRight.placeholder);
return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders);
@@ -7718,14 +7502,6 @@
var length = isObjectLike(value) ? value.length : undefined;
return (isLength(length) && objToString.call(value) == argsTag) || false;
}
- // Fallback for environments without a `toStringTag` for `arguments` objects.
- if (!support.argsTag) {
- isArguments = function(value) {
- var length = isObjectLike(value) ? value.length : undefined;
- return (isLength(length) && hasOwnProperty.call(value, 'callee') &&
- !propertyIsEnumerable.call(value, 'callee')) || false;
- };
- }
/**
* Checks if `value` is classified as an `Array` object.
@@ -7805,7 +7581,7 @@
*/
function isElement(value) {
return (value && value.nodeType === 1 && isObjectLike(value) &&
- (lodash.support.nodeTag ? objToString.call(value).indexOf('Element') > -1 : isHostObject(value))) || false;
+ objToString.call(value).indexOf('Element') > -1) || false;
}
// Fallback for environments without DOM support.
if (!support.dom) {
@@ -7868,8 +7644,8 @@
* @static
* @memberOf _
* @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
+ * @param {*} value The value to compare to `other`.
+ * @param {*} other The value to compare to `value`.
* @param {Function} [customizer] The function to customize comparing values.
* @param {*} [thisArg] The `this` binding of `customizer`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
@@ -8133,8 +7909,7 @@
if (objToString.call(value) == funcTag) {
return reNative.test(fnToString.call(value));
}
- return (isObjectLike(value) &&
- (isHostObject(value) ? reNative : reHostCtor).test(value)) || false;
+ return (isObjectLike(value) && reHostCtor.test(value)) || false;
}
/**
@@ -8215,7 +7990,7 @@
* // => true
*/
var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
- if (!(value && objToString.call(value) == objectTag) || (!lodash.support.argsTag && isArguments(value))) {
+ if (!(value && objToString.call(value) == objectTag)) {
return false;
}
var valueOf = value.valueOf,
@@ -8243,7 +8018,7 @@
* // => false
*/
function isRegExp(value) {
- return (isObject(value) && objToString.call(value) == regexpTag) || false;
+ return (isObjectLike(value) && objToString.call(value) == regexpTag) || false;
}
/**
@@ -8379,7 +8154,7 @@
if (object == null) {
return object;
}
- var args = arrayCopy(arguments);
+ var args = baseSlice(arguments);
args.push(assignDefaults);
return assign.apply(undefined, args);
}
@@ -8709,7 +8484,7 @@
length = object.length;
}
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
- (typeof object == 'function' ? lodash.support.enumPrototypes : (length && isLength(length)))) {
+ (typeof object != 'function' && (length && isLength(length)))) {
return shimKeys(object);
}
return isObject(object) ? nativeKeys(object) : [];
@@ -8744,54 +8519,25 @@
if (!isObject(object)) {
object = Object(object);
}
- var length = object.length,
- support = lodash.support;
-
+ var length = object.length;
length = (length && isLength(length) &&
- (isArray(object) || (support.nonEnumStrings && isString(object)) ||
- (support.nonEnumArgs && isArguments(object))) && length) || 0;
+ (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;
var Ctor = object.constructor,
index = -1,
- proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto,
- isProto = proto === object,
+ isProto = typeof Ctor == 'function' && Ctor.prototype == object,
result = Array(length),
- skipIndexes = length > 0,
- skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error),
- skipProto = support.enumPrototypes && typeof object == 'function';
+ skipIndexes = length > 0;
while (++index < length) {
- result[index] = (index + '');
+ result[index] = String(index);
}
- // Lo-Dash skips the `constructor` property when it infers it is iterating
- // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]`
- // attribute of an existing property and the `constructor` property of a
- // prototype defaults to non-enumerable.
for (var key in object) {
- if (!(skipProto && key == 'prototype') &&
- !(skipErrorProps && (key == 'message' || key == 'name')) &&
- !(skipIndexes && isIndex(key, length)) &&
+ if (!(skipIndexes && isIndex(key, length)) &&
!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
result.push(key);
}
}
- if (support.nonEnumShadows && object !== objectProto) {
- var tag = object === stringProto ? stringTag : object === errorProto ? errorTag : objToString.call(object),
- nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag];
-
- if (tag == objectTag) {
- proto = objectProto;
- }
- length = shadowProps.length;
- while (length--) {
- key = shadowProps[length];
- var nonEnum = nonEnums[key];
- if (!(isProto && nonEnum) &&
- (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {
- result.push(key);
- }
- }
- }
return result;
}
@@ -10260,7 +10006,7 @@
var chainAll = this.__chain__;
if (chain || chainAll) {
var result = object(this.__wrapped__);
- (result.__actions__ = arrayCopy(this.__actions__)).push({ 'func': func, 'args': arguments, 'thisArg': object });
+ (result.__actions__ = baseSlice(this.__actions__)).push({ 'func': func, 'args': arguments, 'thisArg': object });
result.__chain__ = chainAll;
return result;
}
@@ -10888,21 +10634,10 @@
// Add `Array.prototype` functions to `lodash.prototype`.
arrayEach(['concat', 'join', 'pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
- var arrayFunc = arrayProto[methodName],
+ var func = arrayProto[methodName],
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
- fixObjects = !support.spliceObjects && /^(?:pop|shift|splice)$/.test(methodName),
retUnwrapped = /^(?:join|pop|shift)$/.test(methodName);
- // Avoid array-like object bugs with `Array#shift` and `Array#splice` in
- // IE < 9, Firefox < 10, Narwhal, and RingoJS.
- var func = !fixObjects ? arrayFunc : function() {
- var result = arrayFunc.apply(this, arguments);
- if (this.length === 0) {
- delete this[0];
- }
- return result;
- };
-
lodash.prototype[methodName] = function() {
var args = arguments;
if (retUnwrapped && !this.__chain__) {
diff --git a/lodash.js b/lodash.js
index 2d3ab1a58..a87b713ee 100644
--- a/lodash.js
+++ b/lodash.js
@@ -1,7 +1,6 @@
/**
* @license
- * Lo-Dash 3.0.0-pre (Custom Build)
- * Build: `lodash modern -o ./lodash.js`
+ * Lo-Dash 3.0.0-pre
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.7.0
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
@@ -130,6 +129,12 @@
'window', 'WinRTError'
];
+ /** Used to fix the JScript `[[DontEnum]]` bug. */
+ var shadowProps = [
+ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+ 'toLocaleString', 'toString', 'valueOf'
+ ];
+
/** Used to make template sourceURLs easier to identify. */
var templateCounter = -1;
@@ -278,183 +283,6 @@
/*--------------------------------------------------------------------------*/
- /**
- * A specialized version of `_.forEach` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
- */
- function arrayEach(array, iteratee) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (iteratee(array[index], index, array) === false) {
- break;
- }
- }
- return array;
- }
-
- /**
- * A specialized version of `_.forEachRight` for arrays without support for
- * callback shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
- */
- function arrayEachRight(array, iteratee) {
- var length = array.length;
-
- while (length--) {
- if (iteratee(array[length], length, array) === false) {
- break;
- }
- }
- return array;
- }
-
- /**
- * A specialized version of `_.every` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if all elements pass the predicate check,
- * else `false`.
- */
- function arrayEvery(array, predicate) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (!predicate(array[index], index, array)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * A specialized version of `_.filter` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {Array} Returns the new filtered array.
- */
- function arrayFilter(array, predicate) {
- var index = -1,
- length = array.length,
- resIndex = -1,
- result = [];
-
- while (++index < length) {
- var value = array[index];
- if (predicate(value, index, array)) {
- result[++resIndex] = value;
- }
- }
- return result;
- }
-
- /**
- * A specialized version of `_.map` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
- */
- function arrayMap(array, iteratee) {
- var index = -1,
- length = array.length,
- result = Array(length);
-
- while (++index < length) {
- result[index] = iteratee(array[index], index, array);
- }
- return result;
- }
-
- /**
- * A specialized version of `_.reduce` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the first element of
- * `array` as the initial value.
- * @returns {*} Returns the accumulated value.
- */
- function arrayReduce(array, iteratee, accumulator, initFromArray) {
- var index = -1,
- length = array.length;
-
- if (initFromArray && length) {
- accumulator = array[++index];
- }
- while (++index < length) {
- accumulator = iteratee(accumulator, array[index], index, array);
- }
- return accumulator;
- }
-
- /**
- * A specialized version of `_.reduceRight` for arrays without support for
- * callback shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the last element of
- * `array` as the initial value.
- * @returns {*} Returns the accumulated value.
- */
- function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
- var length = array.length;
- if (initFromArray && length) {
- accumulator = array[--length];
- }
- while (length--) {
- accumulator = iteratee(accumulator, array[length], length, array);
- }
- return accumulator;
- }
-
- /**
- * A specialized version of `_.some` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if any element passes the predicate check,
- * else `false`.
- */
- function arraySome(array, predicate) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (predicate(array[index], index, array)) {
- return true;
- }
- }
- return false;
- }
-
/**
* The base implementation of `compareAscending` which compares values and
* sorts them in ascending order without guaranteeing a stable sort.
@@ -503,25 +331,6 @@
return -1;
}
- /**
- * The base implementation of `_.slice` without support for `start` and `end`
- * arguments.
- *
- * @private
- * @param {Array} array The array to slice.
- * @returns {Array} Returns the slice of `array`.
- */
- function baseSlice(array) {
- var index = -1,
- length = array.length,
- result = Array(length);
-
- while (++index < length) {
- result[index] = array[index];
- }
- return result;
- }
-
/**
* The base implementation of `_.sortBy` and `_.sortByAll` which uses `comparer`
* to define the sort order of `array` and replaces criteria objects with their
@@ -686,6 +495,26 @@
return -1;
}
+ /**
+ * Checks if `value` is a host object in IE < 9.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
+ */
+ var isHostObject = (function() {
+ try {
+ Object({ 'toString': 0 } + '');
+ } catch(e) {
+ return function() { return false; };
+ }
+ return function(value) {
+ // IE < 9 presents many host objects as `Object` objects that can coerce
+ // to strings despite having improperly defined `toString` methods.
+ return typeof value.toString != 'function' && typeof (value + '') == 'string';
+ };
+ }());
+
/**
* Checks if `value` is a valid array-like index.
*
@@ -875,7 +704,9 @@
/** Used for native method references. */
var arrayProto = Array.prototype,
- objectProto = Object.prototype;
+ errorProto = Error.prototype,
+ objectProto = Object.prototype,
+ stringProto = String.prototype;
/** Used to detect DOM support. */
var document = (document = context.window) && document.document;
@@ -969,6 +800,34 @@
/** Used to store function metadata. */
var metaMap = WeakMap && new WeakMap;
+ /** Used to lookup a built-in constructor by `toStringTag`. */
+ var ctorByTag = {};
+ ctorByTag[float32Tag] = context.Float32Array;
+ ctorByTag[float64Tag] = context.Float64Array;
+ ctorByTag[int8Tag] = context.Int8Array;
+ ctorByTag[int16Tag] = context.Int16Array;
+ ctorByTag[int32Tag] = context.Int32Array;
+ ctorByTag[uint8Tag] = context.Uint8Array;
+ ctorByTag[uint8ClampedTag] = context.Uint8ClampedArray;
+ ctorByTag[uint16Tag] = context.Uint16Array;
+ ctorByTag[uint32Tag] = context.Uint32Array;
+
+ /** Used to avoid iterating over non-enumerable properties in IE < 9. */
+ var nonEnumProps = {};
+ nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
+ nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true };
+ nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true };
+ nonEnumProps[objectTag] = { 'constructor': true };
+
+ arrayEach(shadowProps, function(key) {
+ for (var tag in nonEnumProps) {
+ if (hasOwnProperty.call(nonEnumProps, tag)) {
+ var props = nonEnumProps[tag];
+ props[key] = hasOwnProperty.call(props, key);
+ }
+ }
+ });
+
/*------------------------------------------------------------------------*/
/**
@@ -991,7 +850,7 @@
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
- * The wrapper functons that support shortcut fusion are:
+ * The wrapper functions that support shortcut fusion are:
* `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `first`,
* `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, `slice`,
* `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `where`
@@ -1058,7 +917,7 @@
return value;
}
if (hasOwnProperty.call(value, '__wrapped__')) {
- return new LodashWrapper(value.__wrapped__, value.__chain__, baseSlice(value.__actions__));
+ return new LodashWrapper(value.__wrapped__, value.__chain__, arrayCopy(value.__actions__));
}
}
return new LodashWrapper(value);
@@ -1088,6 +947,44 @@
var support = lodash.support = {};
(function(x) {
+ var Ctor = function() { this.x = 1; },
+ object = { '0': 1, 'length': 1 },
+ props = [];
+
+ Ctor.prototype = { 'valueOf': 1, 'y': 1 };
+ for (var key in new Ctor) { props.push(key); }
+
+ /**
+ * Detect if the `toStringTag` of `arguments` objects is resolvable
+ * (all but Firefox < 4, IE < 9).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.argsTag = objToString.call(arguments) == argsTag;
+
+ /**
+ * Detect if `name` or `message` properties of `Error.prototype` are
+ * enumerable by default (IE < 9, Safari < 5.1).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') ||
+ propertyIsEnumerable.call(errorProto, 'name');
+
+ /**
+ * Detect if `prototype` properties are enumerable by default.
+ *
+ * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+ * (if the prototype or a property on the prototype has been set)
+ * incorrectly set the `[[Enumerable]]` value of a function's `prototype`
+ * property to `true`.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype');
/**
* Detect if functions can be decompiled by `Function#toString`
@@ -1107,6 +1004,69 @@
*/
support.funcNames = typeof Function.name == 'string';
+ /**
+ * Detect if the `toStringTag` of DOM nodes is resolvable (all but IE < 9).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.nodeTag = objToString.call(document) != objectTag;
+
+ /**
+ * Detect if string indexes are non-enumerable
+ * (IE < 9, RingoJS, Rhino, Narwhal).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.nonEnumStrings = !propertyIsEnumerable.call('x', 0);
+
+ /**
+ * Detect if properties shadowing those on `Object.prototype` are
+ * non-enumerable.
+ *
+ * In IE < 9 an object's own properties, shadowing non-enumerable ones,
+ * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.nonEnumShadows = !/valueOf/.test(props);
+
+ /**
+ * Detect if own properties are iterated after inherited properties (IE < 9).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.ownLast = props[0] != 'x';
+
+ /**
+ * Detect if `Array#shift` and `Array#splice` augment array-like objects
+ * correctly.
+ *
+ * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array `shift()`
+ * and `splice()` functions that fail to remove the last element, `value[0]`,
+ * of array-like objects even though the `length` property is set to `0`.
+ * The `shift()` method is buggy in compatibility modes of IE 8, while `splice()`
+ * is buggy regardless of mode in IE < 9.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.spliceObjects = (splice.call(object, 0, 1), !object[0]);
+
+ /**
+ * Detect lack of support for accessing string characters by index.
+ *
+ * IE < 8 can't access characters by index. IE 8 can only access characters
+ * by index on string literals, not string objects.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
+
/**
* Detect if the DOM is supported.
*
@@ -1232,13 +1192,13 @@
views = this.views,
result = new LazyWrapper(this.wrapped);
- result.actions = actions ? baseSlice(actions) : null;
+ result.actions = actions ? arrayCopy(actions) : null;
result.dir = this.dir;
result.dropCount = this.dropCount;
result.filtered = this.filtered;
- result.iteratees = iteratees ? baseSlice(iteratees) : null;
+ result.iteratees = iteratees ? arrayCopy(iteratees) : null;
result.takeCount = this.takeCount;
- result.views = views ? baseSlice(views) : null;
+ result.views = views ? arrayCopy(views) : null;
return result;
}
@@ -1457,6 +1417,132 @@
return result;
}
+ /**
+ * Copies the values of `array` to `other`.
+ *
+ * @private
+ * @param {Array} array The array to copy.
+ * @param {Array} [other=[]] The array to copy values to.
+ * @returns {Array} Returns `other`.
+ */
+ function arrayCopy(array, other) {
+ var index = -1,
+ length = array.length,
+ result = other || Array(length);
+
+ while (++index < length) {
+ result[index] = array[index];
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.forEach` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * callback shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array.length;
+
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.every` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `_.filter` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.map` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+
/**
* A specialized version of `_.max` for arrays without support for iteratees.
*
@@ -1499,6 +1585,76 @@
return result;
}
+ /**
+ * A specialized version of `_.reduce` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the first element of
+ * `array` as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initFromArray) {
+ var index = -1,
+ length = array.length;
+
+ if (initFromArray && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * callback shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the last element of
+ * `array` as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
+ var length = array.length;
+ if (initFromArray && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.some` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Used by `_.defaults` to customize its `_.assign` use.
*
@@ -1633,7 +1789,7 @@
}
// Handle "_.property" and "_.matches" style callback shorthands.
return type == 'object'
- ? baseMatches(func, argCount)
+ ? baseMatches(func, !argCount)
: baseProperty(argCount ? (func + '') : func);
}
@@ -1659,21 +1815,35 @@
if (typeof result != 'undefined') {
return result;
}
- var isArr = isArray(value);
- result = value;
- if (isArr) {
- result = initArrayClone(value, isDeep);
- } else if (isObject(value)) {
- result = initObjectClone(value, isDeep);
- if (result === null) {
- isDeep = false;
- result = {};
- } else if (isDeep) {
- isDeep = objToString.call(result) == objectTag;
- }
+ if (!isObject(value)) {
+ return value;
}
- if (!isDeep || result === value) {
- return result;
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return arrayCopy(value, result);
+ }
+ } else {
+ var tag = objToString.call(value),
+ isFunc = tag == funcTag;
+
+ if (!lodash.support.argsTag && isArguments(value)) {
+ tag = argsTag;
+ }
+ if (tag == objectTag || (isFunc && !object)) {
+ if (isHostObject(value)) {
+ return object ? value : {};
+ }
+ result = initCloneObject(isFunc ? {} : value);
+ if (!isDeep) {
+ return baseAssign(result, value);
+ }
+ } else {
+ return cloneableTags[tag]
+ ? initCloneByTag(value, tag, isDeep)
+ : (object ? value : {});
+ }
}
// Check for circular references and return corresponding clone.
stackA || (stackA = []);
@@ -1730,7 +1900,7 @@
if (!isFunction(func)) {
throw new TypeError(FUNC_ERROR_TEXT);
}
- return setTimeout(function() { func.apply(undefined, slice(args, fromIndex)); }, wait);
+ return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait);
}
/**
@@ -2075,8 +2245,8 @@
* `customizer` functions.
*
* @private
- * @param {*} value The value to compare to `other`.
- * @param {*} other The value to compare to `value`.
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize comparing values.
* @param {boolean} [isWhere] Specify performing partial comparisons.
* @param {Array} [stackA] Tracks traversed `value` objects.
@@ -2107,8 +2277,8 @@
* objects with circular references to be compared.
*
* @private
- * @param {Array} object The object to compare to `other`.
- * @param {Array} other The object to compare to `value`.
+ * @param {Array} object The object to compare.
+ * @param {Array} other The other object to compare.
* @param {Function} equalFunc The function to determine equivalents of arbitrary values.
* @param {Function} [customizer] The function to customize comparing objects.
* @param {boolean} [isWhere] Specify performing partial comparisons.
@@ -2124,6 +2294,10 @@
othIsArg = othTag == argsTag,
othIsArr = !othIsArg && arrayLikeTags[othTag];
+ if (!lodash.support.argsTag) {
+ objIsArg = !objIsArr && typeof object.length == 'number' && isArguments(object);
+ othIsArg = !othIsArr && typeof other.length == 'number' && isArguments(other);
+ }
if (objIsArg) {
object = argsToObject(object);
objTag = objectTag;
@@ -2132,8 +2306,8 @@
other = argsToObject(other);
othTag = objectTag;
}
- var objIsObj = objTag == objectTag,
- othIsObj = othTag == objectTag,
+ var objIsObj = objTag == objectTag && !isHostObject(object),
+ othIsObj = othTag == objectTag && !isHostObject(other),
isSameTag = objTag == othTag;
if (isSameTag && !(objIsArr || objIsObj)) {
@@ -2242,7 +2416,7 @@
/**
* The base implementation of `_.matches` which supports specifying whether
- * `source` is cloned.
+ * `source` should be cloned.
*
* @private
* @param {Object} source The object of property values to match.
@@ -2263,16 +2437,16 @@
};
}
}
- var notCloned = !isCloned,
- values = Array(length),
+ if (isCloned) {
+ source = baseClone(source, true);
+ }
+ var values = Array(length),
strictCompareFlags = Array(length);
while (length--) {
value = source[props[length]];
- var isStrict = isStrictComparable(value);
-
- values[length] = (isStrict || notCloned) ? value : baseClone(value, true, clonePassthru);
- strictCompareFlags[length] = isStrict;
+ values[length] = value;
+ strictCompareFlags[length] = isStrictComparable(value);
}
return function(object) {
return baseIsMatch(object, props, values, strictCompareFlags);
@@ -2432,6 +2606,36 @@
return func;
};
+ /**
+ * The base implementation of `_.slice` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseSlice(array, start, end) {
+ var index = -1,
+ length = array.length;
+
+ start = start == null ? 0 : (+start || 0);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (typeof end == 'undefined' || end > length) ? length : (+end || 0);
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : (end - start);
+
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
+ }
+
/**
* The base implementation of `_.some` without support for callback shorthands
* or `this` binding.
@@ -2694,18 +2898,6 @@
};
}
- /**
- * Used by `_.matches` to clone `source` values, letting uncloneable values
- * passthu instead of returning empty objects.
- *
- * @private
- * @param {*} value The value to clone.
- * @returns {*} Returns the cloned value.
- */
- function clonePassthru(value) {
- return isCloneable(value) ? undefined : value;
- }
-
/**
* Creates an array that is the composition of partially applied arguments,
* placeholders, and provided arguments into a single array of arguments.
@@ -2987,7 +3179,7 @@
length -= argsHolders.length;
if (length < arity) {
- var newArgPos = argPos ? baseSlice(argPos) : null,
+ var newArgPos = argPos ? arrayCopy(argPos) : null,
newArity = nativeMax(arity - length, 0),
newsHolders = isCurry ? argsHolders : null,
newHoldersRight = isCurry ? null : argsHolders,
@@ -3149,8 +3341,8 @@
* partial deep comparisons.
*
* @private
- * @param {Array} array The array to compare to `other`.
- * @param {Array} other The array to compare to `value`.
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
* @param {Function} equalFunc The function to determine equivalents of arbitrary values.
* @param {Function} [customizer] The function to customize comparing arrays.
* @param {boolean} [isWhere] Specify performing partial comparisons.
@@ -3204,8 +3396,8 @@
* values of `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
*
* @private
- * @param {Object} value The object to compare to `other`.
- * @param {Object} other The object to compare to `object`.
+ * @param {Object} value The object to compare.
+ * @param {Object} other The other object to compare.
* @param {string} tag The `toStringTag` of the objects to compare.
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
*/
@@ -3241,8 +3433,8 @@
* partial deep comparisons.
*
* @private
- * @param {Object} object The object to compare to `other`.
- * @param {Object} other The object to compare to `value`.
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
* @param {Function} equalFunc The function to determine equivalents of arbitrary values.
* @param {Function} [customizer] The function to customize comparing values.
* @param {boolean} [isWhere] Specify performing partial comparisons.
@@ -3399,19 +3591,12 @@
*
* @private
* @param {Array} array The array to clone.
- * @param {boolean} [isDeep] Specify a deep clone.
- * @returns {Array} Returns the initialized array clone.
+ * @returns {Array} Returns the initialized clone.
*/
- function initArrayClone(array, isDeep) {
- var index = -1,
- length = array.length,
+ function initCloneArray(array) {
+ var length = array.length,
result = new array.constructor(length);
- if (!isDeep) {
- while (++index < length) {
- result[index] = array[index];
- }
- }
// Add array properties assigned by `RegExp#exec`.
if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
result.index = array.index;
@@ -3425,30 +3610,37 @@
*
* @private
* @param {Object} object The object to clone.
- * @param {boolean} [isDeep] Specify a deep clone.
- * @returns {null|Object} Returns the initialized object clone if an object
- * is cloneable, else `null`.
+ * @returns {Object} Returns the initialized clone.
*/
- function initObjectClone(object, isDeep) {
- if (!isCloneable(object)) {
- return null;
- }
- var Ctor = object.constructor,
- tag = objToString.call(object),
- isArgs = tag == argsTag,
- isObj = tag == objectTag;
-
- if (isObj && !(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
+ function initCloneObject(object) {
+ var Ctor = object.constructor;
+ if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
Ctor = Object;
}
- if (isArgs || isObj) {
- var result = isDeep ? new Ctor : baseAssign(new Ctor, object);
- if (isArgs) {
- result.length = object.length;
- }
- return result;
- }
+ return new Ctor;
+ }
+
+ /**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with `toStringTag`
+ * values of `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
switch (tag) {
+ case argsTag:
+ var result = new Ctor;
+ result.length = object.length;
+ return arrayCopy(object, result);
+
case arrayBufferTag:
return bufferClone(object);
@@ -3459,6 +3651,10 @@
case float32Tag: case float64Tag:
case int8Tag: case int16Tag: case int32Tag:
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ // Safari 5 mobile incorrectly has `Object` as the constructor of typed arrays.
+ if (Ctor instanceof Ctor) {
+ Ctor = ctorByTag[tag];
+ }
var buffer = object.buffer;
return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
@@ -3482,7 +3678,7 @@
*/
function isArrayLike(value) {
return (isObjectLike(value) && isLength(value.length) &&
- (arrayLikeTags[objToString.call(value)])) || false;
+ (arrayLikeTags[objToString.call(value)] || (!lodash.support.argsTag && isArguments(value)))) || false;
}
/**
@@ -3510,17 +3706,6 @@
return result;
}
- /**
- * Checks if `value` is cloneable.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is cloneable, else `false`.
- */
- function isCloneable(value) {
- return (value && cloneableTags[objToString.call(value)]) || false;
- }
-
/**
* Checks if the provided arguments are from an iteratee call.
*
@@ -3616,20 +3801,20 @@
var value = source[3];
if (value) {
var partials = data[3];
- data[3] = partials ? composeArgs(partials, value, source[4]) : baseSlice(value);
- data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : baseSlice(source[4]);
+ data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
}
// Compose partial right arguments.
value = source[5];
if (value) {
partials = data[5];
- data[5] = partials ? composeArgsRight(partials, value, source[6]) : baseSlice(value);
- data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : baseSlice(source[6]);
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
}
// Use source `argPos` if available.
value = source[7];
if (value) {
- data[7] = baseSlice(value);
+ data[7] = arrayCopy(value);
}
// Use source `ary` if it's smaller.
if (srcBitmask & ARY_FLAG) {
@@ -3704,7 +3889,7 @@
function reorder(array, indexes) {
var arrLength = array.length,
length = nativeMin(indexes.length, arrLength),
- oldArray = baseSlice(array);
+ oldArray = arrayCopy(array);
while (length--) {
var index = indexes[length];
@@ -3759,15 +3944,23 @@
support = lodash.support;
// Exit early for non `Object` objects.
- if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||
+ if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value)) ||
(!hasOwnProperty.call(value, 'constructor') &&
- (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
+ (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor))) ||
+ (!support.argsTag && isArguments(value))) {
return false;
}
// IE < 9 iterates inherited properties before own properties. If the first
// iterated property is an object's own property then there are no inherited
// enumerable properties.
var result;
+ if (support.ownLast) {
+ baseForIn(value, function(subValue, key, object) {
+ result = hasOwnProperty.call(object, key);
+ return false;
+ });
+ return result !== 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.
@@ -3792,7 +3985,8 @@
support = lodash.support;
var allowIndexes = length && isLength(length) &&
- (isArray(object) || (support.nonEnumArgs && isArguments(object)));
+ (isArray(object) || (support.nonEnumStrings && isString(object)) ||
+ (support.nonEnumArgs && isArguments(object)));
var index = -1,
result = [];
@@ -3820,6 +4014,9 @@
if (!isLength(value.length)) {
return values(value);
}
+ if (lodash.support.unindexedChars && isString(value)) {
+ return value.split('');
+ }
return isObject(value) ? value : Object(value);
}
@@ -3831,6 +4028,16 @@
* @returns {Object} Returns the object.
*/
function toObject(value) {
+ if (lodash.support.unindexedChars && isString(value)) {
+ var index = -1,
+ length = value.length,
+ result = Object(value);
+
+ while (++index < length) {
+ result[index] = value.charAt(index);
+ }
+ return result;
+ }
return isObject(value) ? value : Object(value);
}
@@ -3883,7 +4090,7 @@
result = Array(ceil(length / size));
while (index < length) {
- result[++resIndex] = slice(array, index, (index += size));
+ result[++resIndex] = baseSlice(array, index, (index += size));
}
return result;
}
@@ -3976,10 +4183,14 @@
* // => [1, 2, 3]
*/
function drop(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- return slice(array, n < 0 ? 0 : n);
+ return baseSlice(array, n < 0 ? 0 : n);
}
/**
@@ -4008,11 +4219,15 @@
* // => [1, 2, 3]
*/
function dropRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- n = array ? (array.length - (+n || 0)) : 0;
- return slice(array, 0, n < 0 ? 0 : n);
+ n = length - (+n || 0);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
}
/**
@@ -4057,10 +4272,12 @@
*/
function dropRightWhile(array, predicate, thisArg) {
var length = array ? array.length : 0;
-
+ if (!length) {
+ return [];
+ }
predicate = getCallback(predicate, thisArg, 3);
while (length-- && predicate(array[length], length, array)) {}
- return slice(array, 0, length + 1);
+ return baseSlice(array, 0, length + 1);
}
/**
@@ -4104,12 +4321,14 @@
* // => ['pebbles']
*/
function dropWhile(array, predicate, thisArg) {
- var index = -1,
- length = array ? array.length : 0;
-
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ var index = -1;
predicate = getCallback(predicate, thisArg, 3);
while (++index < length && predicate(array[index], index, array)) {}
- return slice(array, index);
+ return baseSlice(array, index);
}
/**
@@ -4631,32 +4850,15 @@
* @returns {Array} Returns the slice of `array`.
*/
function slice(array, start, end) {
- var index = -1,
- length = array ? array.length : 0,
- endType = typeof end;
-
- if (end && endType != 'number' && isIterateeCall(array, start, end)) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
start = 0;
end = length;
}
- start = start == null ? 0 : (+start || 0);
- if (start < 0) {
- start = -start > length ? 0 : (length + start);
- }
- end = (endType == 'undefined' || end > length) ? length : (+end || 0);
- if (end < 0) {
- end += length;
- }
- if (end && end == length && !start) {
- return baseSlice(array);
- }
- length = start > end ? 0 : (end - start);
-
- var result = Array(length);
- while (++index < length) {
- result[index] = array[index + start];
- }
- return result;
+ return baseSlice(array, start, end);
}
/**
@@ -4765,10 +4967,14 @@
* // => []
*/
function take(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- return slice(array, 0, n < 0 ? 0 : n);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
}
/**
@@ -4797,11 +5003,15 @@
* // => []
*/
function takeRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
if (guard ? isIterateeCall(array, n, guard) : n == null) {
n = 1;
}
- n = array ? (array.length - (+n || 0)) : 0;
- return slice(array, n < 0 ? 0 : n);
+ n = length - (+n || 0);
+ return baseSlice(array, n < 0 ? 0 : n);
}
/**
@@ -4846,10 +5056,12 @@
*/
function takeRightWhile(array, predicate, thisArg) {
var length = array ? array.length : 0;
-
+ if (!length) {
+ return [];
+ }
predicate = getCallback(predicate, thisArg, 3);
while (length-- && predicate(array[length], length, array)) {}
- return slice(array, length + 1);
+ return baseSlice(array, length + 1);
}
/**
@@ -4893,12 +5105,14 @@
* // => ['barney', 'fred']
*/
function takeWhile(array, predicate, thisArg) {
- var index = -1,
- length = array ? array.length : 0;
-
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ var index = -1;
predicate = getCallback(predicate, thisArg, 3);
while (++index < length && predicate(array[index], index, array)) {}
- return slice(array, 0, index);
+ return baseSlice(array, 0, index);
}
/**
@@ -5042,7 +5256,7 @@
* // => [2, 3, 4]
*/
function without(array) {
- return baseDifference(array, slice(arguments, 1));
+ return baseDifference(array, baseSlice(arguments, 1));
}
/**
@@ -5791,7 +6005,7 @@
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
- return baseInvoke(collection, methodName, slice(arguments, 2));
+ return baseInvoke(collection, methodName, baseSlice(arguments, 2));
}
/**
@@ -6368,7 +6582,9 @@
if (!length) {
return [];
}
- return baseSlice(collection);
+ return (lodash.support.unindexedChars && isString(collection))
+ ? collection.split('')
+ : arrayCopy(collection);
}
/**
@@ -6562,7 +6778,7 @@
function bind(func, thisArg) {
var bitmask = BIND_FLAG;
if (arguments.length > 2) {
- var partials = slice(arguments, 2),
+ var partials = baseSlice(arguments, 2),
holders = replaceHolders(partials, bind.placeholder);
bitmask |= PARTIAL_FLAG;
@@ -6651,7 +6867,7 @@
function bindKey(object, key) {
var bitmask = BIND_FLAG | BIND_KEY_FLAG;
if (arguments.length > 2) {
- var partials = slice(arguments, 2),
+ var partials = baseSlice(arguments, 2),
holders = replaceHolders(partials, bindKey.placeholder);
bitmask |= PARTIAL_FLAG;
@@ -7214,7 +7430,7 @@
* // => 'hi fred'
*/
function partial(func) {
- var partials = slice(arguments, 1),
+ var partials = baseSlice(arguments, 1),
holders = replaceHolders(partials, partial.placeholder);
return createWrapper(func, PARTIAL_FLAG, null, partials, holders);
@@ -7252,7 +7468,7 @@
* // => 'hello fred'
*/
function partialRight(func) {
- var partials = slice(arguments, 1),
+ var partials = baseSlice(arguments, 1),
holders = replaceHolders(partials, partialRight.placeholder);
return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders);
@@ -7502,6 +7718,14 @@
var length = isObjectLike(value) ? value.length : undefined;
return (isLength(length) && objToString.call(value) == argsTag) || false;
}
+ // Fallback for environments without a `toStringTag` for `arguments` objects.
+ if (!support.argsTag) {
+ isArguments = function(value) {
+ var length = isObjectLike(value) ? value.length : undefined;
+ return (isLength(length) && hasOwnProperty.call(value, 'callee') &&
+ !propertyIsEnumerable.call(value, 'callee')) || false;
+ };
+ }
/**
* Checks if `value` is classified as an `Array` object.
@@ -7581,7 +7805,7 @@
*/
function isElement(value) {
return (value && value.nodeType === 1 && isObjectLike(value) &&
- objToString.call(value).indexOf('Element') > -1) || false;
+ (lodash.support.nodeTag ? objToString.call(value).indexOf('Element') > -1 : isHostObject(value))) || false;
}
// Fallback for environments without DOM support.
if (!support.dom) {
@@ -7644,8 +7868,8 @@
* @static
* @memberOf _
* @category Lang
- * @param {*} value The value to compare to `other`.
- * @param {*} other The value to compare to `value`.
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize comparing values.
* @param {*} [thisArg] The `this` binding of `customizer`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
@@ -7909,7 +8133,8 @@
if (objToString.call(value) == funcTag) {
return reNative.test(fnToString.call(value));
}
- return (isObjectLike(value) && reHostCtor.test(value)) || false;
+ return (isObjectLike(value) &&
+ (isHostObject(value) ? reNative : reHostCtor).test(value)) || false;
}
/**
@@ -7990,7 +8215,7 @@
* // => true
*/
var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
- if (!(value && objToString.call(value) == objectTag)) {
+ if (!(value && objToString.call(value) == objectTag) || (!lodash.support.argsTag && isArguments(value))) {
return false;
}
var valueOf = value.valueOf,
@@ -8018,7 +8243,7 @@
* // => false
*/
function isRegExp(value) {
- return (isObjectLike(value) && objToString.call(value) == regexpTag) || false;
+ return (isObject(value) && objToString.call(value) == regexpTag) || false;
}
/**
@@ -8154,7 +8379,7 @@
if (object == null) {
return object;
}
- var args = baseSlice(arguments);
+ var args = arrayCopy(arguments);
args.push(assignDefaults);
return assign.apply(undefined, args);
}
@@ -8484,7 +8709,7 @@
length = object.length;
}
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
- (typeof object != 'function' && (length && isLength(length)))) {
+ (typeof object == 'function' ? lodash.support.enumPrototypes : (length && isLength(length)))) {
return shimKeys(object);
}
return isObject(object) ? nativeKeys(object) : [];
@@ -8519,25 +8744,54 @@
if (!isObject(object)) {
object = Object(object);
}
- var length = object.length;
+ var length = object.length,
+ support = lodash.support;
+
length = (length && isLength(length) &&
- (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;
+ (isArray(object) || (support.nonEnumStrings && isString(object)) ||
+ (support.nonEnumArgs && isArguments(object))) && length) || 0;
var Ctor = object.constructor,
index = -1,
- isProto = typeof Ctor == 'function' && Ctor.prototype == object,
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto,
+ isProto = proto === object,
result = Array(length),
- skipIndexes = length > 0;
+ skipIndexes = length > 0,
+ skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error),
+ skipProto = support.enumPrototypes && typeof object == 'function';
while (++index < length) {
- result[index] = String(index);
+ result[index] = (index + '');
}
+ // Lo-Dash skips the `constructor` property when it infers it is iterating
+ // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]`
+ // attribute of an existing property and the `constructor` property of a
+ // prototype defaults to non-enumerable.
for (var key in object) {
- if (!(skipIndexes && isIndex(key, length)) &&
+ if (!(skipProto && key == 'prototype') &&
+ !(skipErrorProps && (key == 'message' || key == 'name')) &&
+ !(skipIndexes && isIndex(key, length)) &&
!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
result.push(key);
}
}
+ if (support.nonEnumShadows && object !== objectProto) {
+ var tag = object === stringProto ? stringTag : object === errorProto ? errorTag : objToString.call(object),
+ nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag];
+
+ if (tag == objectTag) {
+ proto = objectProto;
+ }
+ length = shadowProps.length;
+ while (length--) {
+ key = shadowProps[length];
+ var nonEnum = nonEnums[key];
+ if (!(isProto && nonEnum) &&
+ (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {
+ result.push(key);
+ }
+ }
+ }
return result;
}
@@ -10006,7 +10260,7 @@
var chainAll = this.__chain__;
if (chain || chainAll) {
var result = object(this.__wrapped__);
- (result.__actions__ = baseSlice(this.__actions__)).push({ 'func': func, 'args': arguments, 'thisArg': object });
+ (result.__actions__ = arrayCopy(this.__actions__)).push({ 'func': func, 'args': arguments, 'thisArg': object });
result.__chain__ = chainAll;
return result;
}
@@ -10634,10 +10888,21 @@
// Add `Array.prototype` functions to `lodash.prototype`.
arrayEach(['concat', 'join', 'pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
- var func = arrayProto[methodName],
+ var arrayFunc = arrayProto[methodName],
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
+ fixObjects = !support.spliceObjects && /^(?:pop|shift|splice)$/.test(methodName),
retUnwrapped = /^(?:join|pop|shift)$/.test(methodName);
+ // Avoid array-like object bugs with `Array#shift` and `Array#splice` in
+ // IE < 9, Firefox < 10, Narwhal, and RingoJS.
+ var func = !fixObjects ? arrayFunc : function() {
+ var result = arrayFunc.apply(this, arguments);
+ if (this.length === 0) {
+ delete this[0];
+ }
+ return result;
+ };
+
lodash.prototype[methodName] = function() {
var args = arguments;
if (retUnwrapped && !this.__chain__) {