1/** 2 * lodash (Custom Build) <https://lodash.com/> 3 * Build: `lodash modularize exports="npm" -o ./` 4 * Copyright jQuery Foundation and other contributors <https://jquery.org/> 5 * Released under MIT license <https://lodash.com/license> 6 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> 7 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 8 */ 9var createSet = require('lodash._createset'), 10 root = require('lodash._root'); 11 12/** Used as the size to enable large array optimizations. */ 13var LARGE_ARRAY_SIZE = 200; 14 15/** Used to stand-in for `undefined` hash values. */ 16var HASH_UNDEFINED = '__lodash_hash_undefined__'; 17 18/** `Object#toString` result references. */ 19var funcTag = '[object Function]', 20 genTag = '[object GeneratorFunction]'; 21 22/** 23 * Used to match `RegExp` 24 * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). 25 */ 26var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; 27 28/** Used to detect host constructors (Safari). */ 29var reIsHostCtor = /^\[object .+?Constructor\]$/; 30 31/** 32 * A specialized version of `_.includes` for arrays without support for 33 * specifying an index to search from. 34 * 35 * @private 36 * @param {Array} array The array to search. 37 * @param {*} target The value to search for. 38 * @returns {boolean} Returns `true` if `target` is found, else `false`. 39 */ 40function arrayIncludes(array, value) { 41 return !!array.length && baseIndexOf(array, value, 0) > -1; 42} 43 44/** 45 * This function is like `arrayIncludes` except that it accepts a comparator. 46 * 47 * @private 48 * @param {Array} array The array to search. 49 * @param {*} target The value to search for. 50 * @param {Function} comparator The comparator invoked per element. 51 * @returns {boolean} Returns `true` if `target` is found, else `false`. 52 */ 53function arrayIncludesWith(array, value, comparator) { 54 var index = -1, 55 length = array.length; 56 57 while (++index < length) { 58 if (comparator(value, array[index])) { 59 return true; 60 } 61 } 62 return false; 63} 64 65/** 66 * The base implementation of `_.indexOf` without `fromIndex` bounds checks. 67 * 68 * @private 69 * @param {Array} array The array to search. 70 * @param {*} value The value to search for. 71 * @param {number} fromIndex The index to search from. 72 * @returns {number} Returns the index of the matched value, else `-1`. 73 */ 74function baseIndexOf(array, value, fromIndex) { 75 if (value !== value) { 76 return indexOfNaN(array, fromIndex); 77 } 78 var index = fromIndex - 1, 79 length = array.length; 80 81 while (++index < length) { 82 if (array[index] === value) { 83 return index; 84 } 85 } 86 return -1; 87} 88 89/** 90 * Checks if a cache value for `key` exists. 91 * 92 * @private 93 * @param {Object} cache The cache to query. 94 * @param {string} key The key of the entry to check. 95 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 96 */ 97function cacheHas(cache, key) { 98 return cache.has(key); 99} 100 101/** 102 * Gets the index at which the first occurrence of `NaN` is found in `array`. 103 * 104 * @private 105 * @param {Array} array The array to search. 106 * @param {number} fromIndex The index to search from. 107 * @param {boolean} [fromRight] Specify iterating from right to left. 108 * @returns {number} Returns the index of the matched `NaN`, else `-1`. 109 */ 110function indexOfNaN(array, fromIndex, fromRight) { 111 var length = array.length, 112 index = fromIndex + (fromRight ? 0 : -1); 113 114 while ((fromRight ? index-- : ++index < length)) { 115 var other = array[index]; 116 if (other !== other) { 117 return index; 118 } 119 } 120 return -1; 121} 122 123/** 124 * Checks if `value` is a host object in IE < 9. 125 * 126 * @private 127 * @param {*} value The value to check. 128 * @returns {boolean} Returns `true` if `value` is a host object, else `false`. 129 */ 130function isHostObject(value) { 131 // Many host objects are `Object` objects that can coerce to strings 132 // despite having improperly defined `toString` methods. 133 var result = false; 134 if (value != null && typeof value.toString != 'function') { 135 try { 136 result = !!(value + ''); 137 } catch (e) {} 138 } 139 return result; 140} 141 142/** 143 * Converts `set` to an array of its values. 144 * 145 * @private 146 * @param {Object} set The set to convert. 147 * @returns {Array} Returns the values. 148 */ 149function setToArray(set) { 150 var index = -1, 151 result = Array(set.size); 152 153 set.forEach(function(value) { 154 result[++index] = value; 155 }); 156 return result; 157} 158 159/** Used for built-in method references. */ 160var arrayProto = Array.prototype, 161 objectProto = Object.prototype; 162 163/** Used to resolve the decompiled source of functions. */ 164var funcToString = Function.prototype.toString; 165 166/** Used to check objects for own properties. */ 167var hasOwnProperty = objectProto.hasOwnProperty; 168 169/** 170 * Used to resolve the 171 * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 172 * of values. 173 */ 174var objectToString = objectProto.toString; 175 176/** Used to detect if a method is native. */ 177var reIsNative = RegExp('^' + 178 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') 179 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' 180); 181 182/** Built-in value references. */ 183var splice = arrayProto.splice; 184 185/* Built-in method references that are verified to be native. */ 186var Map = getNative(root, 'Map'), 187 nativeCreate = getNative(Object, 'create'); 188 189/** 190 * Creates a hash object. 191 * 192 * @private 193 * @constructor 194 * @param {Array} [entries] The key-value pairs to cache. 195 */ 196function Hash(entries) { 197 var index = -1, 198 length = entries ? entries.length : 0; 199 200 this.clear(); 201 while (++index < length) { 202 var entry = entries[index]; 203 this.set(entry[0], entry[1]); 204 } 205} 206 207/** 208 * Removes all key-value entries from the hash. 209 * 210 * @private 211 * @name clear 212 * @memberOf Hash 213 */ 214function hashClear() { 215 this.__data__ = nativeCreate ? nativeCreate(null) : {}; 216} 217 218/** 219 * Removes `key` and its value from the hash. 220 * 221 * @private 222 * @name delete 223 * @memberOf Hash 224 * @param {Object} hash The hash to modify. 225 * @param {string} key The key of the value to remove. 226 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 227 */ 228function hashDelete(key) { 229 return this.has(key) && delete this.__data__[key]; 230} 231 232/** 233 * Gets the hash value for `key`. 234 * 235 * @private 236 * @name get 237 * @memberOf Hash 238 * @param {string} key The key of the value to get. 239 * @returns {*} Returns the entry value. 240 */ 241function hashGet(key) { 242 var data = this.__data__; 243 if (nativeCreate) { 244 var result = data[key]; 245 return result === HASH_UNDEFINED ? undefined : result; 246 } 247 return hasOwnProperty.call(data, key) ? data[key] : undefined; 248} 249 250/** 251 * Checks if a hash value for `key` exists. 252 * 253 * @private 254 * @name has 255 * @memberOf Hash 256 * @param {string} key The key of the entry to check. 257 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 258 */ 259function hashHas(key) { 260 var data = this.__data__; 261 return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); 262} 263 264/** 265 * Sets the hash `key` to `value`. 266 * 267 * @private 268 * @name set 269 * @memberOf Hash 270 * @param {string} key The key of the value to set. 271 * @param {*} value The value to set. 272 * @returns {Object} Returns the hash instance. 273 */ 274function hashSet(key, value) { 275 var data = this.__data__; 276 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; 277 return this; 278} 279 280// Add methods to `Hash`. 281Hash.prototype.clear = hashClear; 282Hash.prototype['delete'] = hashDelete; 283Hash.prototype.get = hashGet; 284Hash.prototype.has = hashHas; 285Hash.prototype.set = hashSet; 286 287/** 288 * Creates an list cache object. 289 * 290 * @private 291 * @constructor 292 * @param {Array} [entries] The key-value pairs to cache. 293 */ 294function ListCache(entries) { 295 var index = -1, 296 length = entries ? entries.length : 0; 297 298 this.clear(); 299 while (++index < length) { 300 var entry = entries[index]; 301 this.set(entry[0], entry[1]); 302 } 303} 304 305/** 306 * Removes all key-value entries from the list cache. 307 * 308 * @private 309 * @name clear 310 * @memberOf ListCache 311 */ 312function listCacheClear() { 313 this.__data__ = []; 314} 315 316/** 317 * Removes `key` and its value from the list cache. 318 * 319 * @private 320 * @name delete 321 * @memberOf ListCache 322 * @param {string} key The key of the value to remove. 323 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 324 */ 325function listCacheDelete(key) { 326 var data = this.__data__, 327 index = assocIndexOf(data, key); 328 329 if (index < 0) { 330 return false; 331 } 332 var lastIndex = data.length - 1; 333 if (index == lastIndex) { 334 data.pop(); 335 } else { 336 splice.call(data, index, 1); 337 } 338 return true; 339} 340 341/** 342 * Gets the list cache value for `key`. 343 * 344 * @private 345 * @name get 346 * @memberOf ListCache 347 * @param {string} key The key of the value to get. 348 * @returns {*} Returns the entry value. 349 */ 350function listCacheGet(key) { 351 var data = this.__data__, 352 index = assocIndexOf(data, key); 353 354 return index < 0 ? undefined : data[index][1]; 355} 356 357/** 358 * Checks if a list cache value for `key` exists. 359 * 360 * @private 361 * @name has 362 * @memberOf ListCache 363 * @param {string} key The key of the entry to check. 364 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 365 */ 366function listCacheHas(key) { 367 return assocIndexOf(this.__data__, key) > -1; 368} 369 370/** 371 * Sets the list cache `key` to `value`. 372 * 373 * @private 374 * @name set 375 * @memberOf ListCache 376 * @param {string} key The key of the value to set. 377 * @param {*} value The value to set. 378 * @returns {Object} Returns the list cache instance. 379 */ 380function listCacheSet(key, value) { 381 var data = this.__data__, 382 index = assocIndexOf(data, key); 383 384 if (index < 0) { 385 data.push([key, value]); 386 } else { 387 data[index][1] = value; 388 } 389 return this; 390} 391 392// Add methods to `ListCache`. 393ListCache.prototype.clear = listCacheClear; 394ListCache.prototype['delete'] = listCacheDelete; 395ListCache.prototype.get = listCacheGet; 396ListCache.prototype.has = listCacheHas; 397ListCache.prototype.set = listCacheSet; 398 399/** 400 * Creates a map cache object to store key-value pairs. 401 * 402 * @private 403 * @constructor 404 * @param {Array} [entries] The key-value pairs to cache. 405 */ 406function MapCache(entries) { 407 var index = -1, 408 length = entries ? entries.length : 0; 409 410 this.clear(); 411 while (++index < length) { 412 var entry = entries[index]; 413 this.set(entry[0], entry[1]); 414 } 415} 416 417/** 418 * Removes all key-value entries from the map. 419 * 420 * @private 421 * @name clear 422 * @memberOf MapCache 423 */ 424function mapCacheClear() { 425 this.__data__ = { 426 'hash': new Hash, 427 'map': new (Map || ListCache), 428 'string': new Hash 429 }; 430} 431 432/** 433 * Removes `key` and its value from the map. 434 * 435 * @private 436 * @name delete 437 * @memberOf MapCache 438 * @param {string} key The key of the value to remove. 439 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 440 */ 441function mapCacheDelete(key) { 442 return getMapData(this, key)['delete'](key); 443} 444 445/** 446 * Gets the map value for `key`. 447 * 448 * @private 449 * @name get 450 * @memberOf MapCache 451 * @param {string} key The key of the value to get. 452 * @returns {*} Returns the entry value. 453 */ 454function mapCacheGet(key) { 455 return getMapData(this, key).get(key); 456} 457 458/** 459 * Checks if a map value for `key` exists. 460 * 461 * @private 462 * @name has 463 * @memberOf MapCache 464 * @param {string} key The key of the entry to check. 465 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 466 */ 467function mapCacheHas(key) { 468 return getMapData(this, key).has(key); 469} 470 471/** 472 * Sets the map `key` to `value`. 473 * 474 * @private 475 * @name set 476 * @memberOf MapCache 477 * @param {string} key The key of the value to set. 478 * @param {*} value The value to set. 479 * @returns {Object} Returns the map cache instance. 480 */ 481function mapCacheSet(key, value) { 482 getMapData(this, key).set(key, value); 483 return this; 484} 485 486// Add methods to `MapCache`. 487MapCache.prototype.clear = mapCacheClear; 488MapCache.prototype['delete'] = mapCacheDelete; 489MapCache.prototype.get = mapCacheGet; 490MapCache.prototype.has = mapCacheHas; 491MapCache.prototype.set = mapCacheSet; 492 493/** 494 * 495 * Creates an array cache object to store unique values. 496 * 497 * @private 498 * @constructor 499 * @param {Array} [values] The values to cache. 500 */ 501function SetCache(values) { 502 var index = -1, 503 length = values ? values.length : 0; 504 505 this.__data__ = new MapCache; 506 while (++index < length) { 507 this.add(values[index]); 508 } 509} 510 511/** 512 * Adds `value` to the array cache. 513 * 514 * @private 515 * @name add 516 * @memberOf SetCache 517 * @alias push 518 * @param {*} value The value to cache. 519 * @returns {Object} Returns the cache instance. 520 */ 521function setCacheAdd(value) { 522 this.__data__.set(value, HASH_UNDEFINED); 523 return this; 524} 525 526/** 527 * Checks if `value` is in the array cache. 528 * 529 * @private 530 * @name has 531 * @memberOf SetCache 532 * @param {*} value The value to search for. 533 * @returns {number} Returns `true` if `value` is found, else `false`. 534 */ 535function setCacheHas(value) { 536 return this.__data__.has(value); 537} 538 539// Add methods to `SetCache`. 540SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; 541SetCache.prototype.has = setCacheHas; 542 543/** 544 * Gets the index at which the `key` is found in `array` of key-value pairs. 545 * 546 * @private 547 * @param {Array} array The array to search. 548 * @param {*} key The key to search for. 549 * @returns {number} Returns the index of the matched value, else `-1`. 550 */ 551function assocIndexOf(array, key) { 552 var length = array.length; 553 while (length--) { 554 if (eq(array[length][0], key)) { 555 return length; 556 } 557 } 558 return -1; 559} 560 561/** 562 * The base implementation of `_.uniqBy` without support for iteratee shorthands. 563 * 564 * @private 565 * @param {Array} array The array to inspect. 566 * @param {Function} [iteratee] The iteratee invoked per element. 567 * @param {Function} [comparator] The comparator invoked per element. 568 * @returns {Array} Returns the new duplicate free array. 569 */ 570function baseUniq(array, iteratee, comparator) { 571 var index = -1, 572 includes = arrayIncludes, 573 length = array.length, 574 isCommon = true, 575 result = [], 576 seen = result; 577 578 if (comparator) { 579 isCommon = false; 580 includes = arrayIncludesWith; 581 } 582 else if (length >= LARGE_ARRAY_SIZE) { 583 var set = iteratee ? null : createSet(array); 584 if (set) { 585 return setToArray(set); 586 } 587 isCommon = false; 588 includes = cacheHas; 589 seen = new SetCache; 590 } 591 else { 592 seen = iteratee ? [] : result; 593 } 594 outer: 595 while (++index < length) { 596 var value = array[index], 597 computed = iteratee ? iteratee(value) : value; 598 599 value = (comparator || value !== 0) ? value : 0; 600 if (isCommon && computed === computed) { 601 var seenIndex = seen.length; 602 while (seenIndex--) { 603 if (seen[seenIndex] === computed) { 604 continue outer; 605 } 606 } 607 if (iteratee) { 608 seen.push(computed); 609 } 610 result.push(value); 611 } 612 else if (!includes(seen, computed, comparator)) { 613 if (seen !== result) { 614 seen.push(computed); 615 } 616 result.push(value); 617 } 618 } 619 return result; 620} 621 622/** 623 * Gets the data for `map`. 624 * 625 * @private 626 * @param {Object} map The map to query. 627 * @param {string} key The reference key. 628 * @returns {*} Returns the map data. 629 */ 630function getMapData(map, key) { 631 var data = map.__data__; 632 return isKeyable(key) 633 ? data[typeof key == 'string' ? 'string' : 'hash'] 634 : data.map; 635} 636 637/** 638 * Gets the native function at `key` of `object`. 639 * 640 * @private 641 * @param {Object} object The object to query. 642 * @param {string} key The key of the method to get. 643 * @returns {*} Returns the function if it's native, else `undefined`. 644 */ 645function getNative(object, key) { 646 var value = object[key]; 647 return isNative(value) ? value : undefined; 648} 649 650/** 651 * Checks if `value` is suitable for use as unique object key. 652 * 653 * @private 654 * @param {*} value The value to check. 655 * @returns {boolean} Returns `true` if `value` is suitable, else `false`. 656 */ 657function isKeyable(value) { 658 var type = typeof value; 659 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') 660 ? (value !== '__proto__') 661 : (value === null); 662} 663 664/** 665 * Converts `func` to its source code. 666 * 667 * @private 668 * @param {Function} func The function to process. 669 * @returns {string} Returns the source code. 670 */ 671function toSource(func) { 672 if (func != null) { 673 try { 674 return funcToString.call(func); 675 } catch (e) {} 676 try { 677 return (func + ''); 678 } catch (e) {} 679 } 680 return ''; 681} 682 683/** 684 * Performs a 685 * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) 686 * comparison between two values to determine if they are equivalent. 687 * 688 * @static 689 * @memberOf _ 690 * @since 4.0.0 691 * @category Lang 692 * @param {*} value The value to compare. 693 * @param {*} other The other value to compare. 694 * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 695 * @example 696 * 697 * var object = { 'user': 'fred' }; 698 * var other = { 'user': 'fred' }; 699 * 700 * _.eq(object, object); 701 * // => true 702 * 703 * _.eq(object, other); 704 * // => false 705 * 706 * _.eq('a', 'a'); 707 * // => true 708 * 709 * _.eq('a', Object('a')); 710 * // => false 711 * 712 * _.eq(NaN, NaN); 713 * // => true 714 */ 715function eq(value, other) { 716 return value === other || (value !== value && other !== other); 717} 718 719/** 720 * Checks if `value` is classified as a `Function` object. 721 * 722 * @static 723 * @memberOf _ 724 * @since 0.1.0 725 * @category Lang 726 * @param {*} value The value to check. 727 * @returns {boolean} Returns `true` if `value` is correctly classified, 728 * else `false`. 729 * @example 730 * 731 * _.isFunction(_); 732 * // => true 733 * 734 * _.isFunction(/abc/); 735 * // => false 736 */ 737function isFunction(value) { 738 // The use of `Object#toString` avoids issues with the `typeof` operator 739 // in Safari 8 which returns 'object' for typed array and weak map constructors, 740 // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. 741 var tag = isObject(value) ? objectToString.call(value) : ''; 742 return tag == funcTag || tag == genTag; 743} 744 745/** 746 * Checks if `value` is the 747 * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) 748 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) 749 * 750 * @static 751 * @memberOf _ 752 * @since 0.1.0 753 * @category Lang 754 * @param {*} value The value to check. 755 * @returns {boolean} Returns `true` if `value` is an object, else `false`. 756 * @example 757 * 758 * _.isObject({}); 759 * // => true 760 * 761 * _.isObject([1, 2, 3]); 762 * // => true 763 * 764 * _.isObject(_.noop); 765 * // => true 766 * 767 * _.isObject(null); 768 * // => false 769 */ 770function isObject(value) { 771 var type = typeof value; 772 return !!value && (type == 'object' || type == 'function'); 773} 774 775/** 776 * Checks if `value` is a native function. 777 * 778 * @static 779 * @memberOf _ 780 * @since 3.0.0 781 * @category Lang 782 * @param {*} value The value to check. 783 * @returns {boolean} Returns `true` if `value` is a native function, 784 * else `false`. 785 * @example 786 * 787 * _.isNative(Array.prototype.push); 788 * // => true 789 * 790 * _.isNative(_); 791 * // => false 792 */ 793function isNative(value) { 794 if (!isObject(value)) { 795 return false; 796 } 797 var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; 798 return pattern.test(toSource(value)); 799} 800 801module.exports = baseUniq; 802