diff options
author | st398c <st398c@research.att.com> | 2019-06-14 14:36:53 -0400 |
---|---|---|
committer | st398c <st398c@research.att.com> | 2019-06-18 12:44:52 -0400 |
commit | 7af2403dd9a6c95b12efec59e60d47125dc8e286 (patch) | |
tree | e557a0e80412c15619f172b9ccefc25363fd1c83 /ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash | |
parent | 0d5c6d9516afa7b28e64f7445785ecb539849876 (diff) |
Blackduck scan fixes
Issue-ID: PORTAL-631
Change-Id: I1a09436f606831378b7f2a6211b1199ab830e06e
Signed-off-by: st398c <st398c@research.att.com>
Diffstat (limited to 'ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash')
-rw-r--r-- | ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.17.11/lodash.js (renamed from ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js) | 7787 |
1 files changed, 4981 insertions, 2806 deletions
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.17.11/lodash.js index f1860f12..cad4cad9 100644 --- a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js +++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.17.11/lodash.js @@ -1,10 +1,10 @@ /** * @license - * lodash 4.5.1 <https://lodash.com/> - * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/> + * Lodash <https://lodash.com/> + * Copyright JS Foundation and other contributors <https://js.foundation/> + * Released under MIT license <https://lodash.com/license> * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> - * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license <https://lodash.com/license> + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ ;(function() { @@ -12,46 +12,58 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.5.1'; - - /** Used to compose bitmasks for wrapper metadata. */ - var BIND_FLAG = 1, - BIND_KEY_FLAG = 2, - CURRY_BOUND_FLAG = 4, - CURRY_FLAG = 8, - CURRY_RIGHT_FLAG = 16, - PARTIAL_FLAG = 32, - PARTIAL_RIGHT_FLAG = 64, - ARY_FLAG = 128, - REARG_FLAG = 256, - FLIP_FLAG = 512; - - /** Used to compose bitmasks for comparison styles. */ - var UNORDERED_COMPARE_FLAG = 1, - PARTIAL_COMPARE_FLAG = 2; + var VERSION = '4.17.11'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; /** Used as default options for `_.truncate`. */ var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = '...'; /** Used to detect hot functions by number of calls within a span of milliseconds. */ - var HOT_COUNT = 150, + var HOT_COUNT = 800, HOT_SPAN = 16; - /** Used as the size to enable large array optimizations. */ - var LARGE_ARRAY_SIZE = 200; - /** Used to indicate the type of lazy iteratees. */ var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3; - /** Used as the `TypeError` message for "Functions" methods. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /** Used to stand-in for `undefined` hash values. */ - var HASH_UNDEFINED = '__lodash_hash_undefined__'; - /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, @@ -63,28 +75,45 @@ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - /** Used as the internal argument placeholder. */ - var PLACEHOLDER = '__lodash_placeholder__'; + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', boolTag = '[object Boolean]', dateTag = '[object Date]', + domExcTag = '[object DOMException]', errorTag = '[object Error]', funcTag = '[object Function]', genTag = '[object GeneratorFunction]', mapTag = '[object Map]', numberTag = '[object Number]', + nullTag = '[object Null]', objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', weakMapTag = '[object WeakMap]', weakSetTag = '[object WeakSet]'; var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', float32Tag = '[object Float32Array]', float64Tag = '[object Float64Array]', int8Tag = '[object Int8Array]', @@ -101,8 +130,8 @@ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities and HTML characters. */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, - reUnescapedHtml = /[&<>"'`]/g, + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); @@ -114,9 +143,12 @@ /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, - rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g; + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; - /** Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */ + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); @@ -125,25 +157,33 @@ reTrimStart = /^\s+/, reTrimEnd = /\s+$/; + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; - /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */ + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; - /** Used to detect hexadecimal string values. */ - var reHasHexPrefix = /^0x/i; - /** Used to detect bad signed hexadecimal string values. */ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; /** Used to detect binary string values. */ var reIsBinary = /^0b[01]+$/i; - /** Used to detect host constructors (Safari > 5). */ + /** Used to detect host constructors (Safari). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used to detect octal string values. */ @@ -152,8 +192,8 @@ /** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|[1-9]\d*)$/; - /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ - var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; /** Used to ensure capturing order of template delimiters. */ var reNoMatch = /($^)/; @@ -163,22 +203,25 @@ /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', - rsComboSymbolsRange = '\\u20d0-\\u20f0', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = '\\u2700-\\u27bf', rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', - rsQuoteRange = '\\u2018\\u2019\\u201c\\u201d', + rsPunctuationRange = '\\u2000-\\u206f', rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', rsVarRange = '\\ufe0e\\ufe0f', - rsBreakRange = rsMathOpRange + rsNonCharRange + rsQuoteRange + rsSpaceRange; + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; /** Used to compose unicode capture groups. */ - var rsAstral = '[' + rsAstralRange + ']', + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', rsBreak = '[' + rsBreakRange + ']', - rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsCombo = '[' + rsComboRange + ']', rsDigits = '\\d+', rsDingbat = '[' + rsDingbatRange + ']', rsLower = '[' + rsLowerRange + ']', @@ -192,15 +235,22 @@ rsZWJ = '\\u200d'; /** Used to compose unicode regexes. */ - var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', - rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', + var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', reOptMod = rsModifier + '?', rsOptVar = '[' + rsVarRange + ']?', rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', + rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + /** * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). @@ -208,34 +258,33 @@ var reComboMark = RegExp(rsCombo, 'g'); /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ - var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); - - /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ - var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); - - /** Used to match non-compound words composed of alphanumeric characters. */ - var reBasicWord = /[a-zA-Z0-9]+/g; + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); /** Used to match complex or compound words. */ - var reComplexWord = RegExp([ - rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', - rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', - rsUpper + '?' + rsLowerMisc + '+', - rsUpper + '+', + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, rsDigits, rsEmoji ].join('|'), 'g'); + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + /** Used to detect strings that need a more robust regexp to match words. */ - var reHasComplexWord = /[a-z][A-Z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; /** Used to assign default `context` object properties. */ var contextProps = [ - 'Array', 'Buffer', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', - 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_', - 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' ]; /** Used to make template sourceURLs easier to identify. */ @@ -250,38 +299,40 @@ typedArrayTags[uint32Tag] = true; typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = - typedArrayTags[dateTag] = typedArrayTags[errorTag] = - typedArrayTags[funcTag] = typedArrayTags[mapTag] = - typedArrayTags[numberTag] = typedArrayTags[objectTag] = - typedArrayTags[regexpTag] = typedArrayTags[setTag] = - typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; /** Used to identify `toStringTag` values supported by `_.clone`. */ var cloneableTags = {}; cloneableTags[argsTag] = cloneableTags[arrayTag] = - cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = - cloneableTags[dateTag] = cloneableTags[float32Tag] = - cloneableTags[float64Tag] = cloneableTags[int8Tag] = - cloneableTags[int16Tag] = cloneableTags[int32Tag] = - cloneableTags[mapTag] = cloneableTags[numberTag] = - cloneableTags[objectTag] = cloneableTags[regexpTag] = - cloneableTags[setTag] = cloneableTags[stringTag] = - cloneableTags[symbolTag] = cloneableTags[uint8Tag] = - cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = - cloneableTags[uint32Tag] = true; + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false; - /** Used to map latin-1 supplementary letters to basic latin letters. */ + /** Used to map Latin Unicode letters to basic Latin letters. */ var deburredLetters = { + // Latin-1 Supplement block. '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', '\xc7': 'C', '\xe7': 'c', '\xd0': 'D', '\xf0': 'd', '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', - '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', - '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', '\xd1': 'N', '\xf1': 'n', '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', @@ -290,7 +341,43 @@ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', '\xc6': 'Ae', '\xe6': 'ae', '\xde': 'Th', '\xfe': 'th', - '\xdf': 'ss' + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' }; /** Used to map characters to HTML entities. */ @@ -299,8 +386,7 @@ '<': '<', '>': '>', '"': '"', - "'": ''', - '`': '`' + "'": ''' }; /** Used to map HTML entities to characters. */ @@ -309,14 +395,7 @@ '<': '<', '>': '>', '"': '"', - ''': "'", - '`': '`' - }; - - /** Used to determine if values are of the language type `Object`. */ - var objectTypes = { - 'function': true, - 'object': true + ''': "'" }; /** Used to escape characters for inclusion in compiled string literals. */ @@ -333,84 +412,64 @@ var freeParseFloat = parseFloat, freeParseInt = parseInt; + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + /** Detect free variable `exports`. */ - var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) - ? exports - : undefined; + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; /** Detect free variable `module`. */ - var freeModule = (objectTypes[typeof module] && module && !module.nodeType) - ? module - : undefined; + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; /** Detect the popular CommonJS extension `module.exports`. */ - var moduleExports = (freeModule && freeModule.exports === freeExports) - ? freeExports - : undefined; + var moduleExports = freeModule && freeModule.exports === freeExports; - /** Detect free variable `global` from Node.js. */ - var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; - /** Detect free variable `self`. */ - var freeSelf = checkGlobal(objectTypes[typeof self] && self); + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; - /** Detect free variable `window`. */ - var freeWindow = checkGlobal(objectTypes[typeof window] && window); + if (types) { + return types; + } - /** Detect `this` as the global object. */ - var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); - /** - * Used as a reference to the global object. - * - * The `this` value is used if it's the global object to avoid Greasemonkey's - * restricted `window` object, otherwise the `window` object is used. - */ - var root = freeGlobal || - ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || - freeSelf || thisGlobal || Function('return this')(); + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; /*--------------------------------------------------------------------------*/ /** - * Adds the key-value `pair` to `map`. - * - * @private - * @param {Object} map The map to modify. - * @param {Array} pair The key-value pair to add. - * @returns {Object} Returns `map`. - */ - function addMapEntry(map, pair) { - map.set(pair[0], pair[1]); - return map; - } - - /** - * Adds `value` to `set`. - * - * @private - * @param {Object} set The set to modify. - * @param {*} value The value to add. - * @returns {Object} Returns `set`. - */ - function addSetEntry(set, value) { - set.add(value); - return set; - } - - /** * A faster alternative to `Function#apply`, this function invokes `func` * with the `this` binding of `thisArg` and the arguments of `args`. * * @private * @param {Function} func The function to invoke. * @param {*} thisArg The `this` binding of `func`. - * @param {...*} args The arguments to invoke `func` with. + * @param {Array} args The arguments to invoke `func` with. * @returns {*} Returns the result of `func`. */ function apply(func, thisArg, args) { - var length = args.length; - switch (length) { + switch (args.length) { case 0: return func.call(thisArg); case 1: return func.call(thisArg, args[0]); case 2: return func.call(thisArg, args[0], args[1]); @@ -423,7 +482,7 @@ * A specialized version of `baseAggregator` for arrays. * * @private - * @param {Array} array The array to iterate over. + * @param {Array} [array] The array to iterate over. * @param {Function} setter The function to set `accumulator` values. * @param {Function} iteratee The iteratee to transform keys. * @param {Object} accumulator The initial aggregated object. @@ -431,7 +490,7 @@ */ function arrayAggregator(array, setter, iteratee, accumulator) { var index = -1, - length = array.length; + length = array == null ? 0 : array.length; while (++index < length) { var value = array[index]; @@ -441,41 +500,17 @@ } /** - * Creates a new array concatenating `array` with `other`. - * - * @private - * @param {Array} array The first array to concatenate. - * @param {Array} other The second array to concatenate. - * @returns {Array} Returns the new concatenated array. - */ - function arrayConcat(array, other) { - var index = -1, - length = array.length, - othIndex = -1, - othLength = other.length, - result = Array(length + othLength); - - while (++index < length) { - result[index] = array[index]; - } - while (++othIndex < othLength) { - result[index++] = other[othIndex]; - } - return result; - } - - /** * A specialized version of `_.forEach` for arrays without support for * iteratee shorthands. * * @private - * @param {Array} array The array to iterate over. + * @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; + length = array == null ? 0 : array.length; while (++index < length) { if (iteratee(array[index], index, array) === false) { @@ -490,12 +525,12 @@ * iteratee shorthands. * * @private - * @param {Array} array The array to iterate over. + * @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; + var length = array == null ? 0 : array.length; while (length--) { if (iteratee(array[length], length, array) === false) { @@ -510,13 +545,14 @@ * iteratee shorthands. * * @private - * @param {Array} array The array to iterate over. + * @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`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. */ function arrayEvery(array, predicate) { var index = -1, - length = array.length; + length = array == null ? 0 : array.length; while (++index < length) { if (!predicate(array[index], index, array)) { @@ -531,20 +567,20 @@ * iteratee shorthands. * * @private - * @param {Array} array The array to iterate over. + * @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, + length = array == null ? 0 : array.length, + resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { - result[++resIndex] = value; + result[resIndex++] = value; } } return result; @@ -555,27 +591,27 @@ * specifying an index to search from. * * @private - * @param {Array} array The array to search. + * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ function arrayIncludes(array, value) { - return !!array.length && baseIndexOf(array, value, 0) > -1; + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; } /** - * A specialized version of `_.includesWith` for arrays without support for - * specifying an index to search from. + * This function is like `arrayIncludes` except that it accepts a comparator. * * @private - * @param {Array} array The array to search. + * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @param {Function} comparator The comparator invoked per element. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ function arrayIncludesWith(array, value, comparator) { var index = -1, - length = array.length; + length = array == null ? 0 : array.length; while (++index < length) { if (comparator(value, array[index])) { @@ -590,13 +626,13 @@ * shorthands. * * @private - * @param {Array} array The array to iterate over. + * @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, + length = array == null ? 0 : array.length, result = Array(length); while (++index < length) { @@ -629,15 +665,16 @@ * iteratee shorthands. * * @private - * @param {Array} array The array to iterate over. + * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. - * @param {boolean} [initAccum] Specify using the first element of `array` as the initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initAccum) { var index = -1, - length = array.length; + length = array == null ? 0 : array.length; if (initAccum && length) { accumulator = array[++index]; @@ -653,14 +690,15 @@ * iteratee shorthands. * * @private - * @param {Array} array The array to iterate over. + * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. - * @param {boolean} [initAccum] Specify using the last element of `array` as the initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduceRight(array, iteratee, accumulator, initAccum) { - var length = array.length; + var length = array == null ? 0 : array.length; if (initAccum && length) { accumulator = array[--length]; } @@ -675,13 +713,14 @@ * shorthands. * * @private - * @param {Array} array The array to iterate over. + * @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`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. */ function arraySome(array, predicate) { var index = -1, - length = array.length; + length = array == null ? 0 : array.length; while (++index < length) { if (predicate(array[index], index, array)) { @@ -692,51 +731,52 @@ } /** - * The base implementation of methods like `_.max` and `_.min` which accepts a - * `comparator` to determine the extremum value. + * Gets the size of an ASCII `string`. * * @private - * @param {Array} array The array to iterate over. - * @param {Function} iteratee The iteratee invoked per iteration. - * @param {Function} comparator The comparator used to compare values. - * @returns {*} Returns the extremum value. + * @param {string} string The string inspect. + * @returns {number} Returns the string size. */ - function baseExtremum(array, iteratee, comparator) { - var index = -1, - length = array.length; + var asciiSize = baseProperty('length'); - while (++index < length) { - var value = array[index], - current = iteratee(value); + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } - if (current != null && (computed === undefined - ? current === current - : comparator(current, computed) - )) { - var computed = current, - result = value; - } - } - return result; + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; } /** - * The base implementation of methods like `_.find` and `_.findKey`, without - * support for iteratee shorthands, which iterates over `collection` using - * `eachFunc`. + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. * * @private - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. - * @param {boolean} [retKey] Specify returning the key of the found element instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ - function baseFind(collection, predicate, eachFunc, retKey) { + function baseFindKey(collection, predicate, eachFunc) { var result; eachFunc(collection, function(value, key, collection) { if (predicate(value, key, collection)) { - result = retKey ? key : value; + result = key; return false; } }); @@ -748,14 +788,15 @@ * support for iteratee shorthands. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched value, else `-1`. */ - function baseFindIndex(array, predicate, fromRight) { + function baseFindIndex(array, predicate, fromIndex, fromRight) { var length = array.length, - index = fromRight ? length : -1; + index = fromIndex + (fromRight ? 1 : -1); while ((fromRight ? index-- : ++index < length)) { if (predicate(array[index], index, array)) { @@ -769,20 +810,33 @@ * The base implementation of `_.indexOf` without `fromIndex` bounds checks. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { - if (value !== value) { - return indexOfNaN(array, fromIndex); - } + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { var index = fromIndex - 1, length = array.length; while (++index < length) { - if (array[index] === value) { + if (comparator(array[index], value)) { return index; } } @@ -790,6 +844,57 @@ } /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** * The base implementation of `_.reduce` and `_.reduceRight`, without support * for iteratee shorthands, which iterates over `collection` using `eachFunc`. * @@ -797,7 +902,8 @@ * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. - * @param {boolean} initAccum Specify using the first or last element of `collection` as the initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ @@ -811,9 +917,9 @@ } /** - * The base implementation of `_.sortBy` which uses `comparer` to define - * the sort order of `array` and replaces criteria objects with their - * corresponding values. + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. * * @private * @param {Array} array The array to sort. @@ -831,7 +937,8 @@ } /** - * The base implementation of `_.sum` without support for iteratee shorthands. + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. @@ -878,7 +985,7 @@ * @private * @param {Object} object The object to query. * @param {Array} props The property names to get values for. - * @returns {Object} Returns the new array of key-value pairs. + * @returns {Object} Returns the key-value pairs. */ function baseToPairs(object, props) { return arrayMap(props, function(key) { @@ -887,11 +994,11 @@ } /** - * The base implementation of `_.unary` without support for storing wrapper metadata. + * The base implementation of `_.unary` without support for storing metadata. * * @private * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new capped function. */ function baseUnary(func) { return function(value) { @@ -916,6 +1023,18 @@ } /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol * that is not found in the character symbols. * @@ -949,90 +1068,6 @@ } /** - * Checks if `value` is a global object. - * - * @private - * @param {*} value The value to check. - * @returns {null|Object} Returns `value` if it's a global object, else `null`. - */ - function checkGlobal(value) { - return (value && value.Object === Object) ? value : null; - } - - /** - * Compares values to sort them in ascending order. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {number} Returns the sort order indicator for `value`. - */ - function compareAscending(value, other) { - if (value !== other) { - var valIsNull = value === null, - valIsUndef = value === undefined, - valIsReflexive = value === value; - - var othIsNull = other === null, - othIsUndef = other === undefined, - othIsReflexive = other === other; - - if ((value > other && !othIsNull) || !valIsReflexive || - (valIsNull && !othIsUndef && othIsReflexive) || - (valIsUndef && othIsReflexive)) { - return 1; - } - if ((value < other && !valIsNull) || !othIsReflexive || - (othIsNull && !valIsUndef && valIsReflexive) || - (othIsUndef && valIsReflexive)) { - return -1; - } - } - return 0; - } - - /** - * Used by `_.orderBy` to compare multiple properties of a value to another - * and stable sort them. - * - * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, - * specify an order of "desc" for descending or "asc" for ascending sort order - * of corresponding values. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {boolean[]|string[]} orders The order to sort by for each property. - * @returns {number} Returns the sort order indicator for `object`. - */ - function compareMultiple(object, other, orders) { - var index = -1, - objCriteria = object.criteria, - othCriteria = other.criteria, - length = objCriteria.length, - ordersLength = orders.length; - - while (++index < length) { - var result = compareAscending(objCriteria[index], othCriteria[index]); - if (result) { - if (index >= ordersLength) { - return result; - } - var order = orders[index]; - return result * (order == 'desc' ? -1 : 1); - } - } - // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to provide the same value for - // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 - // for more details. - // - // This also ensures a stable sort in V8 and other engines. - // See https://code.google.com/p/v8/issues/detail?id=90 for more details. - return object.index - other.index; - } - - /** * Gets the number of `placeholder` occurrences in `array`. * * @private @@ -1046,22 +1081,21 @@ while (length--) { if (array[length] === placeholder) { - result++; + ++result; } } return result; } /** - * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. * * @private * @param {string} letter The matched letter to deburr. * @returns {string} Returns the deburred letter. */ - function deburrLetter(letter) { - return deburredLetters[letter]; - } + var deburrLetter = basePropertyOf(deburredLetters); /** * Used by `_.escape` to convert characters to HTML entities. @@ -1070,9 +1104,7 @@ * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ - function escapeHtmlChar(chr) { - return htmlEscapes[chr]; - } + var escapeHtmlChar = basePropertyOf(htmlEscapes); /** * Used by `_.template` to escape characters for inclusion in compiled string literals. @@ -1086,58 +1118,37 @@ } /** - * Gets the index at which the first occurrence of `NaN` is found in `array`. + * Gets the value at `key` of `object`. * * @private - * @param {Array} array The array to search. - * @param {number} fromIndex The index to search from. - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {number} Returns the index of the matched `NaN`, else `-1`. + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. */ - function indexOfNaN(array, fromIndex, fromRight) { - var length = array.length, - index = fromIndex + (fromRight ? 0 : -1); - - while ((fromRight ? index-- : ++index < length)) { - var other = array[index]; - if (other !== other) { - return index; - } - } - return -1; + function getValue(object, key) { + return object == null ? undefined : object[key]; } /** - * Checks if `value` is a host object in IE < 9. + * Checks if `string` contains Unicode symbols. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. */ - function isHostObject(value) { - // Many host objects are `Object` objects that can coerce to strings - // despite having improperly defined `toString` methods. - var result = false; - if (value != null && typeof value.toString != 'function') { - try { - result = !!(value + ''); - } catch (e) {} - } - return result; + function hasUnicode(string) { + return reHasUnicode.test(string); } /** - * Checks if `value` is a valid array-like index. + * Checks if `string` contains a word composed of Unicode symbols. * * @private - * @param {*} value The value to check. - * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. - * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. */ - function isIndex(value, length) { - value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; - length = length == null ? MAX_SAFE_INTEGER : length; - return value > -1 && value % 1 == 0 && value < length; + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); } /** @@ -1158,11 +1169,11 @@ } /** - * Converts `map` to an array. + * Converts `map` to its key-value pairs. * * @private * @param {Object} map The map to convert. - * @returns {Array} Returns the converted array. + * @returns {Array} Returns the key-value pairs. */ function mapToArray(map) { var index = -1, @@ -1175,6 +1186,20 @@ } /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** * Replaces all `placeholder` elements in `array` with an internal placeholder * and returns an array of their indexes. * @@ -1186,25 +1211,25 @@ function replaceHolders(array, placeholder) { var index = -1, length = array.length, - resIndex = -1, + resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (value === placeholder || value === PLACEHOLDER) { array[index] = PLACEHOLDER; - result[++resIndex] = index; + result[resIndex++] = index; } } return result; } /** - * Converts `set` to an array. + * Converts `set` to an array of its values. * * @private * @param {Object} set The set to convert. - * @returns {Array} Returns the converted array. + * @returns {Array} Returns the values. */ function setToArray(set) { var index = -1, @@ -1217,6 +1242,65 @@ } /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** * Gets the number of symbols in `string`. * * @private @@ -1224,14 +1308,9 @@ * @returns {number} Returns the string size. */ function stringSize(string) { - if (!(string && reHasComplexSymbol.test(string))) { - return string.length; - } - var result = reComplexSymbol.lastIndex = 0; - while (reComplexSymbol.test(string)) { - result++; - } - return result; + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); } /** @@ -1242,7 +1321,9 @@ * @returns {Array} Returns the converted array. */ function stringToArray(string) { - return string.match(reComplexSymbol); + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); } /** @@ -1252,8 +1333,43 @@ * @param {string} chr The matched character to unescape. * @returns {string} Returns the unescaped character. */ - function unescapeHtmlChar(chr) { - return htmlUnescapes[chr]; + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; } /*--------------------------------------------------------------------------*/ @@ -1263,6 +1379,7 @@ * * @static * @memberOf _ + * @since 1.1.0 * @category Util * @param {Object} [context=root] The context object. * @returns {Function} Returns a new `lodash` function. @@ -1283,32 +1400,33 @@ * lodash.isFunction(lodash.bar); * // => true * - * // Use `context` to mock `Date#getTime` use in `_.now`. - * var mock = _.runInContext({ - * 'Date': function() { - * return { 'getTime': getTimeMock }; - * } - * }); - * * // Create a suped-up `defer` in Node.js. * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ - function runInContext(context) { - context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root; + var runInContext = (function runInContext(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); /** Built-in constructor references. */ - var Date = context.Date, + var Array = context.Array, + Date = context.Date, Error = context.Error, + Function = context.Function, Math = context.Math, + Object = context.Object, RegExp = context.RegExp, + String = context.String, TypeError = context.TypeError; /** Used for built-in method references. */ - var arrayProto = context.Array.prototype, - objectProto = context.Object.prototype; + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; /** Used to resolve the decompiled source of functions. */ - var funcToString = context.Function.prototype.toString; + var funcToString = funcProto.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; @@ -1316,14 +1434,21 @@ /** Used to generate unique IDs. */ var idCounter = 0; - /** Used to infer the `Object` constructor. */ - var objectCtorString = funcToString.call(Object); + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ - var objectToString = objectProto.toString; + var nativeObjectToString = objectProto.toString; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); /** Used to restore the original `_` reference in `_.noConflict`. */ var oldDash = root._; @@ -1336,33 +1461,49 @@ /** Built-in value references. */ var Buffer = moduleExports ? context.Buffer : undefined, - Reflect = context.Reflect, Symbol = context.Symbol, Uint8Array = context.Uint8Array, - clearTimeout = context.clearTimeout, - enumerate = Reflect ? Reflect.enumerate : undefined, - getPrototypeOf = Object.getPrototypeOf, - getOwnPropertySymbols = Object.getOwnPropertySymbols, - iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), objectCreate = Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, - setTimeout = context.setTimeout, - splice = arrayProto.splice; + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, + symIterator = Symbol ? Symbol.iterator : undefined, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil, nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, - nativeKeys = Object.keys, + nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max, nativeMin = Math.min, + nativeNow = Date.now, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeReverse = arrayProto.reverse; /* Built-in method references that are verified to be native. */ - var Map = getNative(context, 'Map'), + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), Set = getNative(context, 'Set'), WeakMap = getNative(context, 'WeakMap'), nativeCreate = getNative(Object, 'create'); @@ -1370,42 +1511,44 @@ /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; + /** Used to lookup unminified function names. */ + var realNames = {}; + /** Used to detect maps, sets, and weakmaps. */ - var mapCtorString = Map ? funcToString.call(Map) : '', - setCtorString = Set ? funcToString.call(Set) : '', - weakMapCtorString = WeakMap ? funcToString.call(WeakMap) : ''; + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); /** Used to convert symbols to primitives and strings. */ var symbolProto = Symbol ? Symbol.prototype : undefined, - symbolValueOf = Symbol ? symbolProto.valueOf : undefined, - symbolToString = Symbol ? symbolProto.toString : undefined; - - /** Used to lookup unminified function names. */ - var realNames = {}; + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps `value` to enable implicit method - * chaining. Methods that operate on and return arrays, collections, and - * functions can be chained together. Methods that retrieve a single value or - * may return a primitive value will automatically end the chain sequence and - * return the unwrapped value. Otherwise, the value must be unwrapped with - * `_#value`. + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. * - * Explicit chaining, which must be unwrapped with `_#value` in all cases, - * may be enabled using `_.chain`. + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. * * The execution of chained methods is lazy, that is, it's deferred until * `_#value` is implicitly or explicitly called. * - * Lazy evaluation allows several methods to support shortcut fusion. Shortcut - * fusion is an optimization to merge iteratee calls; this avoids the creation - * of intermediate arrays and can greatly reduce the number of iteratee executions. - * Sections of a chain sequence qualify for shortcut fusion if the section is - * applied to an array of at least two hundred elements and any iteratees - * accept only one argument. The heuristic for whether a section qualifies - * for shortcut fusion is subject to change. + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. @@ -1427,49 +1570,54 @@ * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, - * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`, - * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`, - * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flattenDepth`, - * `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, `functionsIn`, - * `groupBy`, `initial`, `intersection`, `intersectionBy`, `intersectionWith`, - * `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, `keys`, `keysIn`, - * `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, `memoize`, - * `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, `nthArg`, - * `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, `overEvery`, - * `overSome`, `partial`, `partialRight`, `partition`, `pick`, `pickBy`, `plant`, - * `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, `pullAt`, `push`, - * `range`, `rangeRight`, `rearg`, `reject`, `remove`, `rest`, `reverse`, - * `sampleSize`, `set`, `setWith`, `shuffle`, `slice`, `sort`, `sortBy`, - * `splice`, `spread`, `tail`, `take`, `takeRight`, `takeRightWhile`, - * `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, `toPairs`, `toPairsIn`, - * `toPath`, `toPlainObject`, `transform`, `unary`, `union`, `unionBy`, - * `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, `unshift`, `unzip`, - * `unzipWith`, `values`, `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, - * `xorWith`, `zip`, `zipObject`, `zipObjectDeep`, and `zipWith` + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, - * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `endsWith`, `eq`, - * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, - * `findLastIndex`, `findLastKey`, `floor`, `forEach`, `forEachRight`, `forIn`, - * `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`, - * `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`, - * `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`, - * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`, - * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`, - * `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`, - * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`, - * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`, - * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`, - * `lt`, `lte`, `max`, `maxBy`, `mean`, `min`, `minBy`, `noConflict`, `noop`, - * `now`, `pad`, `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, - * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `sample`, - * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, - * `sortedLastIndex`, `sortedLastIndexBy`, `startCase`, `startsWith`, `subtract`, - * `sum`, `sumBy`, `template`, `times`, `toLower`, `toInteger`, `toLength`, - * `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, `trimEnd`, - * `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, `upperFirst`, - * `value`, and `words` + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` * * @name _ * @constructor @@ -1510,7 +1658,31 @@ } /** - * The function whose prototype all chaining wrappers inherit from. + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. * * @private */ @@ -1523,7 +1695,7 @@ * * @private * @param {*} value The value to wrap. - * @param {boolean} [chainAll] Enable chaining for all wrapper methods. + * @param {boolean} [chainAll] Enable explicit method chain sequences. */ function LodashWrapper(value, chainAll) { this.__wrapped__ = value; @@ -1535,8 +1707,8 @@ /** * By default, the template delimiters used by lodash are like those in - * embedded Ruby (ERB). Change the following template settings to use - * alternative delimiters. + * embedded Ruby (ERB) as well as ES2015 template strings. Change the + * following template settings to use alternative delimiters. * * @static * @memberOf _ @@ -1594,6 +1766,13 @@ } }; + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + /*------------------------------------------------------------------------*/ /** @@ -1676,8 +1855,7 @@ resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); - if (!isArr || arrLength < LARGE_ARRAY_SIZE || - (arrLength == length && takeCount == length)) { + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { return baseWrapperValue(array, this.__actions__); } var result = []; @@ -1710,69 +1888,231 @@ return result; } + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + /*------------------------------------------------------------------------*/ /** - * Creates an hash object. + * Creates a hash object. * * @private * @constructor - * @returns {Object} Returns the new hash object. + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash */ - function Hash() {} + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } /** * Removes `key` and its value from the hash. * * @private + * @name delete + * @memberOf Hash * @param {Object} hash The hash to modify. * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ - function hashDelete(hash, key) { - return hashHas(hash, key) && delete hash[key]; + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; } /** * Gets the hash value for `key`. * * @private - * @param {Object} hash The hash to query. + * @name get + * @memberOf Hash * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ - function hashGet(hash, key) { + function hashGet(key) { + var data = this.__data__; if (nativeCreate) { - var result = hash[key]; + var result = data[key]; return result === HASH_UNDEFINED ? undefined : result; } - return hasOwnProperty.call(hash, key) ? hash[key] : undefined; + return hasOwnProperty.call(data, key) ? data[key] : undefined; } /** * Checks if a hash value for `key` exists. * * @private - * @param {Object} hash The hash to query. + * @name has + * @memberOf Hash * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ - function hashHas(hash, key) { - return nativeCreate ? hash[key] !== undefined : hasOwnProperty.call(hash, key); + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); } /** * Sets the hash `key` to `value`. * * @private - * @param {Object} hash The hash to modify. + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache * @param {string} key The key of the value to set. * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. */ - function hashSet(hash, key, value) { - hash[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; } + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + /*------------------------------------------------------------------------*/ /** @@ -1780,15 +2120,15 @@ * * @private * @constructor - * @param {Array} [values] The values to cache. + * @param {Array} [entries] The key-value pairs to cache. */ - function MapCache(values) { + function MapCache(entries) { var index = -1, - length = values ? values.length : 0; + length = entries == null ? 0 : entries.length; this.clear(); while (++index < length) { - var entry = values[index]; + var entry = entries[index]; this.set(entry[0], entry[1]); } } @@ -1800,10 +2140,11 @@ * @name clear * @memberOf MapCache */ - function mapClear() { + function mapCacheClear() { + this.size = 0; this.__data__ = { 'hash': new Hash, - 'map': Map ? new Map : [], + 'map': new (Map || ListCache), 'string': new Hash }; } @@ -1817,12 +2158,10 @@ * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ - function mapDelete(key) { - var data = this.__data__; - if (isKeyable(key)) { - return hashDelete(typeof key == 'string' ? data.string : data.hash, key); - } - return Map ? data.map['delete'](key) : assocDelete(data.map, key); + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; } /** @@ -1834,12 +2173,8 @@ * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ - function mapGet(key) { - var data = this.__data__; - if (isKeyable(key)) { - return hashGet(typeof key == 'string' ? data.string : data.hash, key); - } - return Map ? data.map.get(key) : assocGet(data.map, key); + function mapCacheGet(key) { + return getMapData(this, key).get(key); } /** @@ -1851,12 +2186,8 @@ * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ - function mapHas(key) { - var data = this.__data__; - if (isKeyable(key)) { - return hashHas(typeof key == 'string' ? data.string : data.hash, key); - } - return Map ? data.map.has(key) : assocHas(data.map, key); + function mapCacheHas(key) { + return getMapData(this, key).has(key); } /** @@ -1867,25 +2198,29 @@ * @memberOf MapCache * @param {string} key The key of the value to set. * @param {*} value The value to set. - * @returns {Object} Returns the map cache object. + * @returns {Object} Returns the map cache instance. */ - function mapSet(key, value) { - var data = this.__data__; - if (isKeyable(key)) { - hashSet(typeof key == 'string' ? data.string : data.hash, key, value); - } else if (Map) { - data.map.set(key, value); - } else { - assocSet(data.map, key, value); - } + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; return this; } + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + /*------------------------------------------------------------------------*/ /** * - * Creates a set cache object to store unique values. + * Creates an array cache object to store unique values. * * @private * @constructor @@ -1893,54 +2228,46 @@ */ function SetCache(values) { var index = -1, - length = values ? values.length : 0; + length = values == null ? 0 : values.length; this.__data__ = new MapCache; while (++index < length) { - this.push(values[index]); + this.add(values[index]); } } /** - * Checks if `value` is in `cache`. + * Adds `value` to the array cache. * * @private - * @param {Object} cache The set cache to search. - * @param {*} value The value to search for. - * @returns {number} Returns `true` if `value` is found, else `false`. + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. */ - function cacheHas(cache, value) { - var map = cache.__data__; - if (isKeyable(value)) { - var data = map.__data__, - hash = typeof value == 'string' ? data.string : data.hash; - - return hash[value] === HASH_UNDEFINED; - } - return map.has(value); + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; } /** - * Adds `value` to the set cache. + * Checks if `value` is in the array cache. * * @private - * @name push + * @name has * @memberOf SetCache - * @param {*} value The value to cache. + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. */ - function cachePush(value) { - var map = this.__data__; - if (isKeyable(value)) { - var data = map.__data__, - hash = typeof value == 'string' ? data.string : data.hash; - - hash[value] = HASH_UNDEFINED; - } - else { - map.set(value, HASH_UNDEFINED); - } + function setCacheHas(value) { + return this.__data__.has(value); } + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + /*------------------------------------------------------------------------*/ /** @@ -1948,17 +2275,11 @@ * * @private * @constructor - * @param {Array} [values] The values to cache. + * @param {Array} [entries] The key-value pairs to cache. */ - function Stack(values) { - var index = -1, - length = values ? values.length : 0; - - this.clear(); - while (++index < length) { - var entry = values[index]; - this.set(entry[0], entry[1]); - } + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; } /** @@ -1969,7 +2290,8 @@ * @memberOf Stack */ function stackClear() { - this.__data__ = { 'array': [], 'map': null }; + this.__data__ = new ListCache; + this.size = 0; } /** @@ -1983,9 +2305,10 @@ */ function stackDelete(key) { var data = this.__data__, - array = data.array; + result = data['delete'](key); - return array ? assocDelete(array, key) : data.map['delete'](key); + this.size = data.size; + return result; } /** @@ -1998,10 +2321,7 @@ * @returns {*} Returns the entry value. */ function stackGet(key) { - var data = this.__data__, - array = data.array; - - return array ? assocGet(array, key) : data.map.get(key); + return this.__data__.get(key); } /** @@ -2014,10 +2334,7 @@ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function stackHas(key) { - var data = this.__data__, - array = data.array; - - return array ? assocHas(array, key) : data.map.has(key); + return this.__data__.has(key); } /** @@ -2028,134 +2345,106 @@ * @memberOf Stack * @param {string} key The key of the value to set. * @param {*} value The value to set. - * @returns {Object} Returns the stack cache object. + * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { - var data = this.__data__, - array = data.array; - - if (array) { - if (array.length < (LARGE_ARRAY_SIZE - 1)) { - assocSet(array, key, value); - } else { - data.array = null; - data.map = new MapCache(array); + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; } + data = this.__data__ = new MapCache(pairs); } - var map = data.map; - if (map) { - map.set(key, value); - } + data.set(key, value); + this.size = data.size; return this; } - /*------------------------------------------------------------------------*/ + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; - /** - * Removes `key` and its value from the associative array. - * - * @private - * @param {Array} array The array to query. - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function assocDelete(array, key) { - var index = assocIndexOf(array, key); - if (index < 0) { - return false; - } - var lastIndex = array.length - 1; - if (index == lastIndex) { - array.pop(); - } else { - splice.call(array, index, 1); - } - return true; - } + /*------------------------------------------------------------------------*/ /** - * Gets the associative array value for `key`. + * Creates an array of the enumerable property names of the array-like `value`. * * @private - * @param {Array} array The array to query. - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. */ - function assocGet(array, key) { - var index = assocIndexOf(array, key); - return index < 0 ? undefined : array[index][1]; - } + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; - /** - * Checks if an associative array value for `key` exists. - * - * @private - * @param {Array} array The array to query. - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function assocHas(array, key) { - return assocIndexOf(array, key) > -1; + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; } /** - * Gets the index at which the first occurrence of `key` is found in `array` - * of key-value pairs. + * A specialized version of `_.sample` for arrays. * * @private - * @param {Array} array The array to search. - * @param {*} key The key to search for. - * @returns {number} Returns the index of the matched value, else `-1`. + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. */ - function assocIndexOf(array, key) { + function arraySample(array) { var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; + return length ? array[baseRandom(0, length - 1)] : undefined; } /** - * Sets the associative array `key` to `value`. + * A specialized version of `_.sampleSize` for arrays. * * @private - * @param {Array} array The array to modify. - * @param {string} key The key of the value to set. - * @param {*} value The value to set. + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. */ - function assocSet(array, key, value) { - var index = assocIndexOf(array, key); - if (index < 0) { - array.push([key, value]); - } else { - array[index][1] = value; - } + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); } - /*------------------------------------------------------------------------*/ - /** - * Used by `_.defaults` to customize its `_.assignIn` use. + * A specialized version of `_.shuffle` for arrays. * * @private - * @param {*} objValue The destination value. - * @param {*} srcValue The source value. - * @param {string} key The key of the property to assign. - * @param {Object} object The parent object of `objValue`. - * @returns {*} Returns the value to assign. + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. */ - function assignInDefaults(objValue, srcValue, key, object) { - if (objValue === undefined || - (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { - return srcValue; - } - return objValue; + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); } /** - * This function is like `assignValue` except that it doesn't assign `undefined` values. + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. * * @private * @param {Object} object The object to modify. @@ -2164,14 +2453,14 @@ */ function assignMergeValue(object, key, value) { if ((value !== undefined && !eq(object[key], value)) || - (typeof key == 'number' && value === undefined && !(key in object))) { - object[key] = value; + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); } } /** * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private @@ -2183,8 +2472,26 @@ var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { - object[key] = value; + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } } + return -1; } /** @@ -2219,60 +2526,62 @@ } /** - * The base implementation of `_.at` without support for individual paths. + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. * * @private - * @param {Object} object The object to iterate over. - * @param {string[]} paths The property paths of elements to pick. - * @returns {Array} Returns the new array of picked elements. + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. */ - function baseAt(object, paths) { - var index = -1, - isNil = object == null, - length = paths.length, - result = Array(length); - - while (++index < length) { - result[index] = isNil ? undefined : get(object, paths[index]); - } - return result; + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); } /** - * Casts `value` to an empty array if it's not an array like object. + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. * * @private - * @param {*} value The value to inspect. - * @returns {Array} Returns the array-like object. + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. */ - function baseCastArrayLikeObject(value) { - return isArrayLikeObject(value) ? value : []; + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } } /** - * Casts `value` to `identity` if it's not a function. + * The base implementation of `_.at` without support for individual paths. * * @private - * @param {*} value The value to inspect. - * @returns {Array} Returns the array-like object. + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. */ - function baseCastFunction(value) { - return typeof value == 'function' ? value : identity; - } + function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; - /** - * Casts `value` to a path array if it's not one. - * - * @private - * @param {*} value The value to inspect. - * @returns {Array} Returns the cast property path array. - */ - function baseCastPath(value) { - return isArray(value) ? value : stringToPath(value); + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; } /** - * The base implementation of `_.clamp` which doesn't coerce arguments to numbers. + * The base implementation of `_.clamp` which doesn't coerce arguments. * * @private * @param {number} number The number to clamp. @@ -2298,15 +2607,22 @@ * * @private * @param {*} value The value to clone. - * @param {boolean} [isDeep] Specify a deep clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols * @param {Function} [customizer] The function to customize cloning. * @param {string} [key] The key of `value`. * @param {Object} [object] The parent object of `value`. * @param {Object} [stack] Tracks traversed objects and their clone counterparts. * @returns {*} Returns the cloned value. */ - function baseClone(value, isDeep, customizer, key, object, stack) { - var result; + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + if (customizer) { result = object ? customizer(value, key, object, stack) : customizer(value); } @@ -2330,12 +2646,11 @@ return cloneBuffer(value, isDeep); } if (tag == objectTag || tag == argsTag || (isFunc && !object)) { - if (isHostObject(value)) { - return object ? value : {}; - } - result = initCloneObject(isFunc ? {} : value); + result = (isFlat || isFunc) ? {} : initCloneObject(value); if (!isDeep) { - return copySymbols(value, baseAssign(result, value)); + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); } } else { if (!cloneableTags[tag]) { @@ -2352,11 +2667,36 @@ } stack.set(value, result); - // Recursively populate clone (susceptible to call stack limits). - (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { - assignValue(result, key, baseClone(subValue, isDeep, customizer, key, value, stack)); + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + + return result; + } + + if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + + return result; + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); }); - return isArr ? result : copySymbols(value, result); + return result; } /** @@ -2364,51 +2704,50 @@ * * @private * @param {Object} source The object of property predicates to conform to. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new spec function. */ function baseConforms(source) { - var props = keys(source), - length = props.length; - + var props = keys(source); return function(object) { - if (object == null) { - return !length; - } - var index = length; - while (index--) { - var key = props[index], - predicate = source[key], - value = object[key]; - - if ((value === undefined && !(key in Object(object))) || !predicate(value)) { - return false; - } - } - return true; + return baseConformsTo(object, source, props); }; } /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. + * The base implementation of `_.conformsTo` which accepts `props` to check. * * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. */ - function baseCreate(proto) { - return isObject(proto) ? objectCreate(proto) : {}; + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; } /** - * The base implementation of `_.delay` and `_.defer` which accepts an array - * of `func` arguments. + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. * * @private * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. - * @param {Object} args The arguments to provide to `func`. - * @returns {number} Returns the timer id. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. */ function baseDelay(func, wait, args) { if (typeof func != 'function') { @@ -2418,8 +2757,8 @@ } /** - * The base implementation of methods like `_.difference` without support for - * excluding multiple arrays or iteratee shorthands. + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. * * @private * @param {Array} array The array to inspect. @@ -2454,8 +2793,9 @@ outer: while (++index < length) { var value = array[index], - computed = iteratee ? iteratee(value) : value; + computed = iteratee == null ? value : iteratee(value); + value = (comparator || value !== 0) ? value : 0; if (isCommon && computed === computed) { var valuesIndex = valuesLength; while (valuesIndex--) { @@ -2498,7 +2838,8 @@ * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false` + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` */ function baseEvery(collection, predicate) { var result = true; @@ -2510,6 +2851,35 @@ } /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** * The base implementation of `_.fill` without an iteratee call guard. * * @private @@ -2561,23 +2931,24 @@ * @private * @param {Array} array The array to flatten. * @param {number} depth The maximum recursion depth. - * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, depth, isStrict, result) { - result || (result = []); - + function baseFlatten(array, depth, predicate, isStrict, result) { var index = -1, length = array.length; + predicate || (predicate = isFlattenable); + result || (result = []); + while (++index < length) { var value = array[index]; - if (depth > 0 && isArrayLikeObject(value) && - (isStrict || isArray(value) || isArguments(value))) { + if (depth > 0 && predicate(value)) { if (depth > 1) { // Recursively flatten arrays (susceptible to call stack limits). - baseFlatten(value, depth - 1, isStrict, result); + baseFlatten(value, depth - 1, predicate, isStrict, result); } else { arrayPush(result, value); } @@ -2589,10 +2960,9 @@ } /** - * The base implementation of `baseForIn` and `baseForOwn` which iterates - * over `object` properties returned by `keysFunc` invoking `iteratee` for - * each property. Iteratee functions may exit iteration early by explicitly - * returning `false`. + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. * * @private * @param {Object} object The object to iterate over. @@ -2615,18 +2985,6 @@ var baseForRight = createBaseFor(true); /** - * The base implementation of `_.forIn` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Object} Returns `object`. - */ - function baseForIn(object, iteratee) { - return object == null ? object : baseFor(object, iteratee, keysIn); - } - - /** * The base implementation of `_.forOwn` without support for iteratee shorthands. * * @private @@ -2657,7 +3015,7 @@ * @private * @param {Object} object The object to inspect. * @param {Array} props The property names to filter. - * @returns {Array} Returns the new array of filtered property names. + * @returns {Array} Returns the function names. */ function baseFunctions(object, props) { return arrayFilter(props, function(key) { @@ -2674,47 +3032,88 @@ * @returns {*} Returns the resolved value. */ function baseGet(object, path) { - path = isKey(path, object) ? [path + ''] : baseCastPath(path); + path = castPath(path, object); var index = 0, length = path.length; while (object != null && index < length) { - object = object[path[index++]]; + object = object[toKey(path[index++])]; } return (index && index == length) ? object : undefined; } /** - * The base implementation of `_.has` without support for deep paths. + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. * * @private * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHas(object, key) { - // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`, - // that are composed entirely of index properties, return `false` for - // `hasOwnProperty` checks of them. - return hasOwnProperty.call(object, key) || - (typeof object == 'object' && key in object && getPrototypeOf(object) === null); + return object != null && hasOwnProperty.call(object, key); } /** * The base implementation of `_.hasIn` without support for deep paths. * * @private - * @param {Object} object The object to query. + * @param {Object} [object] The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHasIn(object, key) { - return key in Object(object); + return object != null && key in Object(object); } /** - * The base implementation of `_.inRange` which doesn't coerce arguments to numbers. + * The base implementation of `_.inRange` which doesn't coerce arguments. * * @private * @param {number} number The number to check. @@ -2738,9 +3137,11 @@ */ function baseIntersection(arrays, iteratee, comparator) { var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array(othLength), + maxLength = Infinity, result = []; while (othIndex--) { @@ -2748,26 +3149,27 @@ if (othIndex && iteratee) { array = arrayMap(array, baseUnary(iteratee)); } - caches[othIndex] = !comparator && (iteratee || array.length >= 120) + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) ? new SetCache(othIndex && array) : undefined; } array = arrays[0]; var index = -1, - length = array.length, seen = caches[0]; outer: - while (++index < length) { + while (++index < length && result.length < maxLength) { var value = array[index], computed = iteratee ? iteratee(value) : value; + value = (comparator || value !== 0) ? value : 0; if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator) )) { - var othIndex = othLength; + othIndex = othLength; while (--othIndex) { var cache = caches[othIndex]; if (!(cache @@ -2815,38 +3217,67 @@ * @returns {*} Returns the result of the invoked method. */ function baseInvoke(object, path, args) { - if (!isKey(path, object)) { - path = baseCastPath(path); - object = parent(object, path); - path = last(path); - } - var func = object == null ? object : object[path]; + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; return func == null ? undefined : apply(func, object, args); } /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** * The base implementation of `_.isEqual` which supports partial comparisons * and tracks traversed objects. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison * @param {Function} [customizer] The function to customize comparisons. - * @param {boolean} [bitmask] The bitmask of comparison flags. - * The bitmask may be composed of the following flags: - * 1 - Unordered comparison - * 2 - Partial comparison * @param {Object} [stack] Tracks traversed `value` and `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ - function baseIsEqual(value, other, customizer, bitmask, stack) { + function baseIsEqual(value, other, bitmask, customizer, stack) { if (value === other) { return true; } - if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { return value !== value && other !== other; } - return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack); + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); } /** @@ -2857,55 +3288,66 @@ * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Function} [customizer] The function to customize comparisons. - * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ - function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { var objIsArr = isArray(object), othIsArr = isArray(other), - objTag = arrayTag, - othTag = arrayTag; + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); - if (!objIsArr) { - objTag = getTag(object); - if (objTag == argsTag) { - objTag = objectTag; - } else if (objTag != objectTag) { - objIsArr = isTypedArray(object); - } - } - if (!othIsArr) { - othTag = getTag(other); - if (othTag == argsTag) { - othTag = objectTag; - } else if (othTag != objectTag) { - othIsArr = isTypedArray(other); - } - } - var objIsObj = objTag == objectTag && !isHostObject(object), - othIsObj = othTag == objectTag && !isHostObject(other), + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, isSameTag = objTag == othTag; - if (isSameTag && !(objIsArr || objIsObj)) { - return equalByTag(object, other, objTag, equalFunc, customizer, bitmask); + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; } - var isPartial = bitmask & PARTIAL_COMPARE_FLAG; - if (!isPartial) { + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (objIsWrapped || othIsWrapped) { - return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, bitmask, stack); + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); } } if (!isSameTag) { return false; } stack || (stack = new Stack); - return (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; } /** @@ -2947,11 +3389,12 @@ return false; } } else { - var stack = new Stack, - result = customizer ? customizer(objValue, srcValue, key, object, source, stack) : undefined; - + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } if (!(result === undefined - ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result )) { return false; @@ -2962,6 +3405,56 @@ } /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + /** * The base implementation of `_.iteratee`. * * @private @@ -2969,14 +3462,15 @@ * @returns {Function} Returns the iteratee. */ function baseIteratee(value) { - var type = typeof value; - if (type == 'function') { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { return value; } if (value == null) { return identity; } - if (type == 'object') { + if (typeof value == 'object') { return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value); @@ -2985,40 +3479,58 @@ } /** - * The base implementation of `_.keys` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeys(object) { - return nativeKeys(Object(object)); + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; } /** - * The base implementation of `_.keysIn` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeysIn(object) { - object = object == null ? object : Object(object); + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; - var result = []; for (var key in object) { - result.push(key); + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } } return result; } - // Fallback for IE < 9 with es6-shim. - if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) { - baseKeysIn = function(object) { - return iteratorToArray(enumerate(object)); - }; + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; } /** @@ -3044,21 +3556,12 @@ * * @private * @param {Object} source The object of property values to match. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new spec function. */ function baseMatches(source) { var matchData = getMatchData(source); if (matchData.length == 1 && matchData[0][2]) { - var key = matchData[0][0], - value = matchData[0][1]; - - return function(object) { - if (object == null) { - return false; - } - return object[key] === value && - (value !== undefined || (key in Object(object))); - }; + return matchesStrictComparable(matchData[0][0], matchData[0][1]); } return function(object) { return object === source || baseIsMatch(object, source, matchData); @@ -3071,14 +3574,17 @@ * @private * @param {string} path The path of the property to get. * @param {*} srcValue The value to match. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new spec function. */ function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } return function(object) { var objValue = get(object, path); return (objValue === undefined && objValue === srcValue) ? hasIn(object, path) - : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG); + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); }; } @@ -3090,28 +3596,21 @@ * @param {Object} source The source object. * @param {number} srcIndex The index of `source`. * @param {Function} [customizer] The function to customize merged values. - * @param {Object} [stack] Tracks traversed source values and their merged counterparts. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. */ function baseMerge(object, source, srcIndex, customizer, stack) { if (object === source) { return; } - var props = (isArray(source) || isTypedArray(source)) - ? undefined - : keysIn(source); - - arrayEach(props || source, function(srcValue, key) { - if (props) { - key = srcValue; - srcValue = source[key]; - } + baseFor(source, function(srcValue, key) { if (isObject(srcValue)) { stack || (stack = new Stack); baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { var newValue = customizer - ? customizer(object[key], srcValue, (key + ''), object, source, stack) + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) : undefined; if (newValue === undefined) { @@ -3119,7 +3618,7 @@ } assignMergeValue(object, key, newValue); } - }); + }, keysIn); } /** @@ -3134,11 +3633,12 @@ * @param {number} srcIndex The index of `source`. * @param {Function} mergeFunc The function to merge values. * @param {Function} [customizer] The function to customize assigned values. - * @param {Object} [stack] Tracks traversed source values and their merged counterparts. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. */ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { - var objValue = object[key], - srcValue = source[key], + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), stacked = stack.get(srcValue); if (stacked) { @@ -3152,45 +3652,70 @@ var isCommon = newValue === undefined; if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + newValue = srcValue; - if (isArray(srcValue) || isTypedArray(srcValue)) { + if (isArr || isBuff || isTyped) { if (isArray(objValue)) { newValue = objValue; } else if (isArrayLikeObject(objValue)) { newValue = copyArray(objValue); } - else { + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { isCommon = false; - newValue = baseClone(srcValue, true); + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; } } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; if (isArguments(objValue)) { newValue = toPlainObject(objValue); } - else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { - isCommon = false; - newValue = baseClone(srcValue, true); - } - else { - newValue = objValue; + else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); } } else { isCommon = false; } } - stack.set(srcValue, newValue); - if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); } assignMergeValue(object, key, newValue); } /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** * The base implementation of `_.orderBy` without param guards. * * @private @@ -3200,12 +3725,8 @@ * @returns {Array} Returns the new sorted array. */ function baseOrderBy(collection, iteratees, orders) { - var index = -1, - toIteratee = getIteratee(); - - iteratees = arrayMap(iteratees.length ? iteratees : Array(1), function(iteratee) { - return toIteratee(iteratee); - }); + var index = -1; + iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); var result = baseMap(collection, function(value, key, collection) { var criteria = arrayMap(iteratees, function(iteratee) { @@ -3221,21 +3742,17 @@ /** * The base implementation of `_.pick` without support for individual - * property names. + * property identifiers. * * @private * @param {Object} object The source object. - * @param {string[]} props The property names to pick. + * @param {string[]} paths The property paths to pick. * @returns {Object} Returns the new object. */ - function basePick(object, props) { - object = Object(object); - return arrayReduce(props, function(result, key) { - if (key in object) { - result[key] = object[key]; - } - return result; - }, {}); + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); } /** @@ -3243,38 +3760,32 @@ * * @private * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. * @param {Function} predicate The function invoked per property. * @returns {Object} Returns the new object. */ - function basePickBy(object, predicate) { - var result = {}; - baseForIn(object, function(value, key) { - if (predicate(value, key)) { - result[key] = value; + function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); } - }); + } return result; } /** - * The base implementation of `_.property` without support for deep paths. - * - * @private - * @param {string} key The key of the property to get. - * @returns {Function} Returns the new function. - */ - function baseProperty(key) { - return function(object) { - return object == null ? undefined : object[key]; - }; - } - - /** * A specialized version of `baseProperty` which supports deep paths. * * @private * @param {Array|string} path The path of the property to get. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new accessor function. */ function basePropertyDeep(path) { return function(object) { @@ -3283,18 +3794,6 @@ } /** - * The base implementation of `_.pullAll`. - * - * @private - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @returns {Array} Returns `array`. - */ - function basePullAll(array, values) { - return basePullAllBy(array, values); - } - - /** * The base implementation of `_.pullAllBy` without support for iteratee * shorthands. * @@ -3302,22 +3801,27 @@ * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns `array`. */ - function basePullAllBy(array, values, iteratee) { - var index = -1, + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, length = values.length, seen = array; + if (array === values) { + values = copyArray(values); + } if (iteratee) { - seen = arrayMap(array, function(value) { return iteratee(value); }); + seen = arrayMap(array, baseUnary(iteratee)); } while (++index < length) { var fromIndex = 0, value = values[index], computed = iteratee ? iteratee(value) : value; - while ((fromIndex = baseIndexOf(seen, computed, fromIndex)) > -1) { + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { if (seen !== array) { splice.call(seen, fromIndex, 1); } @@ -3342,21 +3846,12 @@ while (length--) { var index = indexes[length]; - if (lastIndex == length || index != previous) { + if (length == lastIndex || index !== previous) { var previous = index; if (isIndex(index)) { splice.call(array, index, 1); - } - else if (!isKey(index, array)) { - var path = baseCastPath(index), - object = parent(array, path); - - if (object != null) { - delete object[last(path)]; - } - } - else { - delete array[index]; + } else { + baseUnset(array, index); } } } @@ -3378,14 +3873,14 @@ /** * The base implementation of `_.range` and `_.rangeRight` which doesn't - * coerce arguments to numbers. + * coerce arguments. * * @private * @param {number} start The start of the range. * @param {number} end The end of the range. * @param {number} step The value to increment or decrement by. * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Array} Returns the new array of numbers. + * @returns {Array} Returns the range of numbers. */ function baseRange(start, end, step, fromRight) { var index = -1, @@ -3400,17 +3895,84 @@ } /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** * The base implementation of `_.set`. * * @private - * @param {Object} object The object to query. + * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { - path = isKey(path, object) ? [path + ''] : baseCastPath(path); + if (!isObject(object)) { + return object; + } + path = castPath(path, object); var index = -1, length = path.length, @@ -3418,27 +3980,26 @@ nested = object; while (nested != null && ++index < length) { - var key = path[index]; - if (isObject(nested)) { - var newValue = value; - if (index != lastIndex) { - var objValue = nested[key]; - newValue = customizer ? customizer(objValue, key, nested) : undefined; - if (newValue === undefined) { - newValue = objValue == null - ? (isIndex(path[index + 1]) ? [] : {}) - : objValue; - } + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); } - assignValue(nested, key, newValue); } + assignValue(nested, key, newValue); nested = nested[key]; } return object; } /** - * The base implementation of `setData` without support for hot loop detection. + * The base implementation of `setData` without support for hot loop shorting. * * @private * @param {Function} func The function to associate metadata with. @@ -3451,6 +4012,34 @@ }; /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** * The base implementation of `_.slice` without an iteratee call guard. * * @private @@ -3486,7 +4075,8 @@ * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. */ function baseSome(collection, predicate) { var result; @@ -3512,14 +4102,15 @@ */ function baseSortedIndex(array, value, retHighest) { var low = 0, - high = array ? array.length : low; + high = array == null ? low : array.length; if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { while (low < high) { var mid = (low + high) >>> 1, computed = array[mid]; - if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) { + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { low = mid + 1; } else { high = mid; @@ -3540,30 +4131,36 @@ * @param {*} value The value to evaluate. * @param {Function} iteratee The iteratee invoked per element. * @param {boolean} [retHighest] Specify returning the highest qualified index. - * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. */ function baseSortedIndexBy(array, value, iteratee, retHighest) { value = iteratee(value); var low = 0, - high = array ? array.length : 0, + high = array == null ? 0 : array.length, valIsNaN = value !== value, valIsNull = value === null, - valIsUndef = value === undefined; + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; while (low < high) { var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), - isDef = computed !== undefined, - isReflexive = computed === computed; + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); if (valIsNaN) { - var setLow = isReflexive || retHighest; + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); } else if (valIsNull) { - setLow = isReflexive && isDef && (retHighest || computed != null); - } else if (valIsUndef) { - setLow = isReflexive && (retHighest || isDef); - } else if (computed == null) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { setLow = false; } else { setLow = retHighest ? (computed <= value) : (computed < value); @@ -3578,47 +4175,75 @@ } /** - * The base implementation of `_.sortedUniq`. - * - * @private - * @param {Array} array The array to inspect. - * @returns {Array} Returns the new duplicate free array. - */ - function baseSortedUniq(array) { - return baseSortedUniqBy(array); - } - - /** - * The base implementation of `_.sortedUniqBy` without support for iteratee - * shorthands. + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @returns {Array} Returns the new duplicate free array. */ - function baseSortedUniqBy(array, iteratee) { - var index = 0, + function baseSortedUniq(array, iteratee) { + var index = -1, length = array.length, - value = array[0], - computed = iteratee ? iteratee(value) : value, - seen = computed, resIndex = 0, - result = [value]; + result = []; while (++index < length) { - value = array[index], - computed = iteratee ? iteratee(value) : value; + var value = array[index], + computed = iteratee ? iteratee(value) : value; - if (!eq(computed, seen)) { - seen = computed; - result[++resIndex] = value; + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; } } return result; } /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** * The base implementation of `_.uniqBy` without support for iteratee shorthands. * * @private @@ -3656,6 +4281,7 @@ var value = array[index], computed = iteratee ? iteratee(value) : value; + value = (comparator || value !== 0) ? value : 0; if (isCommon && computed === computed) { var seenIndex = seen.length; while (seenIndex--) { @@ -3683,14 +4309,27 @@ * * @private * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to unset. + * @param {Array|string} path The property path to unset. * @returns {boolean} Returns `true` if the property is deleted, else `false`. */ function baseUnset(object, path) { - path = isKey(path, object) ? [path + ''] : baseCastPath(path); + path = castPath(path, object); object = parent(object, path); - var key = last(path); - return (object != null && has(object, key)) ? delete object[key] : true; + return object == null || delete object[toKey(last(path))]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); } /** @@ -3747,25 +4386,31 @@ * @returns {Array} Returns the new array of values. */ function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } var index = -1, - length = arrays.length; + result = Array(length); while (++index < length) { - var result = result - ? arrayPush( - baseDifference(result, arrays[index], iteratee, comparator), - baseDifference(arrays[index], result, iteratee, comparator) - ) - : arrays[index]; + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } } - return (result && result.length) ? baseUniq(result, iteratee, comparator) : []; + return baseUniq(baseFlatten(result, 1), iteratee, comparator); } /** * This base implementation of `_.zipObject` which assigns values using `assignFunc`. * * @private - * @param {Array} props The property names. + * @param {Array} props The property identifiers. * @param {Array} values The property values. * @param {Function} assignFunc The function to assign values. * @returns {Object} Returns the new object. @@ -3777,12 +4422,86 @@ result = {}; while (++index < length) { - assignFunc(result, props[index], index < valsLength ? values[index] : undefined); + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); } return result; } /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** * Creates a clone of `buffer`. * * @private @@ -3794,8 +4513,8 @@ if (isDeep) { return buffer.slice(); } - var Ctor = buffer.constructor, - result = new Ctor(buffer.length); + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); buffer.copy(result); return result; @@ -3809,24 +4528,22 @@ * @returns {ArrayBuffer} Returns the cloned array buffer. */ function cloneArrayBuffer(arrayBuffer) { - var Ctor = arrayBuffer.constructor, - result = new Ctor(arrayBuffer.byteLength), - view = new Uint8Array(result); - - view.set(new Uint8Array(arrayBuffer)); + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); return result; } /** - * Creates a clone of `map`. + * Creates a clone of `dataView`. * * @private - * @param {Object} map The map to clone. - * @returns {Object} Returns the cloned map. + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. */ - function cloneMap(map) { - var Ctor = map.constructor; - return arrayReduce(mapToArray(map), addMapEntry, new Ctor); + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); } /** @@ -3837,26 +4554,12 @@ * @returns {Object} Returns the cloned regexp. */ function cloneRegExp(regexp) { - var Ctor = regexp.constructor, - result = new Ctor(regexp.source, reFlags.exec(regexp)); - + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); result.lastIndex = regexp.lastIndex; return result; } /** - * Creates a clone of `set`. - * - * @private - * @param {Object} set The set to clone. - * @returns {Object} Returns the cloned set. - */ - function cloneSet(set) { - var Ctor = set.constructor; - return arrayReduce(setToArray(set), addSetEntry, new Ctor); - } - - /** * Creates a clone of the `symbol` object. * * @private @@ -3864,7 +4567,7 @@ * @returns {Object} Returns the cloned symbol object. */ function cloneSymbol(symbol) { - return Symbol ? Object(symbolValueOf.call(symbol)) : {}; + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; } /** @@ -3876,11 +4579,87 @@ * @returns {Object} Returns the cloned typed array. */ function cloneTypedArray(typedArray, isDeep) { - var arrayBuffer = typedArray.buffer, - buffer = isDeep ? cloneArrayBuffer(arrayBuffer) : arrayBuffer, - Ctor = typedArray.constructor; + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; - return new Ctor(buffer, typedArray.byteOffset, typedArray.length); + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; } /** @@ -3888,7 +4667,7 @@ * placeholders, and provided arguments into a single array of arguments. * * @private - * @param {Array|Object} args The provided arguments. + * @param {Array} args The provided arguments. * @param {Array} partials The arguments to prepend to those provided. * @param {Array} holders The `partials` placeholder indexes. * @params {boolean} [isCurried] Specify composing for a curried function. @@ -3923,7 +4702,7 @@ * is tailored for `_.partialRight`. * * @private - * @param {Array|Object} args The provided arguments. + * @param {Array} args The provided arguments. * @param {Array} partials The arguments to append to those provided. * @param {Array} holders The `partials` placeholder indexes. * @params {boolean} [isCurried] Specify composing for a curried function. @@ -3979,26 +4758,13 @@ * * @private * @param {Object} source The object to copy properties from. - * @param {Array} props The property names to copy. - * @param {Object} [object={}] The object to copy properties to. - * @returns {Object} Returns `object`. - */ - function copyObject(source, props, object) { - return copyObjectWith(source, props, object); - } - - /** - * This function is like `copyObject` except that it accepts a function to - * customize copied values. - * - * @private - * @param {Object} source The object to copy properties from. - * @param {Array} props The property names to copy. + * @param {Array} props The property identifiers to copy. * @param {Object} [object={}] The object to copy properties to. * @param {Function} [customizer] The function to customize copied values. * @returns {Object} Returns `object`. */ - function copyObjectWith(source, props, object, customizer) { + function copyObject(source, props, object, customizer) { + var isNew = !object; object || (object = {}); var index = -1, @@ -4009,15 +4775,22 @@ var newValue = customizer ? customizer(object[key], source[key], key, object, source) - : source[key]; + : undefined; - assignValue(object, key, newValue); + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } } return object; } /** - * Copies own symbol properties of `source` to `object`. + * Copies own symbols of `source` to `object`. * * @private * @param {Object} source The object to copy symbols from. @@ -4029,6 +4802,18 @@ } /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + /** * Creates a function like `_.groupBy`. * * @private @@ -4041,7 +4826,7 @@ var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {}; - return func(collection, setter, getIteratee(iteratee), accumulator); + return func(collection, setter, getIteratee(iteratee, 2), accumulator); }; } @@ -4053,13 +4838,13 @@ * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { - return rest(function(object, sources) { + return baseRest(function(object, sources) { var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined, guard = length > 2 ? sources[2] : undefined; - customizer = typeof customizer == 'function' + customizer = (assigner.length > 3 && typeof customizer == 'function') ? (length--, customizer) : undefined; @@ -4108,7 +4893,7 @@ } /** - * Creates a base function for methods like `_.forIn`. + * Creates a base function for methods like `_.forIn` and `_.forOwn`. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. @@ -4137,13 +4922,13 @@ * * @private * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new wrapped function. */ - function createBaseWrapper(func, bitmask, thisArg) { - var isBind = bitmask & BIND_FLAG, - Ctor = createCtorWrapper(func); + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); function wrapper() { var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; @@ -4157,18 +4942,23 @@ * * @private * @param {string} methodName The name of the `String` case method to use. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new case function. */ function createCaseFirst(methodName) { return function(string) { string = toString(string); - var strSymbols = reHasComplexSymbol.test(string) + var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined; - var chr = strSymbols ? strSymbols[0] : string.charAt(0), - trailing = strSymbols ? strSymbols.slice(1).join('') : string.slice(1); + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); return chr[methodName]() + trailing; }; @@ -4183,7 +4973,7 @@ */ function createCompounder(callback) { return function(string) { - return arrayReduce(words(deburr(string)), callback, ''); + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); }; } @@ -4195,10 +4985,10 @@ * @param {Function} Ctor The constructor to wrap. * @returns {Function} Returns the new wrapped function. */ - function createCtorWrapper(Ctor) { + function createCtor(Ctor) { return function() { - // Use a `switch` statement to work with class constructors. - // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { @@ -4225,18 +5015,18 @@ * * @private * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @param {number} arity The arity of `func`. * @returns {Function} Returns the new wrapped function. */ - function createCurryWrapper(func, bitmask, arity) { - var Ctor = createCtorWrapper(func); + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); function wrapper() { var length = arguments.length, args = Array(length), index = length, - placeholder = getPlaceholder(wrapper); + placeholder = getHolder(wrapper); while (index--) { args[index] = arguments[index]; @@ -4247,8 +5037,8 @@ length -= holders.length; if (length < arity) { - return createRecurryWrapper( - func, bitmask, createHybridWrapper, wrapper.placeholder, undefined, + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, args, holders, undefined, undefined, arity - length); } var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; @@ -4258,6 +5048,26 @@ } /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** * Creates a `_.flow` or `_.flowRight` function. * * @private @@ -4265,9 +5075,7 @@ * @returns {Function} Returns the new flow function. */ function createFlow(fromRight) { - return rest(function(funcs) { - funcs = baseFlatten(funcs, 1); - + return flatRest(function(funcs) { var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru; @@ -4292,20 +5100,21 @@ data = funcName == 'wrapper' ? getData(func) : undefined; if (data && isLaziable(data[0]) && - data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1 ) { wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); } else { - wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func); + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); } } return function() { var args = arguments, value = args[0]; - if (wrapper && args.length == 1 && - isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + if (wrapper && args.length == 1 && isArray(value)) { return wrapper.plant(value).value(); } var index = 0, @@ -4325,35 +5134,37 @@ * * @private * @param {Function|string} func The function or method name to wrap. - * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to prepend to those provided to the new function. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [partialsRight] The arguments to append to those provided to the new function. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ - function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { - var isAry = bitmask & ARY_FLAG, - isBind = bitmask & BIND_FLAG, - isBindKey = bitmask & BIND_KEY_FLAG, - isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG), - isFlip = bitmask & FLIP_FLAG, - Ctor = isBindKey ? undefined : createCtorWrapper(func); + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); function wrapper() { var length = arguments.length, - index = length, - args = Array(length); + args = Array(length), + index = length; while (index--) { args[index] = arguments[index]; } if (isCurried) { - var placeholder = getPlaceholder(wrapper), + var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder); } if (partials) { @@ -4365,8 +5176,8 @@ length -= holdersCount; if (isCurried && length < arity) { var newHolders = replaceHolders(args, placeholder); - return createRecurryWrapper( - func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg, + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length ); } @@ -4383,7 +5194,7 @@ args.length = ary; } if (this && this !== root && this instanceof wrapper) { - fn = Ctor || createCtorWrapper(fn); + fn = Ctor || createCtor(fn); } return fn.apply(thisBinding, args); } @@ -4405,16 +5216,50 @@ } /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** * Creates a function like `_.over`. * * @private * @param {Function} arrayFunc The function to iterate over iteratees. - * @returns {Function} Returns the new invoker function. + * @returns {Function} Returns the new over function. */ function createOver(arrayFunc) { - return rest(function(iteratees) { - iteratees = arrayMap(baseFlatten(iteratees, 1), getIteratee()); - return rest(function(args) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { var thisArg = this; return arrayFunc(iteratees, function(iteratee) { return apply(iteratee, thisArg, args); @@ -4428,42 +5273,38 @@ * is truncated if the number of characters exceeds `length`. * * @private - * @param {string} string The string to create padding for. - * @param {number} [length=0] The padding length. + * @param {number} length The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padding for `string`. */ - function createPadding(string, length, chars) { - length = toInteger(length); + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); - var strLength = stringSize(string); - if (!length || strLength >= length) { - return ''; + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; } - var padLength = length - strLength; - chars = chars === undefined ? ' ' : (chars + ''); - - var result = repeat(chars, nativeCeil(padLength / stringSize(chars))); - return reHasComplexSymbol.test(chars) - ? stringToArray(result).slice(0, padLength).join('') - : result.slice(0, padLength); + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); } /** - * Creates a function that wraps `func` to invoke it with the optional `this` - * binding of `thisArg` and the `partials` prepended to those provided to - * the wrapper. + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. * * @private * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @param {*} thisArg The `this` binding of `func`. - * @param {Array} partials The arguments to prepend to those provided to the new function. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. * @returns {Function} Returns the new wrapped function. */ - function createPartialWrapper(func, bitmask, thisArg, partials) { - var isBind = bitmask & BIND_FLAG, - Ctor = createCtorWrapper(func); + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); function wrapper() { var argsIndex = -1, @@ -4497,52 +5338,68 @@ end = step = undefined; } // Ensure the sign of `-0` is preserved. - start = toNumber(start); - start = start === start ? start : 0; + start = toFinite(start); if (end === undefined) { end = start; start = 0; } else { - end = toNumber(end) || 0; + end = toFinite(end); } - step = step === undefined ? (start < end ? 1 : -1) : (toNumber(step) || 0); + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); return baseRange(start, end, step, fromRight); }; } /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** * Creates a function that wraps `func` to continue currying. * * @private * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @param {Function} wrapFunc The function to create the `func` wrapper. * @param {*} placeholder The placeholder value. * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to prepend to those provided to the new function. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ - function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { - var isCurry = bitmask & CURRY_FLAG, - newArgPos = argPos ? copyArray(argPos) : undefined, + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, newHolders = isCurry ? holders : undefined, newHoldersRight = isCurry ? undefined : holders, newPartials = isCurry ? partials : undefined, newPartialsRight = isCurry ? undefined : partials; - bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); - bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); - if (!(bitmask & CURRY_BOUND_FLAG)) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); } var newData = [ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, - newHoldersRight, newArgPos, ary, arity + newHoldersRight, argPos, ary, arity ]; var result = wrapFunc.apply(undefined, newData); @@ -4550,7 +5407,7 @@ setData(result, newData); } result.placeholder = placeholder; - return result; + return setWrapToString(result, func, bitmask); } /** @@ -4564,7 +5421,7 @@ var func = Math[methodName]; return function(number, precision) { number = toNumber(number); - precision = toInteger(precision); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); if (precision) { // Shift with exponential notation to avoid floating-point issues. // See [MDN](https://mdn.io/round#Examples) for more details. @@ -4579,33 +5436,53 @@ } /** - * Creates a set of `values`. + * Creates a set object of `values`. * * @private * @param {Array} values The values to add to the set. * @returns {Object} Returns the new set. */ - var createSet = !(Set && new Set([1, 2]).size === 2) ? noop : function(values) { + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { return new Set(values); }; /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to wrap. - * @param {number} bitmask The bitmask of wrapper flags. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` or `_.curryRight` of a bound function - * 8 - `_.curry` - * 16 - `_.curryRight` - * 32 - `_.partial` - * 64 - `_.partialRight` - * 128 - `_.rearg` - * 256 - `_.ary` + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to be partially applied. * @param {Array} [holders] The `partials` placeholder indexes. @@ -4614,21 +5491,21 @@ * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ - function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { - var isBindKey = bitmask & BIND_KEY_FLAG; + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; if (!isBindKey && typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } var length = partials ? partials.length : 0; if (!length) { - bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); partials = holders = undefined; } ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); arity = arity === undefined ? arity : toInteger(arity); length -= holders ? holders.length : 0; - if (bitmask & PARTIAL_RIGHT_FLAG) { + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; @@ -4649,24 +5526,81 @@ thisArg = newData[2]; partials = newData[3]; holders = newData[4]; - arity = newData[9] = newData[9] == null + arity = newData[9] = newData[9] === undefined ? (isBindKey ? 0 : func.length) : nativeMax(newData[9] - length, 0); - if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) { - bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG); + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); } - if (!bitmask || bitmask == BIND_FLAG) { - var result = createBaseWrapper(func, bitmask, thisArg); - } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) { - result = createCurryWrapper(func, bitmask, arity); - } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) { - result = createPartialWrapper(func, bitmask, thisArg, partials); + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); } else { - result = createHybridWrapper.apply(undefined, newData); + result = createHybrid.apply(undefined, newData); } var setter = data ? baseSetData : setData; - return setter(result, newData); + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ + function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; } /** @@ -4676,16 +5610,14 @@ * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Function} [customizer] The function to customize comparisons. - * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. - * @param {Object} [stack] Tracks traversed `array` and `other` objects. + * @param {Object} stack Tracks traversed `array` and `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ - function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { - var index = -1, - isPartial = bitmask & PARTIAL_COMPARE_FLAG, - isUnordered = bitmask & UNORDERED_COMPARE_FLAG, + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; @@ -4694,11 +5626,15 @@ } // Assume cyclic values are equal. var stacked = stack.get(array); - if (stacked) { + if (stacked && stack.get(other)) { return stacked == other; } - var result = true; + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + stack.set(array, other); + stack.set(other, array); // Ignore non-index properties. while (++index < arrLength) { @@ -4718,19 +5654,26 @@ break; } // Recursively compare arrays (susceptible to call stack limits). - if (isUnordered) { - if (!arraySome(other, function(othValue) { - return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack); + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } })) { result = false; break; } - } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { result = false; break; } } stack['delete'](array); + stack['delete'](other); return result; } @@ -4745,13 +5688,22 @@ * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Function} [customizer] The function to customize comparisons. - * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. + * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ - function equalByTag(object, other, tag, equalFunc, customizer, bitmask) { + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + case arrayBufferTag: if ((object.byteLength != other.byteLength) || !equalFunc(new Uint8Array(object), new Uint8Array(other))) { @@ -4761,36 +5713,48 @@ case boolTag: case dateTag: - // Coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. - return +object == +other; + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); case errorTag: return object.name == other.name && object.message == other.message; - case numberTag: - // Treat `NaN` vs. `NaN` as equal. - return (object != +object) ? other != +other : object == +other; - case regexpTag: case stringTag: - // Coerce regexes to strings and treat strings primitives and string - // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. return object == (other + ''); case mapTag: var convert = mapToArray; case setTag: - var isPartial = bitmask & PARTIAL_COMPARE_FLAG; + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; convert || (convert = setToArray); + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + // Recursively compare objects (susceptible to call stack limits). - return (isPartial || object.size == other.size) && - equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG); + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; case symbolTag: - return !!Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } } return false; } @@ -4802,17 +5766,17 @@ * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Function} [customizer] The function to customize comparisons. - * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. - * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ - function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { - var isPartial = bitmask & PARTIAL_COMPARE_FLAG, - objProps = keys(object), + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), objLength = objProps.length, - othProps = keys(other), + othProps = getAllKeys(other), othLength = othProps.length; if (objLength != othLength && !isPartial) { @@ -4821,17 +5785,18 @@ var index = objLength; while (index--) { var key = objProps[index]; - if (!(isPartial ? key in other : baseHas(other, key))) { + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { return false; } } // Assume cyclic values are equal. var stacked = stack.get(object); - if (stacked) { + if (stacked && stack.get(other)) { return stacked == other; } var result = true; stack.set(object, other); + stack.set(other, object); var skipCtor = isPartial; while (++index < objLength) { @@ -4846,7 +5811,7 @@ } // Recursively compare objects (susceptible to call stack limits). if (!(compared === undefined - ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) : compared )) { result = false; @@ -4867,10 +5832,45 @@ } } stack['delete'](object); + stack['delete'](other); return result; } /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** * Gets metadata for `func`. * * @private @@ -4904,10 +5904,22 @@ } /** - * Gets the appropriate "iteratee" function. If the `_.iteratee` method is - * customized this function returns the custom method, otherwise it returns - * `baseIteratee`. If arguments are provided the chosen function is invoked - * with them and its result is returned. + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. * * @private * @param {*} [value] The value to convert to an iteratee. @@ -4921,16 +5933,19 @@ } /** - * Gets the "length" property value of `object`. - * - * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) - * that affects Safari on at least iOS 8.1-8.3 ARM64. + * Gets the data for `map`. * * @private - * @param {Object} object The object to query. - * @returns {*} Returns the "length" value. + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. */ - var getLength = baseProperty('length'); + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } /** * Gets the property names, values, and compare flags of `object`. @@ -4940,11 +5955,14 @@ * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { - var result = toPairs(object), + var result = keys(object), length = result.length; while (length--) { - result[length][2] = isStrictComparable(result[length][1]); + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; } return result; } @@ -4958,31 +5976,68 @@ * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { - var value = object == null ? undefined : object[key]; - return isNative(value) ? value : undefined; + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; } /** - * Gets the argument placeholder value for `func`. + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. * * @private - * @param {Function} func The function to inspect. - * @returns {*} Returns the placeholder value. + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. */ - function getPlaceholder(func) { - var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; - return object.placeholder; + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; } /** - * Creates an array of the own symbol properties of `object`. + * Creates an array of the own enumerable symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ - var getSymbols = getOwnPropertySymbols || function() { - return []; + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; }; /** @@ -4992,22 +6047,24 @@ * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ - function getTag(value) { - return objectToString.call(value); - } + var getTag = baseGetTag; - // Fallback for IE 11 providing `toStringTag` values for maps, sets, and weakmaps. - if ((Map && getTag(new Map) != mapTag) || + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || (Set && getTag(new Set) != setTag) || (WeakMap && getTag(new WeakMap) != weakMapTag)) { getTag = function(value) { - var result = objectToString.call(value), - Ctor = result == objectTag ? value.constructor : null, - ctorString = typeof Ctor == 'function' ? funcToString.call(Ctor) : ''; + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; if (ctorString) { switch (ctorString) { + case dataViewCtorString: return dataViewTag; case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; case setCtorString: return setTag; case weakMapCtorString: return weakMapTag; } @@ -5045,6 +6102,18 @@ } /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** * Checks if `path` exists on `object`. * * @private @@ -5054,23 +6123,25 @@ * @returns {boolean} Returns `true` if `path` exists, else `false`. */ function hasPath(object, path, hasFunc) { - if (object == null) { - return false; - } - var result = hasFunc(object, path); - if (!result && !isKey(path)) { - path = baseCastPath(path); - object = parent(object, path); - if (object != null) { - path = last(path); - result = hasFunc(object, path); + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; } + object = object[key]; } - var length = object ? object.length : undefined; - return result || ( - !!length && isLength(length) && isIndex(path, length) && - (isArray(object) || isString(object) || isArguments(object)) - ); + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); } /** @@ -5082,7 +6153,7 @@ */ function initCloneArray(array) { var length = array.length, - result = array.constructor(length); + result = new array.constructor(length); // Add properties assigned by `RegExp#exec`. if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { @@ -5100,8 +6171,8 @@ * @returns {Object} Returns the initialized clone. */ function initCloneObject(object) { - return (isFunction(object.constructor) && !isPrototype(object)) - ? baseCreate(getPrototypeOf(object)) + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) : {}; } @@ -5109,7 +6180,7 @@ * Initializes an object clone based on its `toStringTag`. * * **Note:** This function only supports cloning values with tags of - * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. * * @private * @param {Object} object The object to clone. @@ -5127,13 +6198,16 @@ case dateTag: return new Ctor(+object); + case dataViewTag: + return cloneDataView(object, isDeep); + case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: return cloneTypedArray(object, isDeep); case mapTag: - return cloneMap(object); + return new Ctor; case numberTag: case stringTag: @@ -5143,7 +6217,7 @@ return cloneRegExp(object); case setTag: - return cloneSet(object); + return new Ctor; case symbolTag: return cloneSymbol(object); @@ -5151,20 +6225,52 @@ } /** - * Creates an array of index keys for `object` values of arrays, - * `arguments` objects, and strings, otherwise `null` is returned. + * Inserts wrapper `details` in a comment at the top of the `source` body. * * @private - * @param {Object} object The object to query. - * @returns {Array|null} Returns index keys, else `null`. + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. */ - function indexKeys(object) { - var length = object ? object.length : undefined; - if (isLength(length) && - (isArray(object) || isString(object) || isArguments(object))) { - return baseTimes(length, String); + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; } - return null; + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); } /** @@ -5174,7 +6280,8 @@ * @param {*} value The potential iteratee value argument. * @param {*} index The potential iteratee index or key argument. * @param {*} object The potential iteratee object argument. - * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. */ function isIterateeCall(value, index, object) { if (!isObject(object)) { @@ -5182,8 +6289,9 @@ } var type = typeof index; if (type == 'number' - ? (isArrayLike(object) && isIndex(index, object.length)) - : (type == 'string' && index in object)) { + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { return eq(object[index], value); } return false; @@ -5198,12 +6306,16 @@ * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { - if (typeof value == 'number') { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { return true; } - return !isArray(value) && - (reIsPlainProp.test(value) || !reIsDeepProp.test(value) || - (object != null && value in Object(object))); + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); } /** @@ -5215,8 +6327,9 @@ */ function isKeyable(value) { var type = typeof value; - return type == 'number' || type == 'boolean' || - (type == 'string' && value != '__proto__') || value == null; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); } /** @@ -5224,7 +6337,8 @@ * * @private * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. */ function isLaziable(func) { var funcName = getFuncName(func), @@ -5241,6 +6355,26 @@ } /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** * Checks if `value` is likely a prototype object. * * @private @@ -5249,7 +6383,7 @@ */ function isPrototype(value) { var Ctor = value && value.constructor, - proto = (isFunction(Ctor) && Ctor.prototype) || objectProto; + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; return value === proto; } @@ -5267,14 +6401,54 @@ } /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** * Merges the function metadata of `source` into `data`. * * Merging metadata reduces the number of wrappers used to invoke a function. * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` - * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` - * modify function arguments, making the order in which they are executed important, - * preventing the merging of metadata. However, we make an exception for a safe - * combined case where curried functions have `_.ary` and or `_.rearg` applied. + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. * * @private * @param {Array} data The destination metadata. @@ -5285,44 +6459,44 @@ var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, - isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG); + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); var isCombo = - ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) || - ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) || - ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG)); + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { return data; } // Use source `thisArg` if available. - if (srcBitmask & BIND_FLAG) { + if (srcBitmask & WRAP_BIND_FLAG) { data[2] = source[2]; // Set when currying a bound function. - newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; } // Compose partial arguments. var value = source[3]; if (value) { var partials = data[3]; - data[3] = partials ? composeArgs(partials, value, source[4]) : copyArray(value); - data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : copyArray(source[4]); + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; } // Compose partial right arguments. value = source[5]; if (value) { partials = data[5]; - data[5] = partials ? composeArgsRight(partials, value, source[6]) : copyArray(value); - data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : copyArray(source[6]); + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; } // Use source `argPos` if available. value = source[7]; if (value) { - data[7] = copyArray(value); + data[7] = value; } // Use source `ary` if it's smaller. - if (srcBitmask & ARY_FLAG) { + if (srcBitmask & WRAP_ARY_FLAG) { data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); } // Use source `arity` if one is not provided. @@ -5337,23 +6511,63 @@ } /** - * Used by `_.defaultsDeep` to customize its `_.merge` use. + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. * * @private - * @param {*} objValue The destination value. - * @param {*} srcValue The source value. - * @param {string} key The key of the property to merge. - * @param {Object} object The parent object of `objValue`. - * @param {Object} source The parent object of `srcValue`. - * @param {Object} [stack] Tracks traversed source values and their merged counterparts. - * @returns {*} Returns the value to assign. + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. */ - function mergeDefaults(objValue, srcValue, key, object, source, stack) { - if (isObject(objValue) && isObject(srcValue)) { - stack.set(srcValue, objValue); - baseMerge(objValue, srcValue, undefined, mergeDefaults, stack); + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } } - return objValue; + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; } /** @@ -5365,7 +6579,7 @@ * @returns {*} Returns the parent value. */ function parent(object, path) { - return path.length == 1 ? object : get(object, baseSlice(path, 0, -1)); + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); } /** @@ -5391,11 +6605,28 @@ } /** + * Gets the value at `key`, unless `key` is "__proto__". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function safeGet(object, key) { + if (key == '__proto__') { + return; + } + + return object[key]; + } + + /** * Sets metadata for `func`. * * **Note:** If this function becomes hot, i.e. is invoked a lot in a short - * period of time, it will trip its breaker and transition to an identity function - * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070) + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) * for more details. * * @private @@ -5403,25 +6634,98 @@ * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = (function() { + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { var count = 0, lastCalled = 0; - return function(key, value) { - var stamp = now(), + return function() { + var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { if (++count >= HOT_COUNT) { - return key; + return arguments[0]; } } else { count = 0; } - return baseSetData(key, value); + return func.apply(undefined, arguments); }; - }()); + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } /** * Converts `string` to a property path array. @@ -5430,12 +6734,67 @@ * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ - function stringToPath(string) { + var stringToPath = memoizeCapped(function(string) { var result = []; - toString(string).replace(rePropName, function(match, number, quote, string) { - result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); }); return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); } /** @@ -5465,10 +6824,12 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to process. - * @param {number} [size=0] The length of each chunk. - * @returns {Array} Returns the new array containing chunks. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. * @example * * _.chunk(['a', 'b', 'c', 'd'], 2); @@ -5477,19 +6838,22 @@ * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ - function chunk(array, size) { - size = nativeMax(toInteger(size), 0); - - var length = array ? array.length : 0; + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; if (!length || size < 1) { return []; } var index = 0, - resIndex = -1, + resIndex = 0, result = Array(nativeCeil(length / size)); while (index < length) { - result[++resIndex] = baseSlice(array, index, (index += size)); + result[resIndex++] = baseSlice(array, index, (index += size)); } return result; } @@ -5500,6 +6864,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to compact. * @returns {Array} Returns the new array of filtered values. @@ -5510,14 +6875,14 @@ */ function compact(array) { var index = -1, - length = array ? array.length : 0, - resIndex = -1, + length = array == null ? 0 : array.length, + resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (value) { - result[++resIndex] = value; + result[resIndex++] = value; } } return result; @@ -5529,6 +6894,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to concatenate. * @param {...*} [values] The values to concatenate. @@ -5544,74 +6910,95 @@ * console.log(array); * // => [1] */ - var concat = rest(function(array, values) { - if (!isArray(array)) { - array = array == null ? [] : [Object(array)]; + function concat() { + var length = arguments.length; + if (!length) { + return []; } - values = baseFlatten(values, 1); - return arrayConcat(array, values); - }); + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } /** - * Creates an array of unique `array` values not included in the other - * given arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons. + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor * @example * - * _.difference([3, 2, 1], [4, 2]); - * // => [3, 1] + * _.difference([2, 1], [2, 3]); + * // => [1] */ - var difference = rest(function(array, values) { + var difference = baseRest(function(array, values) { return isArrayLikeObject(array) - ? baseDifference(array, baseFlatten(values, 1, true)) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : []; }); /** * This method is like `_.difference` except that it accepts `iteratee` which * is invoked for each element of `array` and `values` to generate the criterion - * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The values to exclude. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {Array} Returns the new array of filtered values. * @example * - * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor); - * // => [3.1, 1.3] + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] * * // The `_.property` iteratee shorthand. * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); * // => [{ 'x': 2 }] */ - var differenceBy = rest(function(array, values) { + var differenceBy = baseRest(function(array, values) { var iteratee = last(values); if (isArrayLikeObject(iteratee)) { iteratee = undefined; } return isArrayLikeObject(array) - ? baseDifference(array, baseFlatten(values, 1, true), getIteratee(iteratee)) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) : []; }); /** * This method is like `_.difference` except that it accepts `comparator` - * which is invoked to compare elements of `array` to `values`. The comparator + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator * is invoked with two arguments: (arrVal, othVal). * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The values to exclude. @@ -5624,13 +7011,13 @@ * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); * // => [{ 'x': 2, 'y': 1 }] */ - var differenceWith = rest(function(array, values) { + var differenceWith = baseRest(function(array, values) { var comparator = last(values); if (isArrayLikeObject(comparator)) { comparator = undefined; } return isArrayLikeObject(array) - ? baseDifference(array, baseFlatten(values, 1, true), undefined, comparator) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) : []; }); @@ -5639,10 +7026,11 @@ * * @static * @memberOf _ + * @since 0.5.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -5659,7 +7047,7 @@ * // => [1, 2, 3] */ function drop(array, n, guard) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return []; } @@ -5672,10 +7060,11 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -5692,7 +7081,7 @@ * // => [1, 2, 3] */ function dropRight(array, n, guard) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return []; } @@ -5708,9 +7097,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * @@ -5748,9 +7138,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * @@ -5789,6 +7180,7 @@ * * @static * @memberOf _ + * @since 3.2.0 * @category Array * @param {Array} array The array to fill. * @param {*} value The value to fill `array` with. @@ -5810,7 +7202,7 @@ * // => [4, '*', '*', 10] */ function fill(array, value, start, end) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return []; } @@ -5827,9 +7219,11 @@ * * @static * @memberOf _ + * @since 1.1.0 * @category Array - * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the found element, else `-1`. * @example * @@ -5854,10 +7248,16 @@ * _.findIndex(users, 'active'); * // => 2 */ - function findIndex(array, predicate) { - return (array && array.length) - ? baseFindIndex(array, getIteratee(predicate, 3)) - : -1; + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); } /** @@ -5866,9 +7266,11 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Array - * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. * @returns {number} Returns the index of the found element, else `-1`. * @example * @@ -5893,10 +7295,19 @@ * _.findLastIndex(users, 'active'); * // => 0 */ - function findLastIndex(array, predicate) { - return (array && array.length) - ? baseFindIndex(array, getIteratee(predicate, 3), true) - : -1; + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); } /** @@ -5904,6 +7315,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to flatten. * @returns {Array} Returns the new flattened array. @@ -5913,7 +7325,7 @@ * // => [1, 2, [3, [4]], 5] */ function flatten(array) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; return length ? baseFlatten(array, 1) : []; } @@ -5922,6 +7334,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to flatten. * @returns {Array} Returns the new flattened array. @@ -5931,7 +7344,7 @@ * // => [1, 2, 3, 4, 5] */ function flattenDeep(array) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; return length ? baseFlatten(array, INFINITY) : []; } @@ -5940,6 +7353,7 @@ * * @static * @memberOf _ + * @since 4.4.0 * @category Array * @param {Array} array The array to flatten. * @param {number} [depth=1] The maximum recursion depth. @@ -5955,7 +7369,7 @@ * // => [1, 2, 3, [4], 5] */ function flattenDepth(array, depth) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return []; } @@ -5969,17 +7383,18 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} pairs The key-value pairs. * @returns {Object} Returns the new object. * @example * - * _.fromPairs([['fred', 30], ['barney', 40]]); - * // => { 'fred': 30, 'barney': 40 } + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } */ function fromPairs(pairs) { var index = -1, - length = pairs ? pairs.length : 0, + length = pairs == null ? 0 : pairs.length, result = {}; while (++index < length) { @@ -5994,6 +7409,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @alias first * @category Array * @param {Array} array The array to query. @@ -6007,19 +7423,20 @@ * // => undefined */ function head(array) { - return array ? array[0] : undefined; + return (array && array.length) ? array[0] : undefined; } /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons. If `fromIndex` is negative, it's used as the offset - * from the end of `array`. + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. * * @static * @memberOf _ + * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. @@ -6033,15 +7450,15 @@ * // => 3 */ function indexOf(array, value, fromIndex) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return -1; } - fromIndex = toInteger(fromIndex); - if (fromIndex < 0) { - fromIndex = nativeMax(length + fromIndex, 0); + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); } - return baseIndexOf(array, value, fromIndex); + return baseIndexOf(array, value, index); } /** @@ -6049,6 +7466,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. @@ -6058,26 +7476,29 @@ * // => [1, 2] */ function initial(array) { - return dropRight(array, 1); + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; } /** * Creates an array of unique values that are included in all given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons. + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of shared values. + * @returns {Array} Returns the new array of intersecting values. * @example * - * _.intersection([2, 1], [4, 2], [1, 2]); + * _.intersection([2, 1], [2, 3]); * // => [2] */ - var intersection = rest(function(arrays) { - var mapped = arrayMap(arrays, baseCastArrayLikeObject); + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); return (mapped.length && mapped[0] === arrays[0]) ? baseIntersection(mapped) : []; @@ -6086,26 +7507,29 @@ /** * This method is like `_.intersection` except that it accepts `iteratee` * which is invoked for each element of each `arrays` to generate the criterion - * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of shared values. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. * @example * - * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor); + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); * // => [2.1] * * // The `_.property` iteratee shorthand. * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }] */ - var intersectionBy = rest(function(arrays) { + var intersectionBy = baseRest(function(arrays) { var iteratee = last(arrays), - mapped = arrayMap(arrays, baseCastArrayLikeObject); + mapped = arrayMap(arrays, castArrayLikeObject); if (iteratee === last(mapped)) { iteratee = undefined; @@ -6113,21 +7537,23 @@ mapped.pop(); } return (mapped.length && mapped[0] === arrays[0]) - ? baseIntersection(mapped, getIteratee(iteratee)) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) : []; }); /** * This method is like `_.intersection` except that it accepts `comparator` - * which is invoked to compare elements of `arrays`. The comparator is invoked - * with two arguments: (arrVal, othVal). + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of shared values. + * @returns {Array} Returns the new array of intersecting values. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; @@ -6136,13 +7562,12 @@ * _.intersectionWith(objects, others, _.isEqual); * // => [{ 'x': 1, 'y': 2 }] */ - var intersectionWith = rest(function(arrays) { + var intersectionWith = baseRest(function(arrays) { var comparator = last(arrays), - mapped = arrayMap(arrays, baseCastArrayLikeObject); + mapped = arrayMap(arrays, castArrayLikeObject); - if (comparator === last(mapped)) { - comparator = undefined; - } else { + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { mapped.pop(); } return (mapped.length && mapped[0] === arrays[0]) @@ -6155,6 +7580,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to convert. * @param {string} [separator=','] The element separator. @@ -6165,7 +7591,7 @@ * // => 'a~b~c' */ function join(array, separator) { - return array ? nativeJoin.call(array, separator) : ''; + return array == null ? '' : nativeJoin.call(array, separator); } /** @@ -6173,6 +7599,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to query. * @returns {*} Returns the last element of `array`. @@ -6182,7 +7609,7 @@ * // => 3 */ function last(array) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; return length ? array[length - 1] : undefined; } @@ -6192,8 +7619,9 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=array.length-1] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. @@ -6207,29 +7635,48 @@ * // => 1 */ function lastIndexOf(array, value, fromIndex) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return -1; } var index = length; if (fromIndex !== undefined) { index = toInteger(fromIndex); - index = (index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1)) + 1; - } - if (value !== value) { - return indexOfNaN(array, index, true); - } - while (index--) { - if (array[index] === value) { - return index; - } + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); } - return -1; + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; } /** * Removes all given values from `array` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` @@ -6237,19 +7684,20 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Array * @param {Array} array The array to modify. * @param {...*} [values] The values to remove. * @returns {Array} Returns `array`. * @example * - * var array = [1, 2, 3, 1, 2, 3]; + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; * - * _.pull(array, 2, 3); + * _.pull(array, 'a', 'c'); * console.log(array); - * // => [1, 1] + * // => ['b', 'b'] */ - var pull = rest(pullAll); + var pull = baseRest(pullAll); /** * This method is like `_.pull` except that it accepts an array of values to remove. @@ -6258,17 +7706,18 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @returns {Array} Returns `array`. * @example * - * var array = [1, 2, 3, 1, 2, 3]; + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; * - * _.pullAll(array, [2, 3]); + * _.pullAll(array, ['a', 'c']); * console.log(array); - * // => [1, 1] + * // => ['b', 'b'] */ function pullAll(array, values) { return (array && array.length && values && values.length) @@ -6279,16 +7728,17 @@ /** * This method is like `_.pullAll` except that it accepts `iteratee` which is * invoked for each element of `array` and `values` to generate the criterion - * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The iteratee is invoked with one argument: (value). * * **Note:** Unlike `_.differenceBy`, this method mutates `array`. * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to modify. * @param {Array} values The values to remove. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {Array} Returns `array`. * @example * @@ -6300,7 +7750,36 @@ */ function pullAllBy(array, values, iteratee) { return (array && array.length && values && values.length) - ? basePullAllBy(array, values, getIteratee(iteratee)) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) : array; } @@ -6312,27 +7791,30 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to modify. - * @param {...(number|number[])} [indexes] The indexes of elements to remove, - * specified individually or in arrays. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. * @returns {Array} Returns the new array of removed elements. * @example * - * var array = [5, 10, 15, 20]; - * var evens = _.pullAt(array, 1, 3); + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); * * console.log(array); - * // => [5, 15] + * // => ['a', 'c'] * - * console.log(evens); - * // => [10, 20] + * console.log(pulled); + * // => ['b', 'd'] */ - var pullAt = rest(function(array, indexes) { - indexes = arrayMap(baseFlatten(indexes, 1), String); + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); - var result = baseAt(array, indexes); - basePullAt(array, indexes.sort(compareAscending)); return result; }); @@ -6346,9 +7828,10 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Array * @param {Array} array The array to modify. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the new array of removed elements. * @example * @@ -6393,7 +7876,9 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array + * @param {Array} array The array to modify. * @returns {Array} Returns `array`. * @example * @@ -6406,17 +7891,19 @@ * // => [3, 2, 1] */ function reverse(array) { - return array ? nativeReverse.call(array) : array; + return array == null ? array : nativeReverse.call(array); } /** * Creates a slice of `array` from `start` up to, but not including, `end`. * - * **Note:** This method is used instead of [`Array#slice`](https://mdn.io/Array/slice) - * to ensure dense arrays are returned. + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to slice. * @param {number} [start=0] The start position. @@ -6424,7 +7911,7 @@ * @returns {Array} Returns the slice of `array`. */ function slice(array, start, end) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return []; } @@ -6440,22 +7927,21 @@ } /** - * Uses a binary search to determine the lowest index at which `value` should - * be inserted into `array` in order to maintain its sort order. + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * * _.sortedIndex([30, 50], 40); * // => 1 - * - * _.sortedIndex([4, 5], 4); - * // => 0 */ function sortedIndex(array, value) { return baseSortedIndex(array, value); @@ -6468,24 +7954,26 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. - * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * - * var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 }; + * var objects = [{ 'x': 4 }, { 'x': 5 }]; * - * _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict)); - * // => 1 + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 * * // The `_.property` iteratee shorthand. - * _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x'); + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); * // => 0 */ function sortedIndexBy(array, value, iteratee) { - return baseSortedIndexBy(array, value, getIteratee(iteratee)); + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); } /** @@ -6494,17 +7982,18 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example * - * _.sortedIndexOf([1, 1, 2, 2], 2); - * // => 2 + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 */ function sortedIndexOf(array, value) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (length) { var index = baseSortedIndex(array, value); if (index < length && eq(array[index], value)) { @@ -6521,14 +8010,16 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * - * _.sortedLastIndex([4, 5], 4); - * // => 1 + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 */ function sortedLastIndex(array, value) { return baseSortedIndex(array, value, true); @@ -6541,19 +8032,26 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. - * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. * @example * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * * // The `_.property` iteratee shorthand. - * _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x'); + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); * // => 1 */ function sortedLastIndexBy(array, value, iteratee) { - return baseSortedIndexBy(array, value, getIteratee(iteratee), true); + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); } /** @@ -6562,17 +8060,18 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example * - * _.sortedLastIndexOf([1, 1, 2, 2], 2); + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); * // => 3 */ function sortedLastIndexOf(array, value) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (length) { var index = baseSortedIndex(array, value, true) - 1; if (eq(array[index], value)) { @@ -6588,6 +8087,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @returns {Array} Returns the new duplicate free array. @@ -6608,6 +8108,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {Function} [iteratee] The iteratee invoked per element. @@ -6619,7 +8120,7 @@ */ function sortedUniqBy(array, iteratee) { return (array && array.length) - ? baseSortedUniqBy(array, getIteratee(iteratee)) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) : []; } @@ -6628,6 +8129,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. @@ -6637,7 +8139,8 @@ * // => [2, 3] */ function tail(array) { - return drop(array, 1); + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; } /** @@ -6645,10 +8148,11 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -6677,10 +8181,11 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -6697,7 +8202,7 @@ * // => [] */ function takeRight(array, n, guard) { - var length = array ? array.length : 0; + var length = array == null ? 0 : array.length; if (!length) { return []; } @@ -6708,14 +8213,15 @@ /** * Creates a slice of `array` with elements taken from the end. Elements are - * taken until `predicate` returns falsey. The predicate is invoked with three - * arguments: (value, index, array). + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * @@ -6753,15 +8259,16 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Array * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * * var users = [ * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false}, + * { 'user': 'fred', 'active': false }, * { 'user': 'pebbles', 'active': true } * ]; * @@ -6788,58 +8295,64 @@ /** * Creates an array of unique values, in order, from all given arrays using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of combined values. * @example * - * _.union([2, 1], [4, 2], [1, 2]); - * // => [2, 1, 4] + * _.union([2], [1, 2]); + * // => [2, 1] */ - var union = rest(function(arrays) { - return baseUniq(baseFlatten(arrays, 1, true)); + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); }); /** * This method is like `_.union` except that it accepts `iteratee` which is - * invoked for each element of each `arrays` to generate the criterion by which - * uniqueness is computed. The iteratee is invoked with one argument: (value). + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {Array} Returns the new array of combined values. * @example * - * _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor); - * // => [2.1, 1.2, 4.3] + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] * * // The `_.property` iteratee shorthand. * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ - var unionBy = rest(function(arrays) { + var unionBy = baseRest(function(arrays) { var iteratee = last(arrays); if (isArrayLikeObject(iteratee)) { iteratee = undefined; } - return baseUniq(baseFlatten(arrays, 1, true), getIteratee(iteratee)); + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); }); /** * This method is like `_.union` except that it accepts `comparator` which - * is invoked to compare elements of `arrays`. The comparator is invoked + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked * with two arguments: (arrVal, othVal). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. @@ -6852,22 +8365,22 @@ * _.unionWith(objects, others, _.isEqual); * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] */ - var unionWith = rest(function(arrays) { + var unionWith = baseRest(function(arrays) { var comparator = last(arrays); - if (isArrayLikeObject(comparator)) { - comparator = undefined; - } - return baseUniq(baseFlatten(arrays, 1, true), undefined, comparator); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); }); /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurrence of each element - * is kept. + * is kept. The order of result values is determined by the order they occur + * in the array. * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {Array} array The array to inspect. * @returns {Array} Returns the new duplicate free array. @@ -6877,21 +8390,22 @@ * // => [2, 1] */ function uniq(array) { - return (array && array.length) - ? baseUniq(array) - : []; + return (array && array.length) ? baseUniq(array) : []; } /** * This method is like `_.uniq` except that it accepts `iteratee` which is * invoked for each element in `array` to generate the criterion by which - * uniqueness is computed. The iteratee is invoked with one argument: (value). + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {Array} Returns the new duplicate free array. * @example * @@ -6903,33 +8417,32 @@ * // => [{ 'x': 1 }, { 'x': 2 }] */ function uniqBy(array, iteratee) { - return (array && array.length) - ? baseUniq(array, getIteratee(iteratee)) - : []; + return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; } /** * This method is like `_.uniq` except that it accepts `comparator` which - * is invoked to compare elements of `array`. The comparator is invoked with - * two arguments: (arrVal, othVal). + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new duplicate free array. * @example * - * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; * * _.uniqWith(objects, _.isEqual); * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] */ function uniqWith(array, comparator) { - return (array && array.length) - ? baseUniq(array, undefined, comparator) - : []; + comparator = typeof comparator == 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; } /** @@ -6939,16 +8452,17 @@ * * @static * @memberOf _ + * @since 1.2.0 * @category Array * @param {Array} array The array of grouped elements to process. * @returns {Array} Returns the new array of regrouped elements. * @example * - * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); - * // => [['fred', 30, true], ['barney', 40, false]] + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] * * _.unzip(zipped); - * // => [['fred', 'barney'], [30, 40], [true, false]] + * // => [['a', 'b'], [1, 2], [true, false]] */ function unzip(array) { if (!(array && array.length)) { @@ -6973,9 +8487,11 @@ * * @static * @memberOf _ + * @since 3.8.0 * @category Array * @param {Array} array The array of grouped elements to process. - * @param {Function} [iteratee=_.identity] The function to combine regrouped values. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. * @returns {Array} Returns the new array of regrouped elements. * @example * @@ -7000,83 +8516,96 @@ /** * Creates an array excluding all given values using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * + * **Note:** Unlike `_.pull`, this method returns a new array. + * * @static * @memberOf _ + * @since 0.1.0 * @category Array - * @param {Array} array The array to filter. + * @param {Array} array The array to inspect. * @param {...*} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor * @example * - * _.without([1, 2, 1, 3], 1, 2); + * _.without([2, 1, 2, 3], 1, 2); * // => [3] */ - var without = rest(function(array, values) { + var without = baseRest(function(array, values) { return isArrayLikeObject(array) ? baseDifference(array, values) : []; }); /** - * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) - * of the given arrays. + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. * * @static * @memberOf _ + * @since 2.4.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of values. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without * @example * - * _.xor([2, 1], [4, 2]); - * // => [1, 4] + * _.xor([2, 1], [2, 3]); + * // => [1, 3] */ - var xor = rest(function(arrays) { + var xor = baseRest(function(arrays) { return baseXor(arrayFilter(arrays, isArrayLikeObject)); }); /** * This method is like `_.xor` except that it accepts `iteratee` which is - * invoked for each element of each `arrays` to generate the criterion by which - * uniqueness is computed. The iteratee is invoked with one argument: (value). + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of values. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. * @example * - * _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor); - * // => [1.2, 4.3] + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] * * // The `_.property` iteratee shorthand. * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 2 }] */ - var xorBy = rest(function(arrays) { + var xorBy = baseRest(function(arrays) { var iteratee = last(arrays); if (isArrayLikeObject(iteratee)) { iteratee = undefined; } - return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee)); + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); }); /** * This method is like `_.xor` except that it accepts `comparator` which is - * invoked to compare elements of `arrays`. The comparator is invoked with - * two arguments: (arrVal, othVal). + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). * * @static * @memberOf _ + * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of values. + * @returns {Array} Returns the new array of filtered values. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; @@ -7085,39 +8614,39 @@ * _.xorWith(objects, others, _.isEqual); * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] */ - var xorWith = rest(function(arrays) { + var xorWith = baseRest(function(arrays) { var comparator = last(arrays); - if (isArrayLikeObject(comparator)) { - comparator = undefined; - } + comparator = typeof comparator == 'function' ? comparator : undefined; return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); }); /** - * Creates an array of grouped elements, the first of which contains the first - * elements of the given arrays, the second of which contains the second elements - * of the given arrays, and so on. + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. * * @static * @memberOf _ + * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to process. * @returns {Array} Returns the new array of grouped elements. * @example * - * _.zip(['fred', 'barney'], [30, 40], [true, false]); - * // => [['fred', 30, true], ['barney', 40, false]] + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] */ - var zip = rest(unzip); + var zip = baseRest(unzip); /** * This method is like `_.fromPairs` except that it accepts two arrays, - * one of property names and one of corresponding values. + * one of property identifiers and one of corresponding values. * * @static * @memberOf _ + * @since 0.4.0 * @category Array - * @param {Array} [props=[]] The property names. + * @param {Array} [props=[]] The property identifiers. * @param {Array} [values=[]] The property values. * @returns {Object} Returns the new object. * @example @@ -7134,8 +8663,9 @@ * * @static * @memberOf _ + * @since 4.1.0 * @category Array - * @param {Array} [props=[]] The property names. + * @param {Array} [props=[]] The property identifiers. * @param {Array} [values=[]] The property values. * @returns {Object} Returns the new object. * @example @@ -7154,9 +8684,11 @@ * * @static * @memberOf _ + * @since 3.8.0 * @category Array * @param {...Array} [arrays] The arrays to process. - * @param {Function} [iteratee=_.identity] The function to combine grouped values. + * @param {Function} [iteratee=_.identity] The function to combine + * grouped values. * @returns {Array} Returns the new array of grouped elements. * @example * @@ -7165,7 +8697,7 @@ * }); * // => [111, 222] */ - var zipWith = rest(function(arrays) { + var zipWith = baseRest(function(arrays) { var length = arrays.length, iteratee = length > 1 ? arrays[length - 1] : undefined; @@ -7176,11 +8708,13 @@ /*------------------------------------------------------------------------*/ /** - * Creates a `lodash` object that wraps `value` with explicit method chaining enabled. - * The result of such method chaining must be unwrapped with `_#value`. + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. * * @static * @memberOf _ + * @since 1.3.0 * @category Seq * @param {*} value The value to wrap. * @returns {Object} Returns the new `lodash` wrapper instance. @@ -7211,10 +8745,11 @@ /** * This method invokes `interceptor` and returns `value`. The interceptor * is invoked with one argument; (value). The purpose of this method is to - * "tap into" a method chain in order to modify intermediate results. + * "tap into" a method chain sequence in order to modify intermediate results. * * @static * @memberOf _ + * @since 0.1.0 * @category Seq * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. @@ -7238,10 +8773,11 @@ /** * This method is like `_.tap` except that it returns the result of `interceptor`. * The purpose of this method is to "pass thru" values replacing intermediate - * results in a method chain. + * results in a method chain sequence. * * @static * @memberOf _ + * @since 3.0.0 * @category Seq * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. @@ -7266,9 +8802,9 @@ * * @name at * @memberOf _ + * @since 1.0.0 * @category Seq - * @param {...(string|string[])} [paths] The property paths of elements to pick, - * specified individually or in arrays. + * @param {...(string|string[])} [paths] The property paths to pick. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * @@ -7276,12 +8812,8 @@ * * _(object).at(['a[0].b.c', 'a[1]']).value(); * // => [3, 4] - * - * _(['a', 'b', 'c']).at(0, 2).value(); - * // => ['a', 'c'] */ - var wrapperAt = rest(function(paths) { - paths = baseFlatten(paths, 1); + var wrapperAt = flatRest(function(paths) { var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, @@ -7306,10 +8838,11 @@ }); /** - * Enables explicit method chaining on the wrapper object. + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. * * @name chain * @memberOf _ + * @since 0.1.0 * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example @@ -7336,10 +8869,11 @@ } /** - * Executes the chained sequence and returns the wrapped result. + * Executes the chain sequence and returns the wrapped result. * * @name commit * @memberOf _ + * @since 3.2.0 * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example @@ -7365,32 +8899,12 @@ } /** - * This method is the wrapper version of `_.flatMap`. - * - * @name flatMap - * @memberOf _ - * @category Seq - * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * function duplicate(n) { - * return [n, n]; - * } - * - * _([1, 2]).flatMap(duplicate).value(); - * // => [1, 1, 2, 2] - */ - function wrapperFlatMap(iteratee) { - return this.map(iteratee).flatten(); - } - - /** * Gets the next value on a wrapped object following the * [iterator protocol](https://mdn.io/iteration_protocols#iterator). * * @name next * @memberOf _ + * @since 4.0.0 * @category Seq * @returns {Object} Returns the next iterator value. * @example @@ -7421,6 +8935,7 @@ * * @name Symbol.iterator * @memberOf _ + * @since 4.0.0 * @category Seq * @returns {Object} Returns the wrapper object. * @example @@ -7438,10 +8953,11 @@ } /** - * Creates a clone of the chained sequence planting `value` as the wrapped value. + * Creates a clone of the chain sequence planting `value` as the wrapped value. * * @name plant * @memberOf _ + * @since 3.2.0 * @category Seq * @param {*} value The value to plant. * @returns {Object} Returns the new `lodash` wrapper instance. @@ -7487,6 +9003,7 @@ * * @name reverse * @memberOf _ + * @since 0.1.0 * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example @@ -7518,10 +9035,11 @@ } /** - * Executes the chained sequence to extract the unwrapped value. + * Executes the chain sequence to resolve the unwrapped value. * * @name value * @memberOf _ + * @since 0.1.0 * @alias toJSON, valueOf * @category Seq * @returns {*} Returns the resolved unwrapped value. @@ -7538,26 +9056,32 @@ /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iteratee`. The corresponding value - * of each key is the number of times the key was returned by `iteratee`. - * The iteratee is invoked with one argument: (value). + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). * * @static * @memberOf _ + * @since 0.5.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * * _.countBy([6.1, 4.2, 6.3], Math.floor); * // => { '4': 1, '6': 2 } * + * // The `_.property` iteratee shorthand. * _.countBy(['one', 'two', 'three'], 'length'); * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { - hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } }); /** @@ -7565,21 +9089,28 @@ * Iteration is stopped once `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index|key, collection). * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. - * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. * @example * * _.every([true, 1, null, 'yes'], Boolean); * // => false * * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false } + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } * ]; * * // The `_.matches` iteratee shorthand. @@ -7604,15 +9135,19 @@ /** * Iterates over elements of `collection`, returning an array of all elements - * `predicate` returns truthy for. The predicate is invoked with three arguments: - * (value, index|key, collection). + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the new filtered array. + * @see _.reject * @example * * var users = [ @@ -7642,14 +9177,16 @@ /** * Iterates over elements of `collection`, returning the first element - * `predicate` returns truthy for. The predicate is invoked with three arguments: - * (value, index|key, collection). + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). * * @static * @memberOf _ + * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. * @returns {*} Returns the matched element, else `undefined`. * @example * @@ -7674,14 +9211,7 @@ * _.find(users, 'active'); * // => object for 'barney' */ - function find(collection, predicate) { - predicate = getIteratee(predicate, 3); - if (isArray(collection)) { - var index = baseFindIndex(collection, predicate); - return index > -1 ? collection[index] : undefined; - } - return baseFind(collection, predicate, baseEach); - } + var find = createFind(findIndex); /** * This method is like `_.find` except that it iterates over elements of @@ -7689,9 +9219,11 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Collection - * @param {Array|Object} collection The collection to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. * @returns {*} Returns the matched element, else `undefined`. * @example * @@ -7700,25 +9232,19 @@ * }); * // => 3 */ - function findLast(collection, predicate) { - predicate = getIteratee(predicate, 3); - if (isArray(collection)) { - var index = baseFindIndex(collection, predicate, true); - return index > -1 ? collection[index] : undefined; - } - return baseFind(collection, predicate, baseEachRight); - } + var findLast = createFind(findLastIndex); /** - * Creates an array of flattened values by running each element in `collection` - * through `iteratee` and concating its result to the other mapped values. - * The iteratee is invoked with three arguments: (value, index|key, collection). + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). * * @static * @memberOf _ + * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array} Returns the new flattened array. * @example * @@ -7734,37 +9260,88 @@ } /** - * Iterates over elements of `collection` invoking `iteratee` for each element. + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. * The iteratee is invoked with three arguments: (value, index|key, collection). * Iteratee functions may exit iteration early by explicitly returning `false`. * - * **Note:** As with other "Collections" methods, objects with a "length" property - * are iterated like arrays. To avoid this behavior use `_.forIn` or `_.forOwn` - * for object iteration. + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. * * @static * @memberOf _ + * @since 0.1.0 * @alias each * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight * @example * - * _([1, 2]).forEach(function(value) { + * _.forEach([1, 2], function(value) { * console.log(value); * }); - * // => logs `1` then `2` + * // => Logs `1` then `2`. * * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { * console.log(key); * }); - * // => logs 'a' then 'b' (iteration order is not guaranteed) + * // => Logs 'a' then 'b' (iteration order is not guaranteed). */ function forEach(collection, iteratee) { - return (typeof iteratee == 'function' && isArray(collection)) - ? arrayEach(collection, iteratee) - : baseEach(collection, baseCastFunction(iteratee)); + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); } /** @@ -7773,35 +9350,38 @@ * * @static * @memberOf _ + * @since 2.0.0 * @alias eachRight * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array|Object} Returns `collection`. + * @see _.forEach * @example * * _.forEachRight([1, 2], function(value) { * console.log(value); * }); - * // => logs `2` then `1` + * // => Logs `2` then `1`. */ function forEachRight(collection, iteratee) { - return (typeof iteratee == 'function' && isArray(collection)) - ? arrayEachRight(collection, iteratee) - : baseEachRight(collection, baseCastFunction(iteratee)); + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); } /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iteratee`. The corresponding value - * of each key is an array of elements responsible for generating the key. - * The iteratee is invoked with one argument: (value). + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * @@ -7816,23 +9396,25 @@ if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { - result[key] = [value]; + baseAssignValue(result, key, [value]); } }); /** - * Checks if `value` is in `collection`. If `collection` is a string it's checked - * for a substring of `value`, otherwise [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * is used for equality comparisons. If `fromIndex` is negative, it's used as * the offset from the end of `collection`. * * @static * @memberOf _ + * @since 0.1.0 * @category Collection - * @param {Array|Object|string} collection The collection to search. + * @param {Array|Object|string} collection The collection to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. * @returns {boolean} Returns `true` if `value` is found, else `false`. * @example * @@ -7842,10 +9424,10 @@ * _.includes([1, 2, 3], 1, 2); * // => false * - * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); + * _.includes({ 'a': 1, 'b': 2 }, 1); * // => true * - * _.includes('pebbles', 'eb'); + * _.includes('abcd', 'bc'); * // => true */ function includes(collection, value, fromIndex, guard) { @@ -7864,11 +9446,12 @@ /** * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments - * are provided to each invoked method. If `methodName` is a function it's - * invoked for, and `this` bound to, each element in `collection`. + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. * * @static * @memberOf _ + * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|string} path The path of the method to invoke or @@ -7883,30 +9466,29 @@ * _.invokeMap([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ - var invokeMap = rest(function(collection, path, args) { + var invokeMap = baseRest(function(collection, path, args) { var index = -1, isFunc = typeof path == 'function', - isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); - result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args); + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); }); return result; }); /** * Creates an object composed of keys generated from the results of running - * each element of `collection` through `iteratee`. The corresponding value - * of each key is the last element responsible for generating the key. The + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The * iteratee is invoked with one argument: (value). * * @static * @memberOf _ + * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * @@ -7924,11 +9506,11 @@ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { - result[key] = value; + baseAssignValue(result, key, value); }); /** - * Creates an array of values by running each element in `collection` through + * Creates an array of values by running each element in `collection` thru * `iteratee`. The iteratee is invoked with three arguments: * (value, index|key, collection). * @@ -7936,16 +9518,17 @@ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. * * The guarded methods are: - * `ary`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, `fill`, - * `invert`, `parseInt`, `random`, `range`, `rangeRight`, `slice`, `some`, - * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimEnd`, `trimStart`, - * and `words` + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array} Returns the new mapped array. * @example * @@ -7981,24 +9564,26 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function[]|Object[]|string[]} [iteratees=[_.identity]] The iteratees to sort by. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. * @param {string[]} [orders] The sort orders of `iteratees`. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. * @returns {Array} Returns the new sorted array. * @example * * var users = [ * { 'user': 'fred', 'age': 48 }, * { 'user': 'barney', 'age': 34 }, - * { 'user': 'fred', 'age': 42 }, + * { 'user': 'fred', 'age': 40 }, * { 'user': 'barney', 'age': 36 } * ]; * * // Sort by `user` in ascending order and by `age` in descending order. * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] */ function orderBy(collection, iteratees, orders, guard) { if (collection == null) { @@ -8022,9 +9607,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the array of grouped elements. * @example * @@ -8055,9 +9641,9 @@ /** * Reduces `collection` to a value which is the accumulated result of running - * each element in `collection` through `iteratee`, where each successive + * each element in `collection` thru `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` - * is not given the first element of `collection` is used as the initial + * is not given, the first element of `collection` is used as the initial * value. The iteratee is invoked with four arguments: * (accumulator, value, index|key, collection). * @@ -8070,11 +9656,13 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @returns {*} Returns the accumulated value. + * @see _.reduceRight * @example * * _.reduce([1, 2], function(sum, n) { @@ -8101,11 +9689,13 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @returns {*} Returns the accumulated value. + * @see _.reduce * @example * * var array = [[0, 1], [2, 3], [4, 5]]; @@ -8128,10 +9718,12 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the new filtered array. + * @see _.filter * @example * * var users = [ @@ -8156,10 +9748,7 @@ */ function reject(collection, predicate) { var func = isArray(collection) ? arrayFilter : baseFilter; - predicate = getIteratee(predicate, 3); - return func(collection, function(value, index, collection) { - return !predicate(value, index, collection); - }); + return func(collection, negate(getIteratee(predicate, 3))); } /** @@ -8167,6 +9756,7 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Collection * @param {Array|Object} collection The collection to sample. * @returns {*} Returns the random element. @@ -8176,10 +9766,8 @@ * // => 2 */ function sample(collection) { - var array = isArrayLike(collection) ? collection : values(collection), - length = array.length; - - return length > 0 ? array[baseRandom(0, length - 1)] : undefined; + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); } /** @@ -8188,9 +9776,11 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to sample. - * @param {number} [n=0] The number of elements to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the random elements. * @example * @@ -8200,22 +9790,14 @@ * _.sampleSize([1, 2, 3], 4); * // => [2, 3, 1] */ - function sampleSize(collection, n) { - var index = -1, - result = toArray(collection), - length = result.length, - lastIndex = length - 1; - - n = baseClamp(toInteger(n), 0, length); - while (++index < n) { - var rand = baseRandom(index, lastIndex), - value = result[rand]; - - result[rand] = result[index]; - result[index] = value; + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); } - result.length = n; - return result; + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); } /** @@ -8224,6 +9806,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to shuffle. * @returns {Array} Returns the new shuffled array. @@ -8233,17 +9816,19 @@ * // => [4, 1, 3, 2] */ function shuffle(collection) { - return sampleSize(collection, MAX_ARRAY_LENGTH); + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); } /** * Gets the size of `collection` by returning its length for array-like - * values or the number of own enumerable properties for objects. + * values or the number of own enumerable string keyed properties for objects. * * @static * @memberOf _ + * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to inspect. + * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns the collection size. * @example * @@ -8261,10 +9846,13 @@ return 0; } if (isArrayLike(collection)) { - var result = collection.length; - return (result && isString(collection)) ? stringSize(collection) : result; + return isString(collection) ? stringSize(collection) : collection.length; } - return keys(collection).length; + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; } /** @@ -8274,11 +9862,13 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. - * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. * @example * * _.some([null, 0, 'yes', false], Boolean); @@ -8311,38 +9901,34 @@ /** * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through each iteratee. This method + * running each element in a collection thru each iteratee. This method * performs a stable sort, that is, it preserves the original sort order of * equal elements. The iteratees are invoked with one argument: (value). * * @static * @memberOf _ + * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {...(Function|Function[]|Object|Object[]|string|string[])} [iteratees=[_.identity]] - * The iteratees to sort by, specified individually or in arrays. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. * @returns {Array} Returns the new sorted array. * @example * * var users = [ * { 'user': 'fred', 'age': 48 }, * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 42 }, + * { 'user': 'fred', 'age': 40 }, * { 'user': 'barney', 'age': 34 } * ]; * - * _.sortBy(users, function(o) { return o.user; }); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] * * _.sortBy(users, ['user', 'age']); - * // => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]] - * - * _.sortBy(users, 'user', function(o) { - * return Math.floor(o.age / 10); - * }); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] + * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] */ - var sortBy = rest(function(collection, iteratees) { + var sortBy = baseRest(function(collection, iteratees) { if (collection == null) { return []; } @@ -8350,7 +9936,7 @@ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { iteratees = []; } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { - iteratees.length = 1; + iteratees = [iteratees[0]]; } return baseOrderBy(collection, baseFlatten(iteratees, 1), []); }); @@ -8363,7 +9949,7 @@ * * @static * @memberOf _ - * @type {Function} + * @since 2.4.0 * @category Date * @returns {number} Returns the timestamp. * @example @@ -8371,9 +9957,11 @@ * _.defer(function(stamp) { * console.log(_.now() - stamp); * }, _.now()); - * // => logs the number of milliseconds it took for the deferred function to be invoked + * // => Logs the number of milliseconds it took for the deferred invocation. */ - var now = Date.now; + var now = ctxNow || function() { + return root.Date.now(); + }; /*------------------------------------------------------------------------*/ @@ -8383,6 +9971,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. @@ -8398,7 +9987,7 @@ * _.forEach(saves, function(type) { * asyncSave({ 'type': type, 'complete': done }); * }); - * // => logs 'done saving!' after the two async saves have completed + * // => Logs 'done saving!' after the two async saves have completed. */ function after(n, func) { if (typeof func != 'function') { @@ -8413,16 +10002,17 @@ } /** - * Creates a function that accepts up to `n` arguments, ignoring any - * additional arguments. + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. * * @static * @memberOf _ + * @since 3.0.0 * @category Function * @param {Function} func The function to cap arguments for. * @param {number} [n=func.length] The arity cap. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. - * @returns {Function} Returns the new function. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. * @example * * _.map(['6', '8', '10'], _.ary(parseInt, 1)); @@ -8431,7 +10021,7 @@ function ary(func, n, guard) { n = guard ? undefined : n; n = (func && n == null) ? func.length : n; - return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); } /** @@ -8441,6 +10031,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Function * @param {number} n The number of calls at which `func` is no longer invoked. * @param {Function} func The function to restrict. @@ -8448,7 +10039,7 @@ * @example * * jQuery(element).on('click', _.before(5, addContactToList)); - * // => allows adding up to 4 contacts to the list + * // => Allows adding up to 4 contacts to the list. */ function before(n, func) { var result; @@ -8469,17 +10060,17 @@ /** * Creates a function that invokes `func` with the `this` binding of `thisArg` - * and prepends any additional `_.bind` arguments to those provided to the - * bound function. + * and `partials` prepended to the arguments it receives. * * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for partially applied arguments. * - * **Note:** Unlike native `Function#bind` this method doesn't set the "length" + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" * property of bound functions. * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. @@ -8487,9 +10078,9 @@ * @returns {Function} Returns the new bound function. * @example * - * var greet = function(greeting, punctuation) { + * function greet(greeting, punctuation) { * return greeting + ' ' + this.user + punctuation; - * }; + * } * * var object = { 'user': 'fred' }; * @@ -8502,22 +10093,22 @@ * bound('hi'); * // => 'hi fred!' */ - var bind = rest(function(func, thisArg, partials) { - var bitmask = BIND_FLAG; + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; if (partials.length) { - var holders = replaceHolders(partials, getPlaceholder(bind)); - bitmask |= PARTIAL_FLAG; + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; } - return createWrapper(func, bitmask, thisArg, partials, holders); + return createWrap(func, bitmask, thisArg, partials, holders); }); /** - * Creates a function that invokes the method at `object[key]` and prepends - * any additional `_.bindKey` arguments to those provided to the bound function. + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. * * This method differs from `_.bind` by allowing bound functions to reference - * methods that may be redefined or don't yet exist. - * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) * for more details. * * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic @@ -8525,6 +10116,7 @@ * * @static * @memberOf _ + * @since 0.10.0 * @category Function * @param {Object} object The object to invoke the method on. * @param {string} key The key of the method. @@ -8555,13 +10147,13 @@ * bound('hi'); * // => 'hiya fred!' */ - var bindKey = rest(function(object, key, partials) { - var bitmask = BIND_FLAG | BIND_KEY_FLAG; + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; if (partials.length) { - var holders = replaceHolders(partials, getPlaceholder(bindKey)); - bitmask |= PARTIAL_FLAG; + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; } - return createWrapper(key, bitmask, object, partials, holders); + return createWrap(key, bitmask, object, partials, holders); }); /** @@ -8578,10 +10170,11 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the new curried function. * @example * @@ -8606,7 +10199,7 @@ */ function curry(func, arity, guard) { arity = guard ? undefined : arity; - var result = createWrapper(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curry.placeholder; return result; } @@ -8622,10 +10215,11 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the new curried function. * @example * @@ -8650,7 +10244,7 @@ */ function curryRight(func, arity, guard) { arity = guard ? undefined : arity; - var result = createWrapper(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curryRight.placeholder; return result; } @@ -8660,30 +10254,35 @@ * milliseconds have elapsed since the last time the debounced function was * invoked. The debounced function comes with a `cancel` method to cancel * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide an options object to indicate whether `func` should be invoked on - * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. Subsequent calls - * to the debounced function return the result of the last `func` invocation. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. * - * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked - * on the trailing edge of the timeout only if the debounced function is - * invoked more than once during the `wait` timeout. + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. * - * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to debounce. * @param {number} [wait=0] The number of milliseconds to delay. - * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify invoking on the leading - * edge of the timeout. - * @param {number} [options.maxWait] The maximum time `func` is allowed to be - * delayed before it's invoked. - * @param {boolean} [options.trailing=true] Specify invoking on the trailing - * edge of the timeout. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * @@ -8705,16 +10304,15 @@ * jQuery(window).on('popstate', debounced.cancel); */ function debounce(func, wait, options) { - var args, - maxTimeoutId, + var lastArgs, + lastThis, + maxWait, result, - stamp, - thisArg, - timeoutId, - trailingCall, - lastCalled = 0, + timerId, + lastCallTime, + lastInvokeTime = 0, leading = false, - maxWait = false, + maxing = false, trailing = true; if (typeof func != 'function') { @@ -8723,96 +10321,104 @@ wait = toNumber(wait) || 0; if (isObject(options)) { leading = !!options.leading; - maxWait = 'maxWait' in options && nativeMax(toNumber(options.maxWait) || 0, wait); + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; trailing = 'trailing' in options ? !!options.trailing : trailing; } - function cancel() { - if (timeoutId) { - clearTimeout(timeoutId); - } - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - lastCalled = 0; - args = maxTimeoutId = thisArg = timeoutId = trailingCall = undefined; + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; } - function complete(isCalled, id) { - if (id) { - clearTimeout(id); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = undefined; - } - } + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; } - function delayed() { - var remaining = wait - (now() - stamp); - if (remaining <= 0 || remaining > wait) { - complete(trailingCall, maxTimeoutId); - } else { - timeoutId = setTimeout(delayed, remaining); + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); } - function flush() { - if ((timeoutId && trailingCall) || (maxTimeoutId && trailing)) { - result = func.apply(thisArg, args); + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); } - cancel(); + lastArgs = lastThis = undefined; return result; } - function maxDelayed() { - complete(trailing, timeoutId); + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; } - function debounced() { - args = arguments; - stamp = now(); - thisArg = this; - trailingCall = trailing && (timeoutId || !leading); + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } - if (maxWait === false) { - var leadingCall = leading && !timeoutId; - } else { - if (!lastCalled && !maxTimeoutId && !leading) { - lastCalled = stamp; - } - var remaining = maxWait - (stamp - lastCalled); + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); - var isCalled = (remaining <= 0 || remaining > maxWait) && - (leading || maxTimeoutId); + lastArgs = arguments; + lastThis = this; + lastCallTime = time; - if (isCalled) { - if (maxTimeoutId) { - maxTimeoutId = clearTimeout(maxTimeoutId); - } - lastCalled = stamp; - result = func.apply(thisArg, args); + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); } - else if (!maxTimeoutId) { - maxTimeoutId = setTimeout(maxDelayed, remaining); + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); } } - if (isCalled && timeoutId) { - timeoutId = clearTimeout(timeoutId); - } - else if (!timeoutId && wait !== maxWait) { - timeoutId = setTimeout(delayed, wait); - } - if (leadingCall) { - isCalled = true; - result = func.apply(thisArg, args); - } - if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = undefined; + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); } return result; } @@ -8827,6 +10433,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to defer. * @param {...*} [args] The arguments to invoke `func` with. @@ -8836,9 +10443,9 @@ * _.defer(function(text) { * console.log(text); * }, 'deferred'); - * // => logs 'deferred' after one or more milliseconds + * // => Logs 'deferred' after one millisecond. */ - var defer = rest(function(func, args) { + var defer = baseRest(function(func, args) { return baseDelay(func, 1, args); }); @@ -8848,6 +10455,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. @@ -8858,9 +10466,9 @@ * _.delay(function(text) { * console.log(text); * }, 1000, 'later'); - * // => logs 'later' after one second + * // => Logs 'later' after one second. */ - var delay = rest(function(func, wait, args) { + var delay = baseRest(function(func, wait, args) { return baseDelay(func, toNumber(wait) || 0, args); }); @@ -8869,9 +10477,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Function * @param {Function} func The function to flip arguments for. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new flipped function. * @example * * var flipped = _.flip(function() { @@ -8882,27 +10491,29 @@ * // => ['d', 'c', 'b', 'a'] */ function flip(func) { - return createWrapper(func, FLIP_FLAG); + return createWrap(func, WRAP_FLIP_FLAG); } /** * Creates a function that memoizes the result of `func`. If `resolver` is - * provided it determines the cache key for storing the result based on the + * provided, it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the map cache key. The `func` * is invoked with the `this` binding of the memoized function. * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) - * method interface of `delete`, `get`, `has`, and `set`. + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] The function to resolve the cache key. - * @returns {Function} Returns the new memoizing function. + * @returns {Function} Returns the new memoized function. * @example * * var object = { 'a': 1, 'b': 2 }; @@ -8928,7 +10539,7 @@ * _.memoize.Cache = WeakMap; */ function memoize(func, resolver) { - if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { @@ -8940,13 +10551,16 @@ return cache.get(key); } var result = func.apply(this, args); - memoized.cache = cache.set(key, result); + memoized.cache = cache.set(key, result) || cache; return result; }; - memoized.cache = new memoize.Cache; + memoized.cache = new (memoize.Cache || MapCache); return memoized; } + // Expose `MapCache`. + memoize.Cache = MapCache; + /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the @@ -8954,9 +10568,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Function * @param {Function} predicate The predicate to negate. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new negated function. * @example * * function isEven(n) { @@ -8971,7 +10586,14 @@ throw new TypeError(FUNC_ERROR_TEXT); } return function() { - return !predicate.apply(this, arguments); + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); }; } @@ -8982,6 +10604,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. @@ -8990,22 +10613,22 @@ * var initialize = _.once(createApplication); * initialize(); * initialize(); - * // `initialize` invokes `createApplication` once + * // => `createApplication` is invoked once */ function once(func) { return before(2, func); } /** - * Creates a function that invokes `func` with arguments transformed by - * corresponding `transforms`. + * Creates a function that invokes `func` with its arguments transformed. * * @static + * @since 4.0.0 * @memberOf _ * @category Function * @param {Function} func The function to wrap. - * @param {...(Function|Function[])} [transforms] The functions to transform - * arguments, specified individually or in arrays. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. * @returns {Function} Returns the new function. * @example * @@ -9019,7 +10642,7 @@ * * var func = _.overArgs(function(x, y) { * return [x, y]; - * }, square, doubled); + * }, [square, doubled]); * * func(9, 3); * // => [81, 6] @@ -9027,11 +10650,13 @@ * func(10, 5); * // => [100, 10] */ - var overArgs = rest(function(func, transforms) { - transforms = arrayMap(baseFlatten(transforms, 1), getIteratee()); + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); var funcsLength = transforms.length; - return rest(function(args) { + return baseRest(function(args) { var index = -1, length = nativeMin(args.length, funcsLength); @@ -9043,9 +10668,9 @@ }); /** - * Creates a function that invokes `func` with `partial` arguments prepended - * to those provided to the new function. This method is like `_.bind` except - * it does **not** alter the `this` binding. + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. * * The `_.partial.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. @@ -9055,15 +10680,16 @@ * * @static * @memberOf _ + * @since 0.2.0 * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * - * var greet = function(greeting, name) { + * function greet(greeting, name) { * return greeting + ' ' + name; - * }; + * } * * var sayHelloTo = _.partial(greet, 'hello'); * sayHelloTo('fred'); @@ -9074,14 +10700,14 @@ * greetFred('hi'); * // => 'hi fred' */ - var partial = rest(function(func, partials) { - var holders = replaceHolders(partials, getPlaceholder(partial)); - return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders); + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); }); /** * This method is like `_.partial` except that partially applied arguments - * are appended to those provided to the new function. + * are appended to the arguments it receives. * * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. @@ -9091,15 +10717,16 @@ * * @static * @memberOf _ + * @since 1.0.0 * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * - * var greet = function(greeting, name) { + * function greet(greeting, name) { * return greeting + ' ' + name; - * }; + * } * * var greetFred = _.partialRight(greet, 'fred'); * greetFred('hi'); @@ -9110,45 +10737,48 @@ * sayHelloTo('fred'); * // => 'hello fred' */ - var partialRight = rest(function(func, partials) { - var holders = replaceHolders(partials, getPlaceholder(partialRight)); - return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders); + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); }); /** * Creates a function that invokes `func` with arguments arranged according - * to the specified indexes where the argument value at the first index is + * to the specified `indexes` where the argument value at the first index is * provided as the first argument, the argument value at the second index is * provided as the second argument, and so on. * * @static * @memberOf _ + * @since 3.0.0 * @category Function * @param {Function} func The function to rearrange arguments for. - * @param {...(number|number[])} indexes The arranged argument indexes, - * specified individually or in arrays. + * @param {...(number|number[])} indexes The arranged argument indexes. * @returns {Function} Returns the new function. * @example * * var rearged = _.rearg(function(a, b, c) { * return [a, b, c]; - * }, 2, 0, 1); + * }, [2, 0, 1]); * * rearged('b', 'c', 'a') * // => ['a', 'b', 'c'] */ - var rearg = rest(function(func, indexes) { - return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1)); + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); }); /** * Creates a function that invokes `func` with the `this` binding of the - * created function and arguments from `start` and beyond provided as an array. + * created function and arguments from `start` and beyond provided as + * an array. * - * **Note:** This method is based on the [rest parameter](https://mdn.io/rest_parameters). + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). * * @static * @memberOf _ + * @since 4.0.0 * @category Function * @param {Function} func The function to apply a rest parameter to. * @param {number} [start=func.length-1] The start position of the rest parameter. @@ -9167,39 +10797,21 @@ if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; - } - switch (start) { - case 0: return func.call(this, array); - case 1: return func.call(this, args[0], array); - case 2: return func.call(this, args[0], args[1], array); - } - var otherArgs = Array(start + 1); - index = -1; - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = array; - return apply(func, this, otherArgs); - }; + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); } /** - * Creates a function that invokes `func` with the `this` binding of the created - * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3). + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). * - * **Note:** This method is based on the [spread operator](https://mdn.io/spread_operator). + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). * * @static * @memberOf _ + * @since 3.2.0 * @category Function * @param {Function} func The function to spread arguments over. * @param {number} [start=0] The start position of the spread. @@ -9227,10 +10839,10 @@ if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - start = start === undefined ? 0 : nativeMax(toInteger(start), 0); - return rest(function(args) { + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { var array = args[start], - otherArgs = args.slice(0, start); + otherArgs = castSlice(args, 0, start); if (array) { arrayPush(otherArgs, array); @@ -9243,29 +10855,33 @@ * Creates a throttled function that only invokes `func` at most once per * every `wait` milliseconds. The throttled function comes with a `cancel` * method to cancel delayed `func` invocations and a `flush` method to - * immediately invoke them. Provide an options object to indicate whether - * `func` should be invoked on the leading and/or trailing edge of the `wait` + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` * timeout. The `func` is invoked with the last arguments provided to the * throttled function. Subsequent calls to the throttled function return the * result of the last `func` invocation. * - * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked - * on the trailing edge of the timeout only if the throttled function is - * invoked more than once during the `wait` timeout. + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. * - * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `_.throttle` and `_.debounce`. * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {Function} func The function to throttle. * @param {number} [wait=0] The number of milliseconds to throttle invocations to. - * @param {Object} [options] The options object. - * @param {boolean} [options.leading=true] Specify invoking on the leading - * edge of the timeout. - * @param {boolean} [options.trailing=true] Specify invoking on the trailing - * edge of the timeout. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * @@ -9303,9 +10919,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Function * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new capped function. * @example * * _.map(['6', '8', '10'], _.unary(parseInt)); @@ -9316,13 +10933,14 @@ } /** - * Creates a function that provides `value` to the wrapper function as its - * first argument. Any additional arguments provided to the function are - * appended to those provided to the wrapper function. The wrapper is invoked - * with the `this` binding of the created function. + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. * * @static * @memberOf _ + * @since 0.1.0 * @category Function * @param {*} value The value to wrap. * @param {Function} [wrapper=identity] The wrapper function. @@ -9337,8 +10955,7 @@ * // => '<p>fred, barney, & pebbles</p>' */ function wrap(value, wrapper) { - wrapper = wrapper == null ? identity : wrapper; - return partial(wrapper, value); + return partial(castFunction(wrapper), value); } /*------------------------------------------------------------------------*/ @@ -9348,6 +10965,7 @@ * * @static * @memberOf _ + * @since 4.4.0 * @category Lang * @param {*} value The value to inspect. * @returns {Array} Returns the cast array. @@ -9396,9 +11014,11 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to clone. * @returns {*} Returns the cloned value. + * @see _.cloneDeep * @example * * var objects = [{ 'a': 1 }, { 'b': 2 }]; @@ -9408,21 +11028,23 @@ * // => true */ function clone(value) { - return baseClone(value); + return baseClone(value, CLONE_SYMBOLS_FLAG); } /** * This method is like `_.clone` except that it accepts `customizer` which - * is invoked to produce the cloned value. If `customizer` returns `undefined` + * is invoked to produce the cloned value. If `customizer` returns `undefined`, * cloning is handled by the method instead. The `customizer` is invoked with * up to four arguments; (value [, index|key, object, stack]). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to clone. * @param {Function} [customizer] The function to customize cloning. * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith * @example * * function customizer(value) { @@ -9441,7 +11063,8 @@ * // => 0 */ function cloneWith(value, customizer) { - return baseClone(value, false, customizer); + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); } /** @@ -9449,9 +11072,11 @@ * * @static * @memberOf _ + * @since 1.0.0 * @category Lang * @param {*} value The value to recursively clone. * @returns {*} Returns the deep cloned value. + * @see _.clone * @example * * var objects = [{ 'a': 1 }, { 'b': 2 }]; @@ -9461,7 +11086,7 @@ * // => false */ function cloneDeep(value) { - return baseClone(value, true); + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); } /** @@ -9469,10 +11094,12 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to recursively clone. * @param {Function} [customizer] The function to customize cloning. * @returns {*} Returns the deep cloned value. + * @see _.cloneWith * @example * * function customizer(value) { @@ -9491,23 +11118,54 @@ * // => 20 */ function cloneDeepWith(value, customizer) { - return baseClone(value, true, customizer); + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); } /** - * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * - * var object = { 'user': 'fred' }; - * var other = { 'user': 'fred' }; + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; * * _.eq(object, object); * // => true @@ -9533,10 +11191,13 @@ * * @static * @memberOf _ + * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt * @example * * _.gt(3, 1); @@ -9548,19 +11209,20 @@ * _.gt(1, 3); * // => false */ - function gt(value, other) { - return value > other; - } + var gt = createRelationalOperation(baseGt); /** * Checks if `value` is greater than or equal to `other`. * * @static * @memberOf _ + * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte * @example * * _.gte(3, 1); @@ -9572,18 +11234,20 @@ * _.gte(1, 3); * // => false */ - function gte(value, other) { + var gte = createRelationalOperation(function(value, other) { return value >= other; - } + }); /** * Checks if `value` is likely an `arguments` object. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. * @example * * _.isArguments(function() { return arguments; }()); @@ -9592,21 +11256,20 @@ * _.isArguments([1, 2, 3]); * // => false */ - function isArguments(value) { - // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. - return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && - (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); - } + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ - * @type {Function} + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. * @example * * _.isArray([1, 2, 3]); @@ -9628,9 +11291,10 @@ * * @static * @memberOf _ + * @since 4.3.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. * @example * * _.isArrayBuffer(new ArrayBuffer(2)); @@ -9639,9 +11303,7 @@ * _.isArrayBuffer(new Array(2)); * // => false */ - function isArrayBuffer(value) { - return isObjectLike(value) && objectToString.call(value) == arrayBufferTag; - } + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; /** * Checks if `value` is array-like. A value is considered array-like if it's @@ -9650,6 +11312,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. @@ -9668,8 +11331,7 @@ * // => false */ function isArrayLike(value) { - return value != null && - !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value)); + return value != null && isLength(value.length) && !isFunction(value); } /** @@ -9678,9 +11340,11 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. * @example * * _.isArrayLikeObject([1, 2, 3]); @@ -9704,9 +11368,10 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. * @example * * _.isBoolean(false); @@ -9717,7 +11382,7 @@ */ function isBoolean(value) { return value === true || value === false || - (isObjectLike(value) && objectToString.call(value) == boolTag); + (isObjectLike(value) && baseGetTag(value) == boolTag); } /** @@ -9725,6 +11390,7 @@ * * @static * @memberOf _ + * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. @@ -9736,18 +11402,17 @@ * _.isBuffer(new Uint8Array(2)); * // => false */ - var isBuffer = !Buffer ? constant(false) : function(value) { - return value instanceof Buffer; - }; + var isBuffer = nativeIsBuffer || stubFalse; /** * Checks if `value` is classified as a `Date` object. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. * @example * * _.isDate(new Date); @@ -9756,15 +11421,14 @@ * _.isDate('Mon April 23 2012'); * // => false */ - function isDate(value) { - return isObjectLike(value) && objectToString.call(value) == dateTag; - } + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; /** * Checks if `value` is likely a DOM element. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. @@ -9777,18 +11441,24 @@ * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); } /** - * Checks if `value` is empty. A value is considered empty unless it's an - * `arguments` object, array, string, or jQuery-like collection with a length - * greater than `0` or an object with own enumerable properties. + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang - * @param {Array|Object|string} value The value to inspect. + * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * @@ -9808,11 +11478,21 @@ * // => false */ function isEmpty(value) { + if (value == null) { + return true; + } if (isArrayLike(value) && - (isArray(value) || isString(value) || - isFunction(value.splice) || isArguments(value))) { + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { return !value.length; } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } for (var key in value) { if (hasOwnProperty.call(value, key)) { return false; @@ -9829,18 +11509,19 @@ * date objects, error objects, maps, numbers, `Object` objects, regexes, * sets, strings, symbols, and typed arrays. `Object` objects are compared * by their own, not inherited, enumerable properties. Functions and DOM - * nodes are **not** supported. + * nodes are compared by strict equality, i.e. `===`. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * - * var object = { 'user': 'fred' }; - * var other = { 'user': 'fred' }; + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; * * _.isEqual(object, other); * // => true @@ -9854,12 +11535,13 @@ /** * This method is like `_.isEqual` except that it accepts `customizer` which - * is invoked to compare values. If `customizer` returns `undefined` comparisons + * is invoked to compare values. If `customizer` returns `undefined`, comparisons * are handled by the method instead. The `customizer` is invoked with up to * six arguments: (objValue, othValue [, index|key, object, other, stack]). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. @@ -9886,7 +11568,7 @@ function isEqualWith(value, other, customizer) { customizer = typeof customizer == 'function' ? customizer : undefined; var result = customizer ? customizer(value, other) : undefined; - return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; } /** @@ -9895,6 +11577,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an error object, else `false`. @@ -9910,17 +11593,20 @@ if (!isObjectLike(value)) { return false; } - return (objectToString.call(value) == errorTag) || - (typeof value.message == 'string' && typeof value.name == 'string'); + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); } /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on [`Number.isFinite`](https://mdn.io/Number/isFinite). + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. @@ -9929,14 +11615,14 @@ * _.isFinite(3); * // => true * - * _.isFinite(Number.MAX_VALUE); - * // => true - * - * _.isFinite(3.14); + * _.isFinite(Number.MIN_VALUE); * // => true * * _.isFinite(Infinity); * // => false + * + * _.isFinite('3'); + * // => false */ function isFinite(value) { return typeof value == 'number' && nativeIsFinite(value); @@ -9947,9 +11633,10 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. * @example * * _.isFunction(_); @@ -9959,20 +11646,24 @@ * // => false */ function isFunction(value) { + if (!isObject(value)) { + return false; + } // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array constructors, and - // PhantomJS 1.9 which returns 'function' for `NodeList` instances. - var tag = isObject(value) ? objectToString.call(value) : ''; - return tag == funcTag || tag == genTag; + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; } /** * Checks if `value` is an integer. * - * **Note:** This method is based on [`Number.isInteger`](https://mdn.io/Number/isInteger). + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an integer, else `false`. @@ -9997,10 +11688,12 @@ /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. @@ -10024,11 +11717,13 @@ } /** - * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. @@ -10048,7 +11743,7 @@ */ function isObject(value) { var type = typeof value; - return !!value && (type == 'object' || type == 'function'); + return value != null && (type == 'object' || type == 'function'); } /** @@ -10057,6 +11752,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. @@ -10075,7 +11771,7 @@ * // => false */ function isObjectLike(value) { - return !!value && typeof value == 'object'; + return value != null && typeof value == 'object'; } /** @@ -10083,9 +11779,10 @@ * * @static * @memberOf _ + * @since 4.3.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. * @example * * _.isMap(new Map); @@ -10094,31 +11791,34 @@ * _.isMap(new WeakMap); * // => false */ - function isMap(value) { - return isObjectLike(value) && getTag(value) == mapTag; - } + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; /** * Performs a partial deep comparison between `object` and `source` to - * determine if `object` contains equivalent property values. This method is - * equivalent to a `_.matches` function when `source` is partially applied. + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. * - * **Note:** This method supports comparing the same values as `_.isEqual`. + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ + * @since 3.0.0 * @category Lang * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * - * var object = { 'user': 'fred', 'age': 40 }; + * var object = { 'a': 1, 'b': 2 }; * - * _.isMatch(object, { 'age': 40 }); + * _.isMatch(object, { 'b': 2 }); * // => true * - * _.isMatch(object, { 'age': 36 }); + * _.isMatch(object, { 'b': 1 }); * // => false */ function isMatch(object, source) { @@ -10127,12 +11827,13 @@ /** * This method is like `_.isMatch` except that it accepts `customizer` which - * is invoked to compare values. If `customizer` returns `undefined` comparisons + * is invoked to compare values. If `customizer` returns `undefined`, comparisons * are handled by the method instead. The `customizer` is invoked with five * arguments: (objValue, srcValue, index|key, object, source). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. @@ -10164,11 +11865,14 @@ /** * Checks if `value` is `NaN`. * - * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4) - * which returns `true` for `undefined` and other non-numeric values. + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. @@ -10188,18 +11892,29 @@ */ function isNaN(value) { // An `NaN` primitive is the only value that is not equal to itself. - // Perform the `toStringTag` check first to avoid errors with some ActiveX objects in IE. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. return isNumber(value) && value != +value; } /** - * Checks if `value` is a native function. + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. * * @static * @memberOf _ + * @since 3.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. * @example * * _.isNative(Array.prototype.push); @@ -10209,14 +11924,10 @@ * // => false */ function isNative(value) { - if (value == null) { - return false; - } - if (isFunction(value)) { - return reIsNative.test(funcToString.call(value)); + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); } - return isObjectLike(value) && - (isHostObject(value) ? reIsNative : reIsHostCtor).test(value); + return baseIsNative(value); } /** @@ -10224,6 +11935,7 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `null`, else `false`. @@ -10244,6 +11956,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is nullish, else `false`. @@ -10265,14 +11978,15 @@ /** * Checks if `value` is classified as a `Number` primitive or object. * - * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified - * as numbers, use the `_.isFinite` method. + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. * @example * * _.isNumber(3); @@ -10289,7 +12003,7 @@ */ function isNumber(value) { return typeof value == 'number' || - (isObjectLike(value) && objectToString.call(value) == numberTag); + (isObjectLike(value) && baseGetTag(value) == numberTag); } /** @@ -10298,6 +12012,7 @@ * * @static * @memberOf _ + * @since 0.8.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. @@ -10320,17 +12035,16 @@ * // => true */ function isPlainObject(value) { - if (!isObjectLike(value) || - objectToString.call(value) != objectTag || isHostObject(value)) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { return false; } - var proto = getPrototypeOf(value); + var proto = getPrototype(value); if (proto === null) { return true; } - var Ctor = proto.constructor; - return (typeof Ctor == 'function' && - Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; } /** @@ -10338,9 +12052,10 @@ * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. * @example * * _.isRegExp(/abc/); @@ -10349,18 +12064,18 @@ * _.isRegExp('/abc/'); * // => false */ - function isRegExp(value) { - return isObject(value) && objectToString.call(value) == regexpTag; - } + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; /** * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 * double precision number which isn't the result of a rounded unsafe integer. * - * **Note:** This method is based on [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. @@ -10387,9 +12102,10 @@ * * @static * @memberOf _ + * @since 4.3.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. * @example * * _.isSet(new Set); @@ -10398,18 +12114,17 @@ * _.isSet(new WeakSet); * // => false */ - function isSet(value) { - return isObjectLike(value) && getTag(value) == setTag; - } + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; /** * Checks if `value` is classified as a `String` primitive or object. * * @static + * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. * @example * * _.isString('abc'); @@ -10420,7 +12135,7 @@ */ function isString(value) { return typeof value == 'string' || - (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); } /** @@ -10428,9 +12143,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. * @example * * _.isSymbol(Symbol.iterator); @@ -10441,7 +12157,7 @@ */ function isSymbol(value) { return typeof value == 'symbol' || - (isObjectLike(value) && objectToString.call(value) == symbolTag); + (isObjectLike(value) && baseGetTag(value) == symbolTag); } /** @@ -10449,9 +12165,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. * @example * * _.isTypedArray(new Uint8Array); @@ -10460,15 +12177,13 @@ * _.isTypedArray([]); * // => false */ - function isTypedArray(value) { - return isObjectLike(value) && - isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; - } + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; /** * Checks if `value` is `undefined`. * * @static + * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to check. @@ -10490,9 +12205,10 @@ * * @static * @memberOf _ + * @since 4.3.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. * @example * * _.isWeakMap(new WeakMap); @@ -10510,9 +12226,10 @@ * * @static * @memberOf _ + * @since 4.3.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. * @example * * _.isWeakSet(new WeakSet); @@ -10522,7 +12239,7 @@ * // => false */ function isWeakSet(value) { - return isObjectLike(value) && objectToString.call(value) == weakSetTag; + return isObjectLike(value) && baseGetTag(value) == weakSetTag; } /** @@ -10530,10 +12247,13 @@ * * @static * @memberOf _ + * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt * @example * * _.lt(1, 3); @@ -10545,19 +12265,20 @@ * _.lt(3, 1); * // => false */ - function lt(value, other) { - return value < other; - } + var lt = createRelationalOperation(baseLt); /** * Checks if `value` is less than or equal to `other`. * * @static * @memberOf _ + * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte * @example * * _.lte(1, 3); @@ -10569,14 +12290,15 @@ * _.lte(3, 1); * // => false */ - function lte(value, other) { + var lte = createRelationalOperation(function(value, other) { return value <= other; - } + }); /** * Converts `value` to an array. * * @static + * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to convert. @@ -10602,8 +12324,8 @@ if (isArrayLike(value)) { return isString(value) ? stringToArray(value) : copyArray(value); } - if (iteratorSymbol && value[iteratorSymbol]) { - return iteratorToArray(value[iteratorSymbol]()); + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); } var tag = getTag(value), func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); @@ -10612,18 +12334,55 @@ } /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** * Converts `value` to an integer. * - * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * - * _.toInteger(3); + * _.toInteger(3.2); * // => 3 * * _.toInteger(Number.MIN_VALUE); @@ -10632,36 +12391,32 @@ * _.toInteger(Infinity); * // => 1.7976931348623157e+308 * - * _.toInteger('3'); + * _.toInteger('3.2'); * // => 3 */ function toInteger(value) { - if (!value) { - return value === 0 ? value : 0; - } - value = toNumber(value); - if (value === INFINITY || value === -INFINITY) { - var sign = (value < 0 ? -1 : 1); - return sign * MAX_INTEGER; - } - var remainder = value % 1; - return value === value ? (remainder ? value - remainder : value) : 0; + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; } /** * Converts `value` to an integer suitable for use as the length of an * array-like object. * - * **Note:** This method is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * - * _.toLength(3); + * _.toLength(3.2); * // => 3 * * _.toLength(Number.MIN_VALUE); @@ -10670,7 +12425,7 @@ * _.toLength(Infinity); * // => 4294967295 * - * _.toLength('3'); + * _.toLength('3.2'); * // => 3 */ function toLength(value) { @@ -10682,13 +12437,14 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * - * _.toNumber(3); - * // => 3 + * _.toNumber(3.2); + * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 @@ -10696,12 +12452,18 @@ * _.toNumber(Infinity); * // => Infinity * - * _.toNumber('3'); - * // => 3 + * _.toNumber('3.2'); + * // => 3.2 */ function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } if (isObject(value)) { - var other = isFunction(value.valueOf) ? value.valueOf() : value; + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; } if (typeof value != 'string') { @@ -10715,11 +12477,12 @@ } /** - * Converts `value` to a plain object flattening inherited enumerable - * properties of `value` to own properties of the plain object. + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. * * @static * @memberOf _ + * @since 3.0.0 * @category Lang * @param {*} value The value to convert. * @returns {Object} Returns the converted plain object. @@ -10747,12 +12510,13 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * - * _.toSafeInteger(3); + * _.toSafeInteger(3.2); * // => 3 * * _.toSafeInteger(Number.MIN_VALUE); @@ -10761,22 +12525,25 @@ * _.toSafeInteger(Infinity); * // => 9007199254740991 * - * _.toSafeInteger('3'); + * _.toSafeInteger('3.2'); * // => 3 */ function toSafeInteger(value) { - return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + return value + ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) + : (value === 0 ? value : 0); } /** - * Converts `value` to a string if it's not one. An empty string is returned - * for `null` and `undefined` values. The sign of `-0` is preserved. + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. * * @static * @memberOf _ + * @since 4.0.0 * @category Lang - * @param {*} value The value to process. - * @returns {string} Returns the string. + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. * @example * * _.toString(null); @@ -10789,54 +12556,53 @@ * // => '1,2,3' */ function toString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value; - } - if (value == null) { - return ''; - } - if (isSymbol(value)) { - return Symbol ? symbolToString.call(value) : ''; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + return value == null ? '' : baseToString(value); } /*------------------------------------------------------------------------*/ /** - * Assigns own enumerable properties of source objects to the destination - * object. Source objects are applied from left to right. Subsequent sources - * overwrite property assignments of previous sources. + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. * * **Note:** This method mutates `object` and is loosely based on * [`Object.assign`](https://mdn.io/Object/assign). * * @static * @memberOf _ + * @since 0.10.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. + * @see _.assignIn * @example * * function Foo() { - * this.c = 3; + * this.a = 1; * } * * function Bar() { - * this.e = 5; + * this.c = 3; * } * - * Foo.prototype.d = 4; - * Bar.prototype.f = 6; + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; * - * _.assign({ 'a': 1 }, new Foo, new Bar); - * // => { 'a': 1, 'c': 3, 'e': 5 } + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } */ var assign = createAssigner(function(object, source) { - copyObject(source, keys(source), object); + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } }); /** @@ -10847,47 +12613,51 @@ * * @static * @memberOf _ + * @since 4.0.0 * @alias extend * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. + * @see _.assign * @example * * function Foo() { - * this.b = 2; + * this.a = 1; * } * * function Bar() { - * this.d = 4; + * this.c = 3; * } * - * Foo.prototype.c = 3; - * Bar.prototype.e = 5; + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; * - * _.assignIn({ 'a': 1 }, new Foo, new Bar); - * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 } + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } */ var assignIn = createAssigner(function(object, source) { copyObject(source, keysIn(source), object); }); /** - * This method is like `_.assignIn` except that it accepts `customizer` which - * is invoked to produce the assigned values. If `customizer` returns `undefined` - * assignment is handled by the method instead. The `customizer` is invoked - * with five arguments: (objValue, srcValue, key, object, source). + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). * * **Note:** This method mutates `object`. * * @static * @memberOf _ + * @since 4.0.0 * @alias extendWith * @category Object * @param {Object} object The destination object. * @param {...Object} sources The source objects. * @param {Function} [customizer] The function to customize assigned values. * @returns {Object} Returns `object`. + * @see _.assignWith * @example * * function customizer(objValue, srcValue) { @@ -10900,24 +12670,26 @@ * // => { 'a': 1, 'b': 2 } */ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { - copyObjectWith(source, keysIn(source), object, customizer); + copyObject(source, keysIn(source), object, customizer); }); /** - * This method is like `_.assign` except that it accepts `customizer` which - * is invoked to produce the assigned values. If `customizer` returns `undefined` - * assignment is handled by the method instead. The `customizer` is invoked - * with five arguments: (objValue, srcValue, key, object, source). + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). * * **Note:** This method mutates `object`. * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The destination object. * @param {...Object} sources The source objects. * @param {Function} [customizer] The function to customize assigned values. * @returns {Object} Returns `object`. + * @see _.assignInWith * @example * * function customizer(objValue, srcValue) { @@ -10930,7 +12702,7 @@ * // => { 'a': 1, 'b': 2 } */ var assignWith = createAssigner(function(object, source, srcIndex, customizer) { - copyObjectWith(source, keys(source), object, customizer); + copyObject(source, keys(source), object, customizer); }); /** @@ -10938,31 +12710,28 @@ * * @static * @memberOf _ + * @since 1.0.0 * @category Object * @param {Object} object The object to iterate over. - * @param {...(string|string[])} [paths] The property paths of elements to pick, - * specified individually or in arrays. - * @returns {Array} Returns the new array of picked elements. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; * * _.at(object, ['a[0].b.c', 'a[1]']); * // => [3, 4] - * - * _.at(['a', 'b', 'c'], 0, 2); - * // => ['a', 'c'] */ - var at = rest(function(object, paths) { - return baseAt(object, baseFlatten(paths, 1)); - }); + var at = flatRest(baseAt); /** - * Creates an object that inherits from the `prototype` object. If a `properties` - * object is given its own enumerable properties are assigned to the created object. + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. * * @static * @memberOf _ + * @since 2.3.0 * @category Object * @param {Object} prototype The object to inherit from. * @param {Object} [properties] The properties to assign to the object. @@ -10991,31 +12760,59 @@ */ function create(prototype, properties) { var result = baseCreate(prototype); - return properties ? baseAssign(result, properties) : result; + return properties == null ? result : baseAssign(result, properties); } /** - * Assigns own and inherited enumerable properties of source objects to the - * destination object for all destination properties that resolve to `undefined`. - * Source objects are applied from left to right. Once a property is set, - * additional values of the same property are ignored. + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. * * **Note:** This method mutates `object`. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. + * @see _.defaultsDeep * @example * - * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); - * // => { 'user': 'barney', 'age': 36 } + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } */ - var defaults = rest(function(args) { - args.push(undefined, assignInDefaults); - return apply(assignInWith, undefined, args); + var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; }); /** @@ -11026,18 +12823,19 @@ * * @static * @memberOf _ + * @since 3.10.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. + * @see _.defaults * @example * - * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); - * // => { 'user': { 'name': 'barney', 'age': 36 } } - * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } */ - var defaultsDeep = rest(function(args) { - args.push(undefined, mergeDefaults); + var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); return apply(mergeWith, undefined, args); }); @@ -11047,10 +12845,12 @@ * * @static * @memberOf _ + * @since 1.1.0 * @category Object - * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. - * @returns {string|undefined} Returns the key of the matched element, else `undefined`. + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. * @example * * var users = { @@ -11075,7 +12875,7 @@ * // => 'barney' */ function findKey(object, predicate) { - return baseFind(object, getIteratee(predicate, 3), baseForOwn, true); + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); } /** @@ -11084,10 +12884,12 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Object - * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. - * @returns {string|undefined} Returns the key of the matched element, else `undefined`. + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. * @example * * var users = { @@ -11112,21 +12914,23 @@ * // => 'pebbles' */ function findLastKey(object, predicate) { - return baseFind(object, getIteratee(predicate, 3), baseForOwnRight, true); + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); } /** - * Iterates over own and inherited enumerable properties of an object invoking - * `iteratee` for each property. The iteratee is invoked with three arguments: - * (value, key, object). Iteratee functions may exit iteration early by explicitly - * returning `false`. + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. * * @static * @memberOf _ + * @since 0.3.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. + * @see _.forInRight * @example * * function Foo() { @@ -11139,12 +12943,12 @@ * _.forIn(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'a', 'b', then 'c' (iteration order is not guaranteed) + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). */ function forIn(object, iteratee) { return object == null ? object - : baseFor(object, baseCastFunction(iteratee), keysIn); + : baseFor(object, getIteratee(iteratee, 3), keysIn); } /** @@ -11153,10 +12957,12 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. + * @see _.forIn * @example * * function Foo() { @@ -11169,26 +12975,28 @@ * _.forInRight(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c' + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. */ function forInRight(object, iteratee) { return object == null ? object - : baseForRight(object, baseCastFunction(iteratee), keysIn); + : baseForRight(object, getIteratee(iteratee, 3), keysIn); } /** - * Iterates over own enumerable properties of an object invoking `iteratee` - * for each property. The iteratee is invoked with three arguments: - * (value, key, object). Iteratee functions may exit iteration early by - * explicitly returning `false`. + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. * * @static * @memberOf _ + * @since 0.3.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. + * @see _.forOwnRight * @example * * function Foo() { @@ -11201,10 +13009,10 @@ * _.forOwn(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'a' then 'b' (iteration order is not guaranteed) + * // => Logs 'a' then 'b' (iteration order is not guaranteed). */ function forOwn(object, iteratee) { - return object && baseForOwn(object, baseCastFunction(iteratee)); + return object && baseForOwn(object, getIteratee(iteratee, 3)); } /** @@ -11213,10 +13021,12 @@ * * @static * @memberOf _ + * @since 2.0.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. + * @see _.forOwn * @example * * function Foo() { @@ -11229,10 +13039,10 @@ * _.forOwnRight(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b' + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. */ function forOwnRight(object, iteratee) { - return object && baseForOwnRight(object, baseCastFunction(iteratee)); + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); } /** @@ -11240,10 +13050,12 @@ * of `object`. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to inspect. - * @returns {Array} Returns the new array of property names. + * @returns {Array} Returns the function names. + * @see _.functionsIn * @example * * function Foo() { @@ -11266,9 +13078,11 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The object to inspect. - * @returns {Array} Returns the new array of property names. + * @returns {Array} Returns the function names. + * @see _.functions * @example * * function Foo() { @@ -11287,14 +13101,15 @@ /** * Gets the value at `path` of `object`. If the resolved value is - * `undefined` the `defaultValue` is used in its place. + * `undefined`, the `defaultValue` is returned in its place. * * @static * @memberOf _ + * @since 3.7.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. - * @param {*} [defaultValue] The value returned if the resolved value is `undefined`. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. * @returns {*} Returns the resolved value. * @example * @@ -11318,6 +13133,7 @@ * Checks if `path` is a direct property of `object`. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. @@ -11325,23 +13141,23 @@ * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * - * var object = { 'a': { 'b': { 'c': 3 } } }; - * var other = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) }); + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); * * _.has(object, 'a'); * // => true * - * _.has(object, 'a.b.c'); + * _.has(object, 'a.b'); * // => true * - * _.has(object, ['a', 'b', 'c']); + * _.has(object, ['a', 'b']); * // => true * * _.has(other, 'a'); * // => false */ function has(object, path) { - return hasPath(object, path, baseHas); + return object != null && hasPath(object, path, baseHas); } /** @@ -11349,37 +13165,39 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * - * var object = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) }); + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); * * _.hasIn(object, 'a'); * // => true * - * _.hasIn(object, 'a.b.c'); + * _.hasIn(object, 'a.b'); * // => true * - * _.hasIn(object, ['a', 'b', 'c']); + * _.hasIn(object, ['a', 'b']); * // => true * * _.hasIn(object, 'b'); * // => false */ function hasIn(object, path) { - return hasPath(object, path, baseHasIn); + return object != null && hasPath(object, path, baseHasIn); } /** * Creates an object composed of the inverted keys and values of `object`. - * If `object` contains duplicate values, subsequent values overwrite property - * assignments of previous values. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. * * @static * @memberOf _ + * @since 0.7.0 * @category Object * @param {Object} object The object to invert. * @returns {Object} Returns the new inverted object. @@ -11391,21 +13209,27 @@ * // => { '1': 'c', '2': 'b' } */ var invert = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + result[value] = key; }, constant(identity)); /** * This method is like `_.invert` except that the inverted object is generated - * from the results of running each element of `object` through `iteratee`. - * The corresponding inverted value of each inverted key is an array of keys + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys * responsible for generating the inverted value. The iteratee is invoked * with one argument: (value). * * @static * @memberOf _ + * @since 4.1.0 * @category Object * @param {Object} object The object to invert. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {Object} Returns the new inverted object. * @example * @@ -11420,6 +13244,11 @@ * // => { 'group1': ['a', 'c'], 'group2': ['b'] } */ var invertBy = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + if (hasOwnProperty.call(result, value)) { result[value].push(key); } else { @@ -11432,6 +13261,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the method to invoke. @@ -11444,16 +13274,17 @@ * _.invoke(object, 'a[0].b.c.slice', 1, 3); * // => [2, 3] */ - var invoke = rest(baseInvoke); + var invoke = baseRest(baseInvoke); /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * for more details. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. @@ -11474,23 +13305,7 @@ * // => ['0', '1'] */ function keys(object) { - var isProto = isPrototype(object); - if (!(isProto || isArrayLike(object))) { - return baseKeys(object); - } - var indexes = indexKeys(object), - skipIndexes = !!indexes, - result = indexes || [], - length = result.length; - - for (var key in object) { - if (baseHas(object, key) && - !(skipIndexes && (key == 'length' || isIndex(key, length))) && - !(isProto && key == 'constructor')) { - result.push(key); - } - } - return result; + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); } /** @@ -11500,6 +13315,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. @@ -11516,37 +13332,23 @@ * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { - var index = -1, - isProto = isPrototype(object), - props = baseKeysIn(object), - propsLength = props.length, - indexes = indexKeys(object), - skipIndexes = !!indexes, - result = indexes || [], - length = result.length; - - while (++index < propsLength) { - var key = props[index]; - if (!(skipIndexes && (key == 'length' || isIndex(key, length))) && - !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { - result.push(key); - } - } - return result; + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); } /** * The opposite of `_.mapValues`; this method creates an object with the * same values as `object` and keys generated by running each own enumerable - * property of `object` through `iteratee`. The iteratee is invoked with - * three arguments: (value, key, object). + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). * * @static * @memberOf _ + * @since 3.8.0 * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns the new mapped object. + * @see _.mapValues * @example * * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { @@ -11559,22 +13361,25 @@ iteratee = getIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { - result[iteratee(value, key, object)] = value; + baseAssignValue(result, iteratee(value, key, object), value); }); return result; } /** - * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through `iteratee`. The - * iteratee is invoked with three arguments: (value, key, object). + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). * * @static * @memberOf _ + * @since 2.4.0 * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns the new mapped object. + * @see _.mapKeys * @example * * var users = { @@ -11594,15 +13399,16 @@ iteratee = getIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { - result[key] = iteratee(value, key, object); + baseAssignValue(result, key, iteratee(value, key, object)); }); return result; } /** - * Recursively merges own and inherited enumerable properties of source objects - * into the destination object. Source properties that resolve to `undefined` - * are skipped if a destination value exists. Array and plain object properties + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties * are merged recursively. Other objects and value types are overridden by * assignment. Source objects are applied from left to right. Subsequent * sources overwrite property assignments of previous sources. @@ -11611,22 +13417,23 @@ * * @static * @memberOf _ + * @since 0.5.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @example * - * var users = { - * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] * }; * - * var ages = { - * 'data': [{ 'age': 36 }, { 'age': 40 }] + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] * }; * - * _.merge(users, ages); - * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } */ var merge = createAssigner(function(object, source, srcIndex) { baseMerge(object, source, srcIndex); @@ -11635,14 +13442,15 @@ /** * This method is like `_.merge` except that it accepts `customizer` which * is invoked to produce the merged values of the destination and source - * properties. If `customizer` returns `undefined` merging is handled by the - * method instead. The `customizer` is invoked with seven arguments: + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: * (objValue, srcValue, key, object, source, stack). * * **Note:** This method mutates `object`. * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The destination object. * @param {...Object} sources The source objects. @@ -11656,18 +13464,11 @@ * } * } * - * var object = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var other = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; * * _.mergeWith(object, other, customizer); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } + * // => { 'a': [1, 3], 'b': [2, 4] } */ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { baseMerge(object, source, srcIndex, customizer); @@ -11675,14 +13476,16 @@ /** * The opposite of `_.pick`; this method creates an object composed of the - * own and inherited enumerable properties of `object` that are not omitted. + * own and inherited enumerable property paths of `object` that are not omitted. + * + * **Note:** This method is considerably slower than `_.pick`. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {...(string|string[])} [props] The property names to omit, specified - * individually or in arrays. + * @param {...(string|string[])} [paths] The property paths to omit. * @returns {Object} Returns the new object. * @example * @@ -11691,25 +13494,40 @@ * _.omit(object, ['a', 'c']); * // => { 'b': '2' } */ - var omit = rest(function(object, props) { + var omit = flatRest(function(object, paths) { + var result = {}; if (object == null) { - return {}; + return result; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result); + if (isDeep) { + result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result, paths[length]); } - props = arrayMap(baseFlatten(props, 1), String); - return basePick(object, baseDifference(keysIn(object), props)); + return result; }); /** * The opposite of `_.pickBy`; this method creates an object composed of - * the own and inherited enumerable properties of `object` that `predicate` - * doesn't return truthy for. The predicate is invoked with two arguments: - * (value, key). + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The source object. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per property. + * @param {Function} [predicate=_.identity] The function invoked per property. * @returns {Object} Returns the new object. * @example * @@ -11719,21 +13537,18 @@ * // => { 'b': '2' } */ function omitBy(object, predicate) { - predicate = getIteratee(predicate); - return basePickBy(object, function(value, key) { - return !predicate(value, key); - }); + return pickBy(object, negate(getIteratee(predicate))); } /** * Creates an object composed of the picked `object` properties. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The source object. - * @param {...(string|string[])} [props] The property names to pick, specified - * individually or in arrays. + * @param {...(string|string[])} [paths] The property paths to pick. * @returns {Object} Returns the new object. * @example * @@ -11742,8 +13557,8 @@ * _.pick(object, ['a', 'c']); * // => { 'a': 1, 'c': 3 } */ - var pick = rest(function(object, props) { - return object == null ? {} : basePick(object, baseFlatten(props, 1)); + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); }); /** @@ -11752,9 +13567,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The source object. - * @param {Function|Object|string} [predicate=_.identity] The function invoked per property. + * @param {Function} [predicate=_.identity] The function invoked per property. * @returns {Object} Returns the new object. * @example * @@ -11764,20 +13580,30 @@ * // => { 'a': 1, 'c': 3 } */ function pickBy(object, predicate) { - return object == null ? {} : basePickBy(object, getIteratee(predicate)); + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); } /** - * This method is like `_.get` except that if the resolved value is a function - * it's invoked with the `this` binding of its parent object and its result - * is returned. + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the property to resolve. - * @param {*} [defaultValue] The value returned if the resolved value is `undefined`. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. * @returns {*} Returns the resolved value. * @example * @@ -11796,21 +13622,29 @@ * // => 'default' */ function result(object, path, defaultValue) { - if (!isKey(path, object)) { - path = baseCastPath(path); - var result = get(object, path); - object = parent(object, path); - } else { - result = object == null ? undefined : object[path]; + path = castPath(path, object); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + length = 1; + object = undefined; } - if (result === undefined) { - result = defaultValue; + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; } - return isFunction(result) ? result.call(object) : result; + return object; } /** - * Sets the value at `path` of `object`. If a portion of `path` doesn't exist + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, * it's created. Arrays are created for missing index properties while objects * are created for all other missing properties. Use `_.setWith` to customize * `path` creation. @@ -11819,6 +13653,7 @@ * * @static * @memberOf _ + * @since 3.7.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. @@ -11832,7 +13667,7 @@ * console.log(object.a[0].b.c); * // => 4 * - * _.set(object, 'x[0].y.z', 5); + * _.set(object, ['x', '0', 'y', 'z'], 5); * console.log(object.x[0].y.z); * // => 5 */ @@ -11850,6 +13685,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. @@ -11858,8 +13694,10 @@ * @returns {Object} Returns `object`. * @example * - * _.setWith({ '0': { 'length': 2 } }, '[0][1][2]', 3, Object); - * // => { '0': { '1': { '2': 3 }, 'length': 2 } } + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } */ function setWith(object, path, value, customizer) { customizer = typeof customizer == 'function' ? customizer : undefined; @@ -11867,14 +13705,17 @@ } /** - * Creates an array of own enumerable key-value pairs for `object` which - * can be consumed by `_.fromPairs`. + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. * * @static * @memberOf _ + * @since 4.0.0 + * @alias entries * @category Object * @param {Object} object The object to query. - * @returns {Array} Returns the new array of key-value pairs. + * @returns {Array} Returns the key-value pairs. * @example * * function Foo() { @@ -11887,19 +13728,20 @@ * _.toPairs(new Foo); * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) */ - function toPairs(object) { - return baseToPairs(object, keys(object)); - } + var toPairs = createToPairs(keys); /** - * Creates an array of own and inherited enumerable key-value pairs for - * `object` which can be consumed by `_.fromPairs`. + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. * * @static * @memberOf _ + * @since 4.0.0 + * @alias entriesIn * @category Object * @param {Object} object The object to query. - * @returns {Array} Returns the new array of key-value pairs. + * @returns {Array} Returns the key-value pairs. * @example * * function Foo() { @@ -11910,24 +13752,24 @@ * Foo.prototype.c = 3; * * _.toPairsIn(new Foo); - * // => [['a', 1], ['b', 2], ['c', 1]] (iteration order is not guaranteed) + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) */ - function toPairsIn(object) { - return baseToPairs(object, keysIn(object)); - } + var toPairsIn = createToPairs(keysIn); /** * An alternative to `_.reduce`; this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own enumerable - * properties through `iteratee`, with each invocation potentially mutating - * the `accumulator` object. The iteratee is invoked with four arguments: - * (accumulator, value, key, object). Iteratee functions may exit iteration - * early by explicitly returning `false`. + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ + * @since 1.3.0 * @category Object - * @param {Array|Object} object The object to iterate over. + * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @returns {*} Returns the accumulated value. @@ -11945,22 +13787,23 @@ * // => { '1': ['a', 'c'], '2': ['b'] } */ function transform(object, iteratee, accumulator) { - var isArr = isArray(object) || isTypedArray(object); - iteratee = getIteratee(iteratee, 4); + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + iteratee = getIteratee(iteratee, 4); if (accumulator == null) { - if (isArr || isObject(object)) { - var Ctor = object.constructor; - if (isArr) { - accumulator = isArray(object) ? new Ctor : []; - } else { - accumulator = isFunction(Ctor) ? baseCreate(getPrototypeOf(object)) : {}; - } - } else { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { accumulator = {}; } } - (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { return iteratee(accumulator, value, index, object); }); return accumulator; @@ -11973,6 +13816,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to unset. @@ -11986,7 +13830,7 @@ * console.log(object); * // => { 'a': [{ 'b': {} }] }; * - * _.unset(object, 'a[0].b.c'); + * _.unset(object, ['a', '0', 'b', 'c']); * // => true * * console.log(object); @@ -11997,11 +13841,72 @@ } /** - * Creates an array of the own enumerable property values of `object`. + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static + * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. @@ -12022,16 +13927,18 @@ * // => ['h', 'i'] */ function values(object) { - return object ? baseValues(object, keys(object)) : []; + return object == null ? [] : baseValues(object, keys(object)); } /** - * Creates an array of the own and inherited enumerable property values of `object`. + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ + * @since 3.0.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. @@ -12058,6 +13965,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Number * @param {number} number The number to clamp. * @param {number} [lower] The lower bound. @@ -12088,18 +13996,20 @@ } /** - * Checks if `n` is between `start` and up to but not including, `end`. If - * `end` is not specified it's set to `start` with `start` then set to `0`. + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. * If `start` is greater than `end` the params are swapped to support * negative ranges. * * @static * @memberOf _ + * @since 3.3.0 * @category Number * @param {number} number The number to check. * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight * @example * * _.inRange(3, 2, 4); @@ -12124,12 +14034,12 @@ * // => true */ function inRange(number, start, end) { - start = toNumber(start) || 0; + start = toFinite(start); if (end === undefined) { end = start; start = 0; } else { - end = toNumber(end) || 0; + end = toFinite(end); } number = toNumber(number); return baseInRange(number, start, end); @@ -12138,14 +14048,15 @@ /** * Produces a random number between the inclusive `lower` and `upper` bounds. * If only one argument is provided a number between `0` and the given number - * is returned. If `floating` is `true`, or either `lower` or `upper` are floats, - * a floating-point number is returned instead of an integer. + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. * * **Note:** JavaScript follows the IEEE-754 standard for resolving * floating-point values which can produce unexpected results. * * @static * @memberOf _ + * @since 0.7.0 * @category Number * @param {number} [lower=0] The lower bound. * @param {number} [upper=1] The upper bound. @@ -12184,12 +14095,12 @@ upper = 1; } else { - lower = toNumber(lower) || 0; + lower = toFinite(lower); if (upper === undefined) { upper = lower; lower = 0; } else { - upper = toNumber(upper) || 0; + upper = toFinite(upper); } } if (lower > upper) { @@ -12211,6 +14122,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the camel cased string. @@ -12219,10 +14131,10 @@ * _.camelCase('Foo Bar'); * // => 'fooBar' * - * _.camelCase('--foo-bar'); + * _.camelCase('--foo-bar--'); * // => 'fooBar' * - * _.camelCase('__foo_bar__'); + * _.camelCase('__FOO_BAR__'); * // => 'fooBar' */ var camelCase = createCompounder(function(result, word, index) { @@ -12236,6 +14148,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to capitalize. * @returns {string} Returns the capitalized string. @@ -12249,11 +14162,15 @@ } /** - * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to deburr. * @returns {string} Returns the deburred string. @@ -12264,7 +14181,7 @@ */ function deburr(string) { string = toString(string); - return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ''); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); } /** @@ -12272,11 +14189,13 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String - * @param {string} [string=''] The string to search. + * @param {string} [string=''] The string to inspect. * @param {string} [target] The string to search for. - * @param {number} [position=string.length] The position to search from. - * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. * @example * * _.endsWith('abc', 'c'); @@ -12290,40 +14209,37 @@ */ function endsWith(string, target, position) { string = toString(string); - target = typeof target == 'string' ? target : (target + ''); + target = baseToString(target); var length = string.length; position = position === undefined ? length : baseClamp(toInteger(position), 0, length); + var end = position; position -= target.length; - return position >= 0 && string.indexOf(target, position) == position; + return position >= 0 && string.slice(position, end) == target; } /** - * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to - * their corresponding HTML entities. + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional * characters use a third-party library like [_he_](https://mths.be/he). * * Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't need escaping in HTML and have no special meaning - * unless they're part of a tag or unquoted attribute value. - * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * - * Backticks are escaped because in IE < 9, they can break out of - * attribute values or HTML comments. See [#59](https://html5sec.org/#59), - * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and - * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/) - * for more details. - * - * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping) - * to reduce XSS vectors. + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. * * @static + * @since 0.1.0 * @memberOf _ * @category String * @param {string} [string=''] The string to escape. @@ -12346,6 +14262,7 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. @@ -12362,10 +14279,12 @@ } /** - * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the kebab cased string. @@ -12377,7 +14296,7 @@ * _.kebabCase('fooBar'); * // => 'foo-bar' * - * _.kebabCase('__foo_bar__'); + * _.kebabCase('__FOO_BAR__'); * // => 'foo-bar' */ var kebabCase = createCompounder(function(result, word, index) { @@ -12389,12 +14308,13 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the lower cased string. * @example * - * _.lowerCase('--Foo-Bar'); + * _.lowerCase('--Foo-Bar--'); * // => 'foo bar' * * _.lowerCase('fooBar'); @@ -12412,6 +14332,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the converted string. @@ -12426,29 +14347,12 @@ var lowerFirst = createCaseFirst('toLowerCase'); /** - * Converts the first character of `string` to upper case. - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the converted string. - * @example - * - * _.upperFirst('fred'); - * // => 'Fred' - * - * _.upperFirst('FRED'); - * // => 'FRED' - */ - var upperFirst = createCaseFirst('toUpperCase'); - - /** * Pads `string` on the left and right sides if it's shorter than `length`. * Padding characters are truncated if they can't be evenly divided by `length`. * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. @@ -12469,15 +14373,16 @@ string = toString(string); length = toInteger(length); - var strLength = stringSize(string); + var strLength = length ? stringSize(string) : 0; if (!length || strLength >= length) { return string; } - var mid = (length - strLength) / 2, - leftLength = nativeFloor(mid), - rightLength = nativeCeil(mid); - - return createPadding('', leftLength, chars) + string + createPadding('', rightLength, chars); + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); } /** @@ -12486,6 +14391,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. @@ -12504,7 +14410,12 @@ */ function padEnd(string, length, chars) { string = toString(string); - return string + createPadding(string, length, chars); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; } /** @@ -12513,6 +14424,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. @@ -12531,23 +14443,29 @@ */ function padStart(string, length, chars) { string = toString(string); - return createPadding(string, length, chars) + string; + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; } /** * Converts `string` to an integer of the specified radix. If `radix` is - * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, - * in which case a `radix` of `16` is used. + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. * - * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#x15.1.2.2) - * of `parseInt`. + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. * * @static * @memberOf _ + * @since 1.1.0 * @category String * @param {string} string The string to convert. * @param {number} [radix=10] The radix to interpret `value` by. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {number} Returns the converted integer. * @example * @@ -12558,15 +14476,12 @@ * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - // Chrome fails to trim leading <BOM> whitespace characters. - // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. if (guard || radix == null) { radix = 0; } else if (radix) { radix = +radix; } - string = toString(string).replace(reTrim, ''); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); } /** @@ -12574,9 +14489,11 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to repeat. - * @param {number} [n=0] The number of times to repeat the string. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {string} Returns the repeated string. * @example * @@ -12589,34 +14506,24 @@ * _.repeat('abc', 0); * // => '' */ - function repeat(string, n) { - string = toString(string); - n = toInteger(n); - - var result = ''; - if (!string || n < 1 || n > MAX_SAFE_INTEGER) { - return result; + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); } - // Leverage the exponentiation by squaring algorithm for a faster repeat. - // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. - do { - if (n % 2) { - result += string; - } - n = nativeFloor(n / 2); - string += string; - } while (n); - - return result; + return baseRepeat(toString(string), n); } /** * Replaces matches for `pattern` in `string` with `replacement`. * - * **Note:** This method is based on [`String#replace`](https://mdn.io/String/replace). + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to modify. * @param {RegExp|string} pattern The pattern to replace. @@ -12635,10 +14542,12 @@ } /** - * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case). + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the snake cased string. @@ -12650,7 +14559,7 @@ * _.snakeCase('fooBar'); * // => 'foo_bar' * - * _.snakeCase('--foo-bar'); + * _.snakeCase('--FOO-BAR--'); * // => 'foo_bar' */ var snakeCase = createCompounder(function(result, word, index) { @@ -12660,45 +14569,66 @@ /** * Splits `string` by `separator`. * - * **Note:** This method is based on [`String#split`](https://mdn.io/String/split). + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to split. * @param {RegExp|string} separator The separator pattern to split by. * @param {number} [limit] The length to truncate results to. - * @returns {Array} Returns the new array of string segments. + * @returns {Array} Returns the string segments. * @example * * _.split('a-b-c', '-', 2); * // => ['a', 'b'] */ function split(string, separator, limit) { - return toString(string).split(separator, limit); + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); } /** - * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). * * @static * @memberOf _ + * @since 3.1.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the start cased string. * @example * - * _.startCase('--foo-bar'); + * _.startCase('--foo-bar--'); * // => 'Foo Bar' * * _.startCase('fooBar'); * // => 'Foo Bar' * - * _.startCase('__foo_bar__'); - * // => 'Foo Bar' + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' */ var startCase = createCompounder(function(result, word, index) { - return result + (index ? ' ' : '') + capitalize(word); + return result + (index ? ' ' : '') + upperFirst(word); }); /** @@ -12706,11 +14636,13 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String - * @param {string} [string=''] The string to search. + * @param {string} [string=''] The string to inspect. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. - * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. * @example * * _.startsWith('abc', 'a'); @@ -12724,8 +14656,12 @@ */ function startsWith(string, target, position) { string = toString(string); - position = baseClamp(toInteger(position), 0, string.length); - return string.lastIndexOf(target, position) == position; + position = position == null + ? 0 + : baseClamp(toInteger(position), 0, string.length); + + target = baseToString(target); + return string.slice(position, position + target.length) == target; } /** @@ -12733,7 +14669,7 @@ * in "interpolate" delimiters, HTML-escape interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data * properties may be accessed as free variables in the template. If a setting - * object is given it takes precedence over `_.templateSettings` values. + * object is given, it takes precedence over `_.templateSettings` values. * * **Note:** In the development build `_.template` utilizes * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) @@ -12746,17 +14682,24 @@ * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). * * @static + * @since 0.1.0 * @memberOf _ * @category String * @param {string} [string=''] The template string. - * @param {Object} [options] The options object. - * @param {RegExp} [options.escape] The HTML "escape" delimiter. - * @param {RegExp} [options.evaluate] The "evaluate" delimiter. - * @param {Object} [options.imports] An object to import into the template as free variables. - * @param {RegExp} [options.interpolate] The "interpolate" delimiter. - * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. - * @param {string} [options.variable] The data object variable name. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the compiled template function. * @example * @@ -12780,17 +14723,12 @@ * compiled({ 'user': 'barney' }); * // => 'hello barney!' * - * // Use the ES delimiter as an alternative to the default "interpolate" delimiter. + * // Use the ES template literal delimiter as an "interpolate" delimiter. + * // Disable support by replacing the "interpolate" delimiter. * var compiled = _.template('hello ${ user }!'); * compiled({ 'user': 'pebbles' }); * // => 'hello pebbles!' * - * // Use custom template delimiters. - * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; - * var compiled = _.template('hello {{ user }}!'); - * compiled({ 'user': 'mustache' }); - * // => 'hello mustache!' - * * // Use backslashes to treat delimiters as plain text. * var compiled = _.template('<%= "\\<%- value %\\>" %>'); * compiled({ 'value': 'ignored' }); @@ -12805,7 +14743,7 @@ * // Use the `sourceURL` option to specify a custom sourceURL for the template. * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' }); * compiled(data); - * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector + * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector. * * // Use the `variable` option to ensure a with-statement isn't used in the compiled template. * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' }); @@ -12816,16 +14754,23 @@ * // return __p; * // } * + * // Use custom template delimiters. + * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; + * var compiled = _.template('hello {{ user }}!'); + * compiled({ 'user': 'mustache' }); + * // => 'hello mustache!' + * * // Use the `source` property to inline compiled templates for meaningful * // line numbers in error messages and stack traces. - * fs.writeFileSync(path.join(cwd, 'jst.js'), '\ + * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\ * var JST = {\ * "main": ' + _.template(mainText).source + '\ * };\ * '); */ function template(string, options, guard) { - // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/) + // Based on John Resig's `tmpl` implementation + // (http://ejohn.org/blog/javascript-micro-templating/) // and Laura Doktorova's doT.js (https://github.com/olado/doT). var settings = lodash.templateSettings; @@ -12833,9 +14778,9 @@ options = undefined; } string = toString(string); - options = assignInWith({}, options, settings, assignInDefaults); + options = assignInWith({}, options, settings, customDefaultsAssignIn); - var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults), + var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); @@ -12932,17 +14877,19 @@ } /** - * Converts `string`, as a whole, to lower case. + * Converts `string`, as a whole, to lower case just like + * [String#toLowerCase](https://mdn.io/toLowerCase). * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the lower cased string. * @example * - * _.toLower('--Foo-Bar'); - * // => '--foo-bar' + * _.toLower('--Foo-Bar--'); + * // => '--foo-bar--' * * _.toLower('fooBar'); * // => 'foobar' @@ -12955,17 +14902,19 @@ } /** - * Converts `string`, as a whole, to upper case. + * Converts `string`, as a whole, to upper case just like + * [String#toUpperCase](https://mdn.io/toUpperCase). * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the upper cased string. * @example * - * _.toUpper('--foo-bar'); - * // => '--FOO-BAR' + * _.toUpper('--foo-bar--'); + * // => '--FOO-BAR--' * * _.toUpper('fooBar'); * // => 'FOOBAR' @@ -12982,10 +14931,11 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {string} Returns the trimmed string. * @example * @@ -13000,22 +14950,18 @@ */ function trim(string, chars, guard) { string = toString(string); - if (!string) { - return string; - } - if (guard || chars === undefined) { + if (string && (guard || chars === undefined)) { return string.replace(reTrim, ''); } - chars = (chars + ''); - if (!chars) { + if (!string || !(chars = baseToString(chars))) { return string; } var strSymbols = stringToArray(string), - chrSymbols = stringToArray(chars); + chrSymbols = stringToArray(chars), + start = charsStartIndex(strSymbols, chrSymbols), + end = charsEndIndex(strSymbols, chrSymbols) + 1; - return strSymbols - .slice(charsStartIndex(strSymbols, chrSymbols), charsEndIndex(strSymbols, chrSymbols) + 1) - .join(''); + return castSlice(strSymbols, start, end).join(''); } /** @@ -13023,10 +14969,11 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {string} Returns the trimmed string. * @example * @@ -13038,20 +14985,16 @@ */ function trimEnd(string, chars, guard) { string = toString(string); - if (!string) { - return string; - } - if (guard || chars === undefined) { + if (string && (guard || chars === undefined)) { return string.replace(reTrimEnd, ''); } - chars = (chars + ''); - if (!chars) { + if (!string || !(chars = baseToString(chars))) { return string; } - var strSymbols = stringToArray(string); - return strSymbols - .slice(0, charsEndIndex(strSymbols, stringToArray(chars)) + 1) - .join(''); + var strSymbols = stringToArray(string), + end = charsEndIndex(strSymbols, stringToArray(chars)) + 1; + + return castSlice(strSymbols, 0, end).join(''); } /** @@ -13059,10 +15002,11 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {string} Returns the trimmed string. * @example * @@ -13074,20 +15018,16 @@ */ function trimStart(string, chars, guard) { string = toString(string); - if (!string) { - return string; - } - if (guard || chars === undefined) { + if (string && (guard || chars === undefined)) { return string.replace(reTrimStart, ''); } - chars = (chars + ''); - if (!chars) { + if (!string || !(chars = baseToString(chars))) { return string; } - var strSymbols = stringToArray(string); - return strSymbols - .slice(charsStartIndex(strSymbols, stringToArray(chars))) - .join(''); + var strSymbols = stringToArray(string), + start = charsStartIndex(strSymbols, stringToArray(chars)); + + return castSlice(strSymbols, start).join(''); } /** @@ -13097,9 +15037,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to truncate. - * @param {Object} [options=({})] The options object. + * @param {Object} [options={}] The options object. * @param {number} [options.length=30] The maximum string length. * @param {string} [options.omission='...'] The string to indicate text is omitted. * @param {RegExp|string} [options.separator] The separator pattern to truncate to. @@ -13133,12 +15074,12 @@ if (isObject(options)) { var separator = 'separator' in options ? options.separator : separator; length = 'length' in options ? toInteger(options.length) : length; - omission = 'omission' in options ? toString(options.omission) : omission; + omission = 'omission' in options ? baseToString(options.omission) : omission; } string = toString(string); var strLength = string.length; - if (reHasComplexSymbol.test(string)) { + if (hasUnicode(string)) { var strSymbols = stringToArray(string); strLength = strSymbols.length; } @@ -13150,7 +15091,7 @@ return omission; } var result = strSymbols - ? strSymbols.slice(0, end).join('') + ? castSlice(strSymbols, 0, end).join('') : string.slice(0, end); if (separator === undefined) { @@ -13173,7 +15114,7 @@ } result = result.slice(0, newEnd === undefined ? end : newEnd); } - } else if (string.indexOf(separator, end) != end) { + } else if (string.indexOf(baseToString(separator), end) != end) { var index = result.lastIndexOf(separator); if (index > -1) { result = result.slice(0, index); @@ -13184,14 +15125,15 @@ /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their - * corresponding characters. + * `&`, `<`, `>`, `"`, and `'` in `string` to + * their corresponding characters. * - * **Note:** No other HTML entities are unescaped. To unescape additional HTML - * entities use a third-party library like [_he_](https://mths.be/he). + * **Note:** No other HTML entities are unescaped. To unescape additional + * HTML entities use a third-party library like [_he_](https://mths.be/he). * * @static * @memberOf _ + * @since 0.6.0 * @category String * @param {string} [string=''] The string to unescape. * @returns {string} Returns the unescaped string. @@ -13212,6 +15154,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the upper cased string. @@ -13231,14 +15174,34 @@ }); /** + * Converts the first character of `string` to upper case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.upperFirst('fred'); + * // => 'Fred' + * + * _.upperFirst('FRED'); + * // => 'FRED' + */ + var upperFirst = createCaseFirst('toUpperCase'); + + /** * Splits `string` into an array of its words. * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to inspect. * @param {RegExp|string} [pattern] The pattern to match words. - * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the words of `string`. * @example * @@ -13253,7 +15216,7 @@ pattern = guard ? undefined : pattern; if (pattern === undefined) { - pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord; + return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); } return string.match(pattern) || []; } @@ -13266,8 +15229,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Util * @param {Function} func The function to attempt. + * @param {...*} [args] The arguments to invoke `func` with. * @returns {*} Returns the `func` result or error object. * @example * @@ -13280,7 +15245,7 @@ * elements = []; * } */ - var attempt = rest(function(func, args) { + var attempt = baseRest(function(func, args) { try { return apply(func, undefined, args); } catch (e) { @@ -13295,49 +15260,51 @@ * **Note:** This method doesn't set the "length" property of bound functions. * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @param {Object} object The object to bind and assign the bound methods to. - * @param {...(string|string[])} methodNames The object method names to bind, - * specified individually or in arrays. + * @param {...(string|string[])} methodNames The object method names to bind. * @returns {Object} Returns `object`. * @example * * var view = { * 'label': 'docs', - * 'onClick': function() { + * 'click': function() { * console.log('clicked ' + this.label); * } * }; * - * _.bindAll(view, 'onClick'); - * jQuery(element).on('click', view.onClick); - * // => logs 'clicked docs' when clicked + * _.bindAll(view, ['click']); + * jQuery(element).on('click', view.click); + * // => Logs 'clicked docs' when clicked. */ - var bindAll = rest(function(object, methodNames) { - arrayEach(baseFlatten(methodNames, 1), function(key) { - object[key] = bind(object[key], object); + var bindAll = flatRest(function(object, methodNames) { + arrayEach(methodNames, function(key) { + key = toKey(key); + baseAssignValue(object, key, bind(object[key], object)); }); return object; }); /** - * Creates a function that iterates over `pairs` invoking the corresponding + * Creates a function that iterates over `pairs` and invokes the corresponding * function of the first predicate to return truthy. The predicate-function * pairs are invoked with the `this` binding and arguments of the created * function. * * @static * @memberOf _ + * @since 4.0.0 * @category Util * @param {Array} pairs The predicate-function pairs. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new composite function. * @example * * var func = _.cond([ * [_.matches({ 'a': 1 }), _.constant('matches A')], * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], - * [_.constant(true), _.constant('no match')] + * [_.stubTrue, _.constant('no match')] * ]); * * func({ 'a': 1, 'b': 2 }); @@ -13350,7 +15317,7 @@ * // => 'no match' */ function cond(pairs) { - var length = pairs ? pairs.length : 0, + var length = pairs == null ? 0 : pairs.length, toIteratee = getIteratee(); pairs = !length ? [] : arrayMap(pairs, function(pair) { @@ -13360,7 +15327,7 @@ return [toIteratee(pair[0]), pair[1]]; }); - return rest(function(args) { + return baseRest(function(args) { var index = -1; while (++index < length) { var pair = pairs[index]; @@ -13376,23 +15343,27 @@ * the corresponding property values of a given object, returning `true` if * all predicates return truthy, else `false`. * + * **Note:** The created function is equivalent to `_.conformsTo` with + * `source` partially applied. + * * @static * @memberOf _ + * @since 4.0.0 * @category Util * @param {Object} source The object of property predicates to conform to. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new spec function. * @example * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } + * var objects = [ + * { 'a': 2, 'b': 1 }, + * { 'a': 1, 'b': 2 } * ]; * - * _.filter(users, _.conforms({ 'age': _.partial(_.gt, _, 38) })); - * // => [{ 'user': 'fred', 'age': 40 }] + * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } })); + * // => [{ 'a': 1, 'b': 2 }] */ function conforms(source) { - return baseConforms(baseClone(source, true)); + return baseConforms(baseClone(source, CLONE_DEEP_FLAG)); } /** @@ -13400,15 +15371,18 @@ * * @static * @memberOf _ + * @since 2.4.0 * @category Util * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new constant function. * @example * - * var object = { 'user': 'fred' }; - * var getter = _.constant(object); + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] * - * getter() === object; + * console.log(objects[0] === objects[1]); * // => true */ function constant(value) { @@ -13418,22 +15392,48 @@ } /** + * Checks `value` to determine whether a default value should be returned in + * its place. The `defaultValue` is returned if `value` is `NaN`, `null`, + * or `undefined`. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Util + * @param {*} value The value to check. + * @param {*} defaultValue The default value. + * @returns {*} Returns the resolved value. + * @example + * + * _.defaultTo(1, 10); + * // => 1 + * + * _.defaultTo(undefined, 10); + * // => 10 + */ + function defaultTo(value, defaultValue) { + return (value == null || value !== value) ? defaultValue : value; + } + + /** * Creates a function that returns the result of invoking the given functions * with the `this` binding of the created function, where each successive * invocation is supplied the return value of the previous. * * @static * @memberOf _ + * @since 3.0.0 * @category Util - * @param {...(Function|Function[])} [funcs] Functions to invoke. - * @returns {Function} Returns the new function. + * @param {...(Function|Function[])} [funcs] The functions to invoke. + * @returns {Function} Returns the new composite function. + * @see _.flowRight * @example * * function square(n) { * return n * n; * } * - * var addSquare = _.flow(_.add, square); + * var addSquare = _.flow([_.add, square]); * addSquare(1, 2); * // => 9 */ @@ -13444,35 +15444,38 @@ * invokes the given functions from right to left. * * @static + * @since 3.0.0 * @memberOf _ * @category Util - * @param {...(Function|Function[])} [funcs] Functions to invoke. - * @returns {Function} Returns the new function. + * @param {...(Function|Function[])} [funcs] The functions to invoke. + * @returns {Function} Returns the new composite function. + * @see _.flow * @example * * function square(n) { * return n * n; * } * - * var addSquare = _.flowRight(square, _.add); + * var addSquare = _.flowRight([square, _.add]); * addSquare(1, 2); * // => 9 */ var flowRight = createFlow(true); /** - * This method returns the first argument given to it. + * This method returns the first argument it receives. * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @param {*} value Any value. * @returns {*} Returns `value`. * @example * - * var object = { 'user': 'fred' }; + * var object = { 'a': 1 }; * - * _.identity(object) === object; + * console.log(_.identity(object) === object); * // => true */ function identity(value) { @@ -13481,12 +15484,13 @@ /** * Creates a function that invokes `func` with the arguments of the created - * function. If `func` is a property name the created callback returns the - * property value for a given element. If `func` is an object the created - * callback returns `true` for elements that contain the equivalent object - * properties, otherwise it returns `false`. + * function. If `func` is a property name, the created function returns the + * property value for a given element. If `func` is an array or object, the + * created function returns `true` for elements that contain the equivalent + * source properties, otherwise it returns `false`. * * @static + * @since 4.0.0 * @memberOf _ * @category Util * @param {*} [func=_.identity] The value to convert to a callback. @@ -13494,50 +15498,66 @@ * @example * * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } * ]; * + * // The `_.matches` iteratee shorthand. + * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); + * // => [{ 'user': 'barney', 'age': 36, 'active': true }] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, _.iteratee(['user', 'fred'])); + * // => [{ 'user': 'fred', 'age': 40 }] + * + * // The `_.property` iteratee shorthand. + * _.map(users, _.iteratee('user')); + * // => ['barney', 'fred'] + * * // Create custom iteratee shorthands. - * _.iteratee = _.wrap(_.iteratee, function(callback, func) { - * var p = /^(\S+)\s*([<>])\s*(\S+)$/.exec(func); - * return !p ? callback(func) : function(object) { - * return (p[2] == '>' ? object[p[1]] > p[3] : object[p[1]] < p[3]); + * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { + * return !_.isRegExp(func) ? iteratee(func) : function(string) { + * return func.test(string); * }; * }); * - * _.filter(users, 'age > 36'); - * // => [{ 'user': 'fred', 'age': 40 }] + * _.filter(['abc', 'def'], /ef/); + * // => ['def'] */ function iteratee(func) { - return baseIteratee(typeof func == 'function' ? func : baseClone(func, true)); + return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG)); } /** * Creates a function that performs a partial deep comparison between a given * object and `source`, returning `true` if the given object has equivalent - * property values, else `false`. The created function is equivalent to - * `_.isMatch` with a `source` partially applied. + * property values, else `false`. * - * **Note:** This method supports comparing the same values as `_.isEqual`. + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ + * @since 3.0.0 * @category Util * @param {Object} source The object of property values to match. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new spec function. * @example * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false } + * var objects = [ + * { 'a': 1, 'b': 2, 'c': 3 }, + * { 'a': 4, 'b': 5, 'c': 6 } * ]; * - * _.filter(users, _.matches({ 'age': 40, 'active': false })); - * // => [{ 'user': 'fred', 'age': 40, 'active': false }] + * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); + * // => [{ 'a': 4, 'b': 5, 'c': 6 }] */ function matches(source) { - return baseMatches(baseClone(source, true)); + return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); } /** @@ -13545,26 +15565,29 @@ * value at `path` of a given object to `srcValue`, returning `true` if the * object value is equivalent, else `false`. * - * **Note:** This method supports comparing the same values as `_.isEqual`. + * **Note:** Partial comparisons will match empty array and empty object + * `srcValue` values against any array or object value, respectively. See + * `_.isEqual` for a list of supported value comparisons. * * @static * @memberOf _ + * @since 3.2.0 * @category Util * @param {Array|string} path The path of the property to get. * @param {*} srcValue The value to match. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new spec function. * @example * - * var users = [ - * { 'user': 'barney' }, - * { 'user': 'fred' } + * var objects = [ + * { 'a': 1, 'b': 2, 'c': 3 }, + * { 'a': 4, 'b': 5, 'c': 6 } * ]; * - * _.find(users, _.matchesProperty('user', 'fred')); - * // => { 'user': 'fred' } + * _.find(objects, _.matchesProperty('a', 4)); + * // => { 'a': 4, 'b': 5, 'c': 6 } */ function matchesProperty(path, srcValue) { - return baseMatchesProperty(path, baseClone(srcValue, true)); + return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG)); } /** @@ -13573,24 +15596,25 @@ * * @static * @memberOf _ + * @since 3.7.0 * @category Util * @param {Array|string} path The path of the method to invoke. * @param {...*} [args] The arguments to invoke the method with. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new invoker function. * @example * * var objects = [ - * { 'a': { 'b': { 'c': _.constant(2) } } }, - * { 'a': { 'b': { 'c': _.constant(1) } } } + * { 'a': { 'b': _.constant(2) } }, + * { 'a': { 'b': _.constant(1) } } * ]; * - * _.map(objects, _.method('a.b.c')); + * _.map(objects, _.method('a.b')); * // => [2, 1] * - * _.invokeMap(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c'); - * // => [1, 2] + * _.map(objects, _.method(['a', 'b'])); + * // => [2, 1] */ - var method = rest(function(path, args) { + var method = baseRest(function(path, args) { return function(object) { return baseInvoke(object, path, args); }; @@ -13603,10 +15627,11 @@ * * @static * @memberOf _ + * @since 3.7.0 * @category Util * @param {Object} object The object to query. * @param {...*} [args] The arguments to invoke the method with. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new invoker function. * @example * * var array = _.times(3, _.constant), @@ -13618,28 +15643,28 @@ * _.map([['a', '2'], ['c', '0']], _.methodOf(object)); * // => [2, 0] */ - var methodOf = rest(function(object, args) { + var methodOf = baseRest(function(object, args) { return function(path) { return baseInvoke(object, path, args); }; }); /** - * Adds all own enumerable function properties of a source object to the - * destination object. If `object` is a function then methods are added to - * its prototype as well. + * Adds all own enumerable string keyed function properties of a source + * object to the destination object. If `object` is a function, then methods + * are added to its prototype as well. * * **Note:** Use `_.runInContext` to create a pristine `lodash` function to * avoid conflicts caused by modifying the original. * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @param {Function|Object} [object=lodash] The destination object. * @param {Object} source The object of functions to add. - * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added - * are chainable. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.chain=true] Specify whether mixins are chainable. * @returns {Function|Object} Returns `object`. * @example * @@ -13671,7 +15696,7 @@ object = this; methodNames = baseFunctions(source, keys(source)); } - var chain = (isObject(options) && 'chain' in options) ? options.chain : true, + var chain = !(isObject(options) && 'chain' in options) || !!options.chain, isFunc = isFunction(object); arrayEach(methodNames, function(methodName) { @@ -13701,6 +15726,7 @@ * the `lodash` function. * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @returns {Function} Returns the `lodash` function. @@ -13716,57 +15742,62 @@ } /** - * A no-operation function that returns `undefined` regardless of the - * arguments it receives. + * This method returns `undefined`. * * @static * @memberOf _ + * @since 2.3.0 * @category Util * @example * - * var object = { 'user': 'fred' }; - * - * _.noop(object) === undefined; - * // => true + * _.times(2, _.noop); + * // => [undefined, undefined] */ function noop() { // No operation performed. } /** - * Creates a function that returns its nth argument. + * Creates a function that gets the argument at index `n`. If `n` is negative, + * the nth argument from the end is returned. * * @static * @memberOf _ + * @since 4.0.0 * @category Util * @param {number} [n=0] The index of the argument to return. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new pass-thru function. * @example * * var func = _.nthArg(1); - * - * func('a', 'b', 'c'); + * func('a', 'b', 'c', 'd'); * // => 'b' + * + * var func = _.nthArg(-2); + * func('a', 'b', 'c', 'd'); + * // => 'c' */ function nthArg(n) { n = toInteger(n); - return function() { - return arguments[n]; - }; + return baseRest(function(args) { + return baseNth(args, n); + }); } /** - * Creates a function that invokes `iteratees` with the arguments provided - * to the created function and returns their results. + * Creates a function that invokes `iteratees` with the arguments it receives + * and returns their results. * * @static * @memberOf _ + * @since 4.0.0 * @category Util - * @param {...(Function|Function[])} iteratees The iteratees to invoke. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to invoke. * @returns {Function} Returns the new function. * @example * - * var func = _.over(Math.max, Math.min); + * var func = _.over([Math.max, Math.min]); * * func(1, 2, 3, 4); * // => [4, 1] @@ -13775,16 +15806,18 @@ /** * Creates a function that checks if **all** of the `predicates` return - * truthy when invoked with the arguments provided to the created function. + * truthy when invoked with the arguments it receives. * * @static * @memberOf _ + * @since 4.0.0 * @category Util - * @param {...(Function|Function[])} predicates The predicates to check. + * @param {...(Function|Function[])} [predicates=[_.identity]] + * The predicates to check. * @returns {Function} Returns the new function. * @example * - * var func = _.overEvery(Boolean, isFinite); + * var func = _.overEvery([Boolean, isFinite]); * * func('1'); * // => true @@ -13799,16 +15832,18 @@ /** * Creates a function that checks if **any** of the `predicates` return - * truthy when invoked with the arguments provided to the created function. + * truthy when invoked with the arguments it receives. * * @static * @memberOf _ + * @since 4.0.0 * @category Util - * @param {...(Function|Function[])} predicates The predicates to check. + * @param {...(Function|Function[])} [predicates=[_.identity]] + * The predicates to check. * @returns {Function} Returns the new function. * @example * - * var func = _.overSome(Boolean, isFinite); + * var func = _.overSome([Boolean, isFinite]); * * func('1'); * // => true @@ -13826,24 +15861,25 @@ * * @static * @memberOf _ + * @since 2.4.0 * @category Util * @param {Array|string} path The path of the property to get. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new accessor function. * @example * * var objects = [ - * { 'a': { 'b': { 'c': 2 } } }, - * { 'a': { 'b': { 'c': 1 } } } + * { 'a': { 'b': 2 } }, + * { 'a': { 'b': 1 } } * ]; * - * _.map(objects, _.property('a.b.c')); + * _.map(objects, _.property('a.b')); * // => [2, 1] * - * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); + * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); * // => [1, 2] */ function property(path) { - return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); } /** @@ -13852,9 +15888,10 @@ * * @static * @memberOf _ + * @since 3.0.0 * @category Util * @param {Object} object The object to query. - * @returns {Function} Returns the new function. + * @returns {Function} Returns the new accessor function. * @example * * var array = [0, 1, 2], @@ -13875,19 +15912,21 @@ /** * Creates an array of numbers (positive and/or negative) progressing from * `start` up to, but not including, `end`. A step of `-1` is used if a negative - * `start` is specified without an `end` or `step`. If `end` is not specified + * `start` is specified without an `end` or `step`. If `end` is not specified, * it's set to `start` with `start` then set to `0`. * * **Note:** JavaScript follows the IEEE-754 standard for resolving * floating-point values which can produce unexpected results. * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns the new array of numbers. + * @returns {Array} Returns the range of numbers. + * @see _.inRange, _.rangeRight * @example * * _.range(4); @@ -13919,11 +15958,13 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Util * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns the new array of numbers. + * @returns {Array} Returns the range of numbers. + * @see _.inRange, _.range * @example * * _.rangeRight(4); @@ -13950,10 +15991,106 @@ var rangeRight = createRange(true); /** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ + function stubArray() { + return []; + } + + /** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ + function stubFalse() { + return false; + } + + /** + * This method returns a new empty object. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Object} Returns the new empty object. + * @example + * + * var objects = _.times(2, _.stubObject); + * + * console.log(objects); + * // => [{}, {}] + * + * console.log(objects[0] === objects[1]); + * // => false + */ + function stubObject() { + return {}; + } + + /** + * This method returns an empty string. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {string} Returns the empty string. + * @example + * + * _.times(2, _.stubString); + * // => ['', ''] + */ + function stubString() { + return ''; + } + + /** + * This method returns `true`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `true`. + * @example + * + * _.times(2, _.stubTrue); + * // => [true, true] + */ + function stubTrue() { + return true; + } + + /** * Invokes the iteratee `n` times, returning an array of the results of * each invocation. The iteratee is invoked with one argument; (index). * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @param {number} n The number of times to invoke `iteratee`. @@ -13964,8 +16101,8 @@ * _.times(3, String); * // => ['0', '1', '2'] * - * _.times(4, _.constant(true)); - * // => [true, true, true, true] + * _.times(4, _.constant(0)); + * // => [0, 0, 0, 0] */ function times(n, iteratee) { n = toInteger(n); @@ -13975,7 +16112,7 @@ var index = MAX_ARRAY_LENGTH, length = nativeMin(n, MAX_ARRAY_LENGTH); - iteratee = baseCastFunction(iteratee); + iteratee = getIteratee(iteratee); n -= MAX_ARRAY_LENGTH; var result = baseTimes(length, iteratee); @@ -13990,6 +16127,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Util * @param {*} value The value to convert. * @returns {Array} Returns the new property path array. @@ -14000,24 +16138,19 @@ * * _.toPath('a[0].b.c'); * // => ['a', '0', 'b', 'c'] - * - * var path = ['a', 'b', 'c'], - * newPath = _.toPath(path); - * - * console.log(newPath); - * // => ['a', 'b', 'c'] - * - * console.log(path === newPath); - * // => false */ function toPath(value) { - return isArray(value) ? arrayMap(value, String) : stringToPath(value); + if (isArray(value)) { + return arrayMap(value, toKey); + } + return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value))); } /** - * Generates a unique ID. If `prefix` is given the ID is appended to it. + * Generates a unique ID. If `prefix` is given, the ID is appended to it. * * @static + * @since 0.1.0 * @memberOf _ * @category Util * @param {string} [prefix=''] The value to prefix the ID with. @@ -14042,6 +16175,7 @@ * * @static * @memberOf _ + * @since 3.4.0 * @category Math * @param {number} augend The first number in an addition. * @param {number} addend The second number in an addition. @@ -14051,25 +16185,16 @@ * _.add(6, 4); * // => 10 */ - function add(augend, addend) { - var result; - if (augend === undefined && addend === undefined) { - return 0; - } - if (augend !== undefined) { - result = augend; - } - if (addend !== undefined) { - result = result === undefined ? addend : (result + addend); - } - return result; - } + var add = createMathOperation(function(augend, addend) { + return augend + addend; + }, 0); /** * Computes `number` rounded up to `precision`. * * @static * @memberOf _ + * @since 3.10.0 * @category Math * @param {number} number The number to round up. * @param {number} [precision=0] The precision to round up to. @@ -14088,10 +16213,30 @@ var ceil = createRound('ceil'); /** + * Divide two numbers. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {number} dividend The first number in a division. + * @param {number} divisor The second number in a division. + * @returns {number} Returns the quotient. + * @example + * + * _.divide(6, 4); + * // => 1.5 + */ + var divide = createMathOperation(function(dividend, divisor) { + return dividend / divisor; + }, 1); + + /** * Computes `number` rounded down to `precision`. * * @static * @memberOf _ + * @since 3.10.0 * @category Math * @param {number} number The number to round down. * @param {number} [precision=0] The precision to round down to. @@ -14110,10 +16255,11 @@ var floor = createRound('floor'); /** - * Computes the maximum value of `array`. If `array` is empty or falsey + * Computes the maximum value of `array`. If `array` is empty or falsey, * `undefined` is returned. * * @static + * @since 0.1.0 * @memberOf _ * @category Math * @param {Array} array The array to iterate over. @@ -14128,7 +16274,7 @@ */ function max(array) { return (array && array.length) - ? baseExtremum(array, identity, gt) + ? baseExtremum(array, identity, baseGt) : undefined; } @@ -14139,9 +16285,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Math * @param {Array} array The array to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {*} Returns the maximum value. * @example * @@ -14156,7 +16303,7 @@ */ function maxBy(array, iteratee) { return (array && array.length) - ? baseExtremum(array, getIteratee(iteratee), gt) + ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) : undefined; } @@ -14165,6 +16312,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Math * @param {Array} array The array to iterate over. * @returns {number} Returns the mean. @@ -14174,14 +16322,42 @@ * // => 5 */ function mean(array) { - return sum(array) / (array ? array.length : 0); + return baseMean(array, identity); + } + + /** + * This method is like `_.mean` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the value to be averaged. + * The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the mean. + * @example + * + * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; + * + * _.meanBy(objects, function(o) { return o.n; }); + * // => 5 + * + * // The `_.property` iteratee shorthand. + * _.meanBy(objects, 'n'); + * // => 5 + */ + function meanBy(array, iteratee) { + return baseMean(array, getIteratee(iteratee, 2)); } /** - * Computes the minimum value of `array`. If `array` is empty or falsey + * Computes the minimum value of `array`. If `array` is empty or falsey, * `undefined` is returned. * * @static + * @since 0.1.0 * @memberOf _ * @category Math * @param {Array} array The array to iterate over. @@ -14196,7 +16372,7 @@ */ function min(array) { return (array && array.length) - ? baseExtremum(array, identity, lt) + ? baseExtremum(array, identity, baseLt) : undefined; } @@ -14207,9 +16383,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Math * @param {Array} array The array to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {*} Returns the minimum value. * @example * @@ -14224,15 +16401,35 @@ */ function minBy(array, iteratee) { return (array && array.length) - ? baseExtremum(array, getIteratee(iteratee), lt) + ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) : undefined; } /** + * Multiply two numbers. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {number} multiplier The first number in a multiplication. + * @param {number} multiplicand The second number in a multiplication. + * @returns {number} Returns the product. + * @example + * + * _.multiply(6, 4); + * // => 24 + */ + var multiply = createMathOperation(function(multiplier, multiplicand) { + return multiplier * multiplicand; + }, 1); + + /** * Computes `number` rounded to `precision`. * * @static * @memberOf _ + * @since 3.10.0 * @category Math * @param {number} number The number to round. * @param {number} [precision=0] The precision to round to. @@ -14255,6 +16452,7 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Math * @param {number} minuend The first number in a subtraction. * @param {number} subtrahend The second number in a subtraction. @@ -14264,25 +16462,16 @@ * _.subtract(6, 4); * // => 2 */ - function subtract(minuend, subtrahend) { - var result; - if (minuend === undefined && subtrahend === undefined) { - return 0; - } - if (minuend !== undefined) { - result = minuend; - } - if (subtrahend !== undefined) { - result = result === undefined ? subtrahend : (result - subtrahend); - } - return result; - } + var subtract = createMathOperation(function(minuend, subtrahend) { + return minuend - subtrahend; + }, 0); /** * Computes the sum of the values in `array`. * * @static * @memberOf _ + * @since 3.4.0 * @category Math * @param {Array} array The array to iterate over. * @returns {number} Returns the sum. @@ -14304,9 +16493,10 @@ * * @static * @memberOf _ + * @since 4.0.0 * @category Math * @param {Array} array The array to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. * @returns {number} Returns the sum. * @example * @@ -14321,45 +16511,13 @@ */ function sumBy(array, iteratee) { return (array && array.length) - ? baseSum(array, getIteratee(iteratee)) + ? baseSum(array, getIteratee(iteratee, 2)) : 0; } /*------------------------------------------------------------------------*/ - // Ensure wrappers are instances of `baseLodash`. - lodash.prototype = baseLodash.prototype; - - LodashWrapper.prototype = baseCreate(baseLodash.prototype); - LodashWrapper.prototype.constructor = LodashWrapper; - - LazyWrapper.prototype = baseCreate(baseLodash.prototype); - LazyWrapper.prototype.constructor = LazyWrapper; - - // Avoid inheriting from `Object.prototype` when possible. - Hash.prototype = nativeCreate ? nativeCreate(null) : objectProto; - - // Add functions to the `MapCache`. - MapCache.prototype.clear = mapClear; - MapCache.prototype['delete'] = mapDelete; - MapCache.prototype.get = mapGet; - MapCache.prototype.has = mapHas; - MapCache.prototype.set = mapSet; - - // Add functions to the `SetCache`. - SetCache.prototype.push = cachePush; - - // Add functions to the `Stack` cache. - Stack.prototype.clear = stackClear; - Stack.prototype['delete'] = stackDelete; - Stack.prototype.get = stackGet; - Stack.prototype.has = stackHas; - Stack.prototype.set = stackSet; - - // Assign cache to `_.memoize`. - memoize.Cache = MapCache; - - // Add functions that return wrapped values when chaining. + // Add methods that return wrapped values in chain sequences. lodash.after = after; lodash.ary = ary; lodash.assign = assign; @@ -14398,6 +16556,8 @@ lodash.fill = fill; lodash.filter = filter; lodash.flatMap = flatMap; + lodash.flatMapDeep = flatMapDeep; + lodash.flatMapDepth = flatMapDepth; lodash.flatten = flatten; lodash.flattenDeep = flattenDeep; lodash.flattenDepth = flattenDepth; @@ -14450,6 +16610,7 @@ lodash.pull = pull; lodash.pullAll = pullAll; lodash.pullAllBy = pullAllBy; + lodash.pullAllWith = pullAllWith; lodash.pullAt = pullAt; lodash.range = range; lodash.rangeRight = rangeRight; @@ -14492,6 +16653,8 @@ lodash.unset = unset; lodash.unzip = unzip; lodash.unzipWith = unzipWith; + lodash.update = update; + lodash.updateWith = updateWith; lodash.values = values; lodash.valuesIn = valuesIn; lodash.without = without; @@ -14506,15 +16669,17 @@ lodash.zipWith = zipWith; // Add aliases. + lodash.entries = toPairs; + lodash.entriesIn = toPairsIn; lodash.extend = assignIn; lodash.extendWith = assignInWith; - // Add functions to `lodash.prototype`. + // Add methods to `lodash.prototype`. mixin(lodash, lodash); /*------------------------------------------------------------------------*/ - // Add functions that return unwrapped values when chaining. + // Add methods that return unwrapped values in chain sequences. lodash.add = add; lodash.attempt = attempt; lodash.camelCase = camelCase; @@ -14525,7 +16690,10 @@ lodash.cloneDeep = cloneDeep; lodash.cloneDeepWith = cloneDeepWith; lodash.cloneWith = cloneWith; + lodash.conformsTo = conformsTo; lodash.deburr = deburr; + lodash.defaultTo = defaultTo; + lodash.divide = divide; lodash.endsWith = endsWith; lodash.eq = eq; lodash.escape = escape; @@ -14603,8 +16771,16 @@ lodash.max = max; lodash.maxBy = maxBy; lodash.mean = mean; + lodash.meanBy = meanBy; lodash.min = min; lodash.minBy = minBy; + lodash.stubArray = stubArray; + lodash.stubFalse = stubFalse; + lodash.stubObject = stubObject; + lodash.stubString = stubString; + lodash.stubTrue = stubTrue; + lodash.multiply = multiply; + lodash.nth = nth; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; @@ -14637,6 +16813,7 @@ lodash.sumBy = sumBy; lodash.template = template; lodash.times = times; + lodash.toFinite = toFinite; lodash.toInteger = toInteger; lodash.toLength = toLength; lodash.toLower = toLower; @@ -14687,14 +16864,13 @@ // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. arrayEach(['drop', 'take'], function(methodName, index) { LazyWrapper.prototype[methodName] = function(n) { - var filtered = this.__filtered__; - if (filtered && !index) { - return new LazyWrapper(this); - } n = n === undefined ? 1 : nativeMax(toInteger(n), 0); - var result = this.clone(); - if (filtered) { + var result = (this.__filtered__ && !index) + ? new LazyWrapper(this) + : this.clone(); + + if (result.__filtered__) { result.__takeCount__ = nativeMin(n, result.__takeCount__); } else { result.__views__.push({ @@ -14756,7 +16932,7 @@ return this.reverse().find(predicate); }; - LazyWrapper.prototype.invokeMap = rest(function(path, args) { + LazyWrapper.prototype.invokeMap = baseRest(function(path, args) { if (typeof path == 'function') { return new LazyWrapper(this); } @@ -14766,10 +16942,7 @@ }); LazyWrapper.prototype.reject = function(predicate) { - predicate = getIteratee(predicate, 3); - return this.filter(function(value) { - return !predicate(value); - }); + return this.filter(negate(getIteratee(predicate))); }; LazyWrapper.prototype.slice = function(start, end) { @@ -14844,7 +17017,7 @@ }; }); - // Add `Array` and `String` methods to `lodash.prototype`. + // Add `Array` methods to `lodash.prototype`. arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', @@ -14853,15 +17026,16 @@ lodash.prototype[methodName] = function() { var args = arguments; if (retUnwrapped && !this.__chain__) { - return func.apply(this.value(), args); + var value = this.value(); + return func.apply(isArray(value) ? value : [], args); } return this[chainName](function(value) { - return func.apply(value, args); + return func.apply(isArray(value) ? value : [], args); }); }; }); - // Map minified function names to their real names. + // Map minified method names to their real names. baseForOwn(LazyWrapper.prototype, function(func, methodName) { var lodashFunc = lodash[methodName]; if (lodashFunc) { @@ -14872,56 +17046,57 @@ } }); - realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ + realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }]; - // Add functions to the lazy wrapper. + // Add methods to `LazyWrapper`. LazyWrapper.prototype.clone = lazyClone; LazyWrapper.prototype.reverse = lazyReverse; LazyWrapper.prototype.value = lazyValue; - // Add chaining functions to the `lodash` wrapper. + // Add chain sequence methods to the `lodash` wrapper. lodash.prototype.at = wrapperAt; lodash.prototype.chain = wrapperChain; lodash.prototype.commit = wrapperCommit; - lodash.prototype.flatMap = wrapperFlatMap; lodash.prototype.next = wrapperNext; lodash.prototype.plant = wrapperPlant; lodash.prototype.reverse = wrapperReverse; lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; - if (iteratorSymbol) { - lodash.prototype[iteratorSymbol] = wrapperToIterator; + // Add lazy aliases. + lodash.prototype.first = lodash.prototype.head; + + if (symIterator) { + lodash.prototype[symIterator] = wrapperToIterator; } return lodash; - } + }); /*--------------------------------------------------------------------------*/ // Export lodash. var _ = runInContext(); - // Expose lodash on the free variable `window` or `self` when available. This - // prevents errors in cases where lodash is loaded by a script tag in the presence - // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details. - (freeWindow || freeSelf || {})._ = _; - - // Some AMD build optimizers like r.js check for condition patterns like the following: + // Some AMD build optimizers, like r.js, check for condition patterns like: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose Lodash on the global object to prevent errors when Lodash is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + // Use `_.noConflict` to remove Lodash from the global object. + root._ = _; + // Define as an anonymous module so, through path mapping, it can be // referenced as the "underscore" module. define(function() { return _; }); } - // Check for `exports` after `define` in case a build optimizer adds an `exports` object. - else if (freeExports && freeModule) { + // Check for `exports` after `define` in case a build optimizer adds it. + else if (freeModule) { // Export for Node.js. - if (moduleExports) { - (freeModule.exports = _)._ = _; - } + (freeModule.exports = _)._ = _; // Export for CommonJS support. freeExports._ = _; } @@ -14929,4 +17104,4 @@ // Export to the global object. root._ = _; } -}.call(this)); +}.call(this));
\ No newline at end of file |