├── .npmignore
├── .gitignore
├── test
└── test.js
├── .github
└── workflows
│ └── ci.yml
├── README.md
├── package.json
└── lodash.custom.js
/.npmignore:
--------------------------------------------------------------------------------
1 | test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | const test = require("ava");
2 | const lodash = require("../")
3 |
4 | test("get", t => {
5 | t.is(lodash.get({ mine: 1 }, "mine"), 1);
6 | });
7 |
8 | test("set", t => {
9 | let obj = { mine: 1 };
10 | lodash.set(obj, "mine", 2)
11 | t.is(obj.mine, 2);
12 | });
13 |
14 | test("chunk", t => {
15 | // taken from the docs https://lodash.com/docs/4.17.15#chunk
16 | t.deepEqual(lodash.chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']]);
17 | });
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches-ignore:
4 | - "gh-pages"
5 | jobs:
6 | build:
7 | runs-on: ${{ matrix.os }}
8 | strategy:
9 | matrix:
10 | os: ["ubuntu-latest", "macos-latest", "windows-latest"]
11 | node: ["14", "16", "18"]
12 | name: Node.js ${{ matrix.node }} on ${{ matrix.os }}
13 | steps:
14 | - uses: actions/checkout@v3
15 | - name: Setup node
16 | uses: actions/setup-node@v3
17 | with:
18 | node-version: ${{ matrix.node }}
19 | # cache: npm
20 | - run: npm install
21 | - run: npm test
22 | env:
23 | YARN_GPG: no
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # @11ty/lodash-custom
2 |
3 | Eleventy uses 3 small `lodash` functions:
4 |
5 | * [`get`](https://lodash.com/docs/4#get)
6 | * [`set`](https://lodash.com/docs/4#set)
7 | * [`chunk`](https://lodash.com/docs/4#chunk)
8 |
9 | ## Why?
10 |
11 | 1. The top level `lodash` package includes all of `lodash` and is a hefty 5 MB.
12 | 1. Using the individual, modularized `lodash.get`, `lodash.set`, `lodash.chunk` packages are a much smaller 106 KB but do contain duplicated code. More problematically, these are not being maintained/updated with the newest versions of `lodash`.
13 |
14 | This package creates one focused custom dependency using the tools that `lodash` provides to do custom builds ([`lodash-cli`](https://lodash.com/custom-builds)) for these three `lodash` functions with updated versions of `lodash`.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@11ty/lodash-custom",
3 | "version": "4.17.21",
4 | "description": "A custom, focused build of lodash exclusively for use internally in Eleventy.",
5 | "main": "lodash.custom.js",
6 | "scripts": {
7 | "build": "npx lodash exports=node include=get,set,chunk && rm lodash.custom.min.js",
8 | "test": "npx ava"
9 | },
10 | "publishConfig": {
11 | "access": "public"
12 | },
13 | "license": "MIT",
14 | "engines": {
15 | "node": ">=14"
16 | },
17 | "funding": {
18 | "type": "opencollective",
19 | "url": "https://opencollective.com/11ty"
20 | },
21 | "author": {
22 | "name": "Zach Leatherman",
23 | "email": "zachleatherman@gmail.com",
24 | "url": "https://zachleat.com/"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "git://github.com/11ty/lodash-custom.git"
29 | },
30 | "bugs": "https://github.com/11ty/lodash-custom/issues",
31 | "homepage": "https://github.com/11ty/lodash-custom/",
32 | "devDependencies": {
33 | "ava": "^5.2.0",
34 | "lodash-cli": "^4.17.5"
35 | },
36 | "overrides": {
37 | "lodash": "4.17.21"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lodash.custom.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Lodash (Custom Build)
4 | * Build: `lodash exports="node" include="get,set,chunk"`
5 | * Copyright OpenJS Foundation and other contributors
6 | * Released under MIT license
7 | * Based on Underscore.js 1.8.3
8 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
9 | */
10 | ;(function() {
11 |
12 | /** Used as a safe reference for `undefined` in pre-ES5 environments. */
13 | var undefined;
14 |
15 | /** Used as the semantic version number. */
16 | var VERSION = '4.17.21';
17 |
18 | /** Error message constants. */
19 | var FUNC_ERROR_TEXT = 'Expected a function';
20 |
21 | /** Used to stand-in for `undefined` hash values. */
22 | var HASH_UNDEFINED = '__lodash_hash_undefined__';
23 |
24 | /** Used as the maximum memoize cache size. */
25 | var MAX_MEMOIZE_SIZE = 500;
26 |
27 | /** Used as references for various `Number` constants. */
28 | var INFINITY = 1 / 0,
29 | MAX_SAFE_INTEGER = 9007199254740991,
30 | MAX_INTEGER = 1.7976931348623157e+308,
31 | NAN = 0 / 0;
32 |
33 | /** `Object#toString` result references. */
34 | var asyncTag = '[object AsyncFunction]',
35 | funcTag = '[object Function]',
36 | genTag = '[object GeneratorFunction]',
37 | nullTag = '[object Null]',
38 | proxyTag = '[object Proxy]',
39 | symbolTag = '[object Symbol]',
40 | undefinedTag = '[object Undefined]';
41 |
42 | /** Used to match property names within property paths. */
43 | var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
44 | reIsPlainProp = /^\w*$/,
45 | rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
46 |
47 | /**
48 | * Used to match `RegExp`
49 | * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
50 | */
51 | var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
52 |
53 | /** Used to match leading whitespace. */
54 | var reTrimStart = /^\s+/;
55 |
56 | /** Used to match a single whitespace character. */
57 | var reWhitespace = /\s/;
58 |
59 | /** Used to match backslashes in property paths. */
60 | var reEscapeChar = /\\(\\)?/g;
61 |
62 | /** Used to detect bad signed hexadecimal string values. */
63 | var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
64 |
65 | /** Used to detect binary string values. */
66 | var reIsBinary = /^0b[01]+$/i;
67 |
68 | /** Used to detect host constructors (Safari). */
69 | var reIsHostCtor = /^\[object .+?Constructor\]$/;
70 |
71 | /** Used to detect octal string values. */
72 | var reIsOctal = /^0o[0-7]+$/i;
73 |
74 | /** Used to detect unsigned integer values. */
75 | var reIsUint = /^(?:0|[1-9]\d*)$/;
76 |
77 | /** Built-in method references without a dependency on `root`. */
78 | var freeParseInt = parseInt;
79 |
80 | /** Detect free variable `global` from Node.js. */
81 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
82 |
83 | /** Detect free variable `self`. */
84 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
85 |
86 | /** Used as a reference to the global object. */
87 | var root = freeGlobal || freeSelf || Function('return this')();
88 |
89 | /** Detect free variable `exports`. */
90 | var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
91 |
92 | /** Detect free variable `module`. */
93 | var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
94 |
95 | /*--------------------------------------------------------------------------*/
96 |
97 | /**
98 | * A specialized version of `_.map` for arrays without support for iteratee
99 | * shorthands.
100 | *
101 | * @private
102 | * @param {Array} [array] The array to iterate over.
103 | * @param {Function} iteratee The function invoked per iteration.
104 | * @returns {Array} Returns the new mapped array.
105 | */
106 | function arrayMap(array, iteratee) {
107 | var index = -1,
108 | length = array == null ? 0 : array.length,
109 | result = Array(length);
110 |
111 | while (++index < length) {
112 | result[index] = iteratee(array[index], index, array);
113 | }
114 | return result;
115 | }
116 |
117 | /**
118 | * The base implementation of `_.trim`.
119 | *
120 | * @private
121 | * @param {string} string The string to trim.
122 | * @returns {string} Returns the trimmed string.
123 | */
124 | function baseTrim(string) {
125 | return string
126 | ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
127 | : string;
128 | }
129 |
130 | /**
131 | * Gets the value at `key` of `object`.
132 | *
133 | * @private
134 | * @param {Object} [object] The object to query.
135 | * @param {string} key The key of the property to get.
136 | * @returns {*} Returns the property value.
137 | */
138 | function getValue(object, key) {
139 | return object == null ? undefined : object[key];
140 | }
141 |
142 | /**
143 | * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
144 | * character of `string`.
145 | *
146 | * @private
147 | * @param {string} string The string to inspect.
148 | * @returns {number} Returns the index of the last non-whitespace character.
149 | */
150 | function trimmedEndIndex(string) {
151 | var index = string.length;
152 |
153 | while (index-- && reWhitespace.test(string.charAt(index))) {}
154 | return index;
155 | }
156 |
157 | /*--------------------------------------------------------------------------*/
158 |
159 | /** Used for built-in method references. */
160 | var arrayProto = Array.prototype,
161 | funcProto = Function.prototype,
162 | objectProto = Object.prototype;
163 |
164 | /** Used to detect overreaching core-js shims. */
165 | var coreJsData = root['__core-js_shared__'];
166 |
167 | /** Used to resolve the decompiled source of functions. */
168 | var funcToString = funcProto.toString;
169 |
170 | /** Used to check objects for own properties. */
171 | var hasOwnProperty = objectProto.hasOwnProperty;
172 |
173 | /** Used to detect methods masquerading as native. */
174 | var maskSrcKey = (function() {
175 | var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
176 | return uid ? ('Symbol(src)_1.' + uid) : '';
177 | }());
178 |
179 | /**
180 | * Used to resolve the
181 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
182 | * of values.
183 | */
184 | var nativeObjectToString = objectProto.toString;
185 |
186 | /** Used to detect if a method is native. */
187 | var reIsNative = RegExp('^' +
188 | funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
189 | .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
190 | );
191 |
192 | /** Built-in value references. */
193 | var Symbol = root.Symbol,
194 | splice = arrayProto.splice,
195 | symToStringTag = Symbol ? Symbol.toStringTag : undefined;
196 |
197 | var defineProperty = (function() {
198 | try {
199 | var func = getNative(Object, 'defineProperty');
200 | func({}, '', {});
201 | return func;
202 | } catch (e) {}
203 | }());
204 |
205 | /* Built-in method references for those with the same name as other `lodash` methods. */
206 | var nativeCeil = Math.ceil,
207 | nativeMax = Math.max;
208 |
209 | /* Built-in method references that are verified to be native. */
210 | var Map = getNative(root, 'Map'),
211 | nativeCreate = getNative(Object, 'create');
212 |
213 | /** Used to lookup unminified function names. */
214 | var realNames = {};
215 |
216 | /** Used to convert symbols to primitives and strings. */
217 | var symbolProto = Symbol ? Symbol.prototype : undefined,
218 | symbolToString = symbolProto ? symbolProto.toString : undefined;
219 |
220 | /*------------------------------------------------------------------------*/
221 |
222 | /**
223 | * Creates a `lodash` object which wraps `value` to enable implicit method
224 | * chain sequences. Methods that operate on and return arrays, collections,
225 | * and functions can be chained together. Methods that retrieve a single value
226 | * or may return a primitive value will automatically end the chain sequence
227 | * and return the unwrapped value. Otherwise, the value must be unwrapped
228 | * with `_#value`.
229 | *
230 | * Explicit chain sequences, which must be unwrapped with `_#value`, may be
231 | * enabled using `_.chain`.
232 | *
233 | * The execution of chained methods is lazy, that is, it's deferred until
234 | * `_#value` is implicitly or explicitly called.
235 | *
236 | * Lazy evaluation allows several methods to support shortcut fusion.
237 | * Shortcut fusion is an optimization to merge iteratee calls; this avoids
238 | * the creation of intermediate arrays and can greatly reduce the number of
239 | * iteratee executions. Sections of a chain sequence qualify for shortcut
240 | * fusion if the section is applied to an array and iteratees accept only
241 | * one argument. The heuristic for whether a section qualifies for shortcut
242 | * fusion is subject to change.
243 | *
244 | * Chaining is supported in custom builds as long as the `_#value` method is
245 | * directly or indirectly included in the build.
246 | *
247 | * In addition to lodash methods, wrappers have `Array` and `String` methods.
248 | *
249 | * The wrapper `Array` methods are:
250 | * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
251 | *
252 | * The wrapper `String` methods are:
253 | * `replace` and `split`
254 | *
255 | * The wrapper methods that support shortcut fusion are:
256 | * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
257 | * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
258 | * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
259 | *
260 | * The chainable wrapper methods are:
261 | * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
262 | * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
263 | * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
264 | * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
265 | * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
266 | * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
267 | * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
268 | * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
269 | * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
270 | * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
271 | * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
272 | * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
273 | * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
274 | * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
275 | * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
276 | * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
277 | * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
278 | * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
279 | * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
280 | * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
281 | * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
282 | * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
283 | * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
284 | * `zipObject`, `zipObjectDeep`, and `zipWith`
285 | *
286 | * The wrapper methods that are **not** chainable by default are:
287 | * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
288 | * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
289 | * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
290 | * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
291 | * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
292 | * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
293 | * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
294 | * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
295 | * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
296 | * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
297 | * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
298 | * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
299 | * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
300 | * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
301 | * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
302 | * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
303 | * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
304 | * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
305 | * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
306 | * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
307 | * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
308 | * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
309 | * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
310 | * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
311 | * `upperFirst`, `value`, and `words`
312 | *
313 | * @name _
314 | * @constructor
315 | * @category Seq
316 | * @param {*} value The value to wrap in a `lodash` instance.
317 | * @returns {Object} Returns the new `lodash` wrapper instance.
318 | * @example
319 | *
320 | * function square(n) {
321 | * return n * n;
322 | * }
323 | *
324 | * var wrapped = _([1, 2, 3]);
325 | *
326 | * // Returns an unwrapped value.
327 | * wrapped.reduce(_.add);
328 | * // => 6
329 | *
330 | * // Returns a wrapped value.
331 | * var squares = wrapped.map(square);
332 | *
333 | * _.isArray(squares);
334 | * // => false
335 | *
336 | * _.isArray(squares.value());
337 | * // => true
338 | */
339 | function lodash() {
340 | // No operation performed.
341 | }
342 |
343 | /*------------------------------------------------------------------------*/
344 |
345 | /**
346 | * Creates a hash object.
347 | *
348 | * @private
349 | * @constructor
350 | * @param {Array} [entries] The key-value pairs to cache.
351 | */
352 | function Hash(entries) {
353 | var index = -1,
354 | length = entries == null ? 0 : entries.length;
355 |
356 | this.clear();
357 | while (++index < length) {
358 | var entry = entries[index];
359 | this.set(entry[0], entry[1]);
360 | }
361 | }
362 |
363 | /**
364 | * Removes all key-value entries from the hash.
365 | *
366 | * @private
367 | * @name clear
368 | * @memberOf Hash
369 | */
370 | function hashClear() {
371 | this.__data__ = nativeCreate ? nativeCreate(null) : {};
372 | this.size = 0;
373 | }
374 |
375 | /**
376 | * Removes `key` and its value from the hash.
377 | *
378 | * @private
379 | * @name delete
380 | * @memberOf Hash
381 | * @param {Object} hash The hash to modify.
382 | * @param {string} key The key of the value to remove.
383 | * @returns {boolean} Returns `true` if the entry was removed, else `false`.
384 | */
385 | function hashDelete(key) {
386 | var result = this.has(key) && delete this.__data__[key];
387 | this.size -= result ? 1 : 0;
388 | return result;
389 | }
390 |
391 | /**
392 | * Gets the hash value for `key`.
393 | *
394 | * @private
395 | * @name get
396 | * @memberOf Hash
397 | * @param {string} key The key of the value to get.
398 | * @returns {*} Returns the entry value.
399 | */
400 | function hashGet(key) {
401 | var data = this.__data__;
402 | if (nativeCreate) {
403 | var result = data[key];
404 | return result === HASH_UNDEFINED ? undefined : result;
405 | }
406 | return hasOwnProperty.call(data, key) ? data[key] : undefined;
407 | }
408 |
409 | /**
410 | * Checks if a hash value for `key` exists.
411 | *
412 | * @private
413 | * @name has
414 | * @memberOf Hash
415 | * @param {string} key The key of the entry to check.
416 | * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
417 | */
418 | function hashHas(key) {
419 | var data = this.__data__;
420 | return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
421 | }
422 |
423 | /**
424 | * Sets the hash `key` to `value`.
425 | *
426 | * @private
427 | * @name set
428 | * @memberOf Hash
429 | * @param {string} key The key of the value to set.
430 | * @param {*} value The value to set.
431 | * @returns {Object} Returns the hash instance.
432 | */
433 | function hashSet(key, value) {
434 | var data = this.__data__;
435 | this.size += this.has(key) ? 0 : 1;
436 | data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
437 | return this;
438 | }
439 |
440 | // Add methods to `Hash`.
441 | Hash.prototype.clear = hashClear;
442 | Hash.prototype['delete'] = hashDelete;
443 | Hash.prototype.get = hashGet;
444 | Hash.prototype.has = hashHas;
445 | Hash.prototype.set = hashSet;
446 |
447 | /*------------------------------------------------------------------------*/
448 |
449 | /**
450 | * Creates an list cache object.
451 | *
452 | * @private
453 | * @constructor
454 | * @param {Array} [entries] The key-value pairs to cache.
455 | */
456 | function ListCache(entries) {
457 | var index = -1,
458 | length = entries == null ? 0 : entries.length;
459 |
460 | this.clear();
461 | while (++index < length) {
462 | var entry = entries[index];
463 | this.set(entry[0], entry[1]);
464 | }
465 | }
466 |
467 | /**
468 | * Removes all key-value entries from the list cache.
469 | *
470 | * @private
471 | * @name clear
472 | * @memberOf ListCache
473 | */
474 | function listCacheClear() {
475 | this.__data__ = [];
476 | this.size = 0;
477 | }
478 |
479 | /**
480 | * Removes `key` and its value from the list cache.
481 | *
482 | * @private
483 | * @name delete
484 | * @memberOf ListCache
485 | * @param {string} key The key of the value to remove.
486 | * @returns {boolean} Returns `true` if the entry was removed, else `false`.
487 | */
488 | function listCacheDelete(key) {
489 | var data = this.__data__,
490 | index = assocIndexOf(data, key);
491 |
492 | if (index < 0) {
493 | return false;
494 | }
495 | var lastIndex = data.length - 1;
496 | if (index == lastIndex) {
497 | data.pop();
498 | } else {
499 | splice.call(data, index, 1);
500 | }
501 | --this.size;
502 | return true;
503 | }
504 |
505 | /**
506 | * Gets the list cache value for `key`.
507 | *
508 | * @private
509 | * @name get
510 | * @memberOf ListCache
511 | * @param {string} key The key of the value to get.
512 | * @returns {*} Returns the entry value.
513 | */
514 | function listCacheGet(key) {
515 | var data = this.__data__,
516 | index = assocIndexOf(data, key);
517 |
518 | return index < 0 ? undefined : data[index][1];
519 | }
520 |
521 | /**
522 | * Checks if a list cache value for `key` exists.
523 | *
524 | * @private
525 | * @name has
526 | * @memberOf ListCache
527 | * @param {string} key The key of the entry to check.
528 | * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
529 | */
530 | function listCacheHas(key) {
531 | return assocIndexOf(this.__data__, key) > -1;
532 | }
533 |
534 | /**
535 | * Sets the list cache `key` to `value`.
536 | *
537 | * @private
538 | * @name set
539 | * @memberOf ListCache
540 | * @param {string} key The key of the value to set.
541 | * @param {*} value The value to set.
542 | * @returns {Object} Returns the list cache instance.
543 | */
544 | function listCacheSet(key, value) {
545 | var data = this.__data__,
546 | index = assocIndexOf(data, key);
547 |
548 | if (index < 0) {
549 | ++this.size;
550 | data.push([key, value]);
551 | } else {
552 | data[index][1] = value;
553 | }
554 | return this;
555 | }
556 |
557 | // Add methods to `ListCache`.
558 | ListCache.prototype.clear = listCacheClear;
559 | ListCache.prototype['delete'] = listCacheDelete;
560 | ListCache.prototype.get = listCacheGet;
561 | ListCache.prototype.has = listCacheHas;
562 | ListCache.prototype.set = listCacheSet;
563 |
564 | /*------------------------------------------------------------------------*/
565 |
566 | /**
567 | * Creates a map cache object to store key-value pairs.
568 | *
569 | * @private
570 | * @constructor
571 | * @param {Array} [entries] The key-value pairs to cache.
572 | */
573 | function MapCache(entries) {
574 | var index = -1,
575 | length = entries == null ? 0 : entries.length;
576 |
577 | this.clear();
578 | while (++index < length) {
579 | var entry = entries[index];
580 | this.set(entry[0], entry[1]);
581 | }
582 | }
583 |
584 | /**
585 | * Removes all key-value entries from the map.
586 | *
587 | * @private
588 | * @name clear
589 | * @memberOf MapCache
590 | */
591 | function mapCacheClear() {
592 | this.size = 0;
593 | this.__data__ = {
594 | 'hash': new Hash,
595 | 'map': new (Map || ListCache),
596 | 'string': new Hash
597 | };
598 | }
599 |
600 | /**
601 | * Removes `key` and its value from the map.
602 | *
603 | * @private
604 | * @name delete
605 | * @memberOf MapCache
606 | * @param {string} key The key of the value to remove.
607 | * @returns {boolean} Returns `true` if the entry was removed, else `false`.
608 | */
609 | function mapCacheDelete(key) {
610 | var result = getMapData(this, key)['delete'](key);
611 | this.size -= result ? 1 : 0;
612 | return result;
613 | }
614 |
615 | /**
616 | * Gets the map value for `key`.
617 | *
618 | * @private
619 | * @name get
620 | * @memberOf MapCache
621 | * @param {string} key The key of the value to get.
622 | * @returns {*} Returns the entry value.
623 | */
624 | function mapCacheGet(key) {
625 | return getMapData(this, key).get(key);
626 | }
627 |
628 | /**
629 | * Checks if a map value for `key` exists.
630 | *
631 | * @private
632 | * @name has
633 | * @memberOf MapCache
634 | * @param {string} key The key of the entry to check.
635 | * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
636 | */
637 | function mapCacheHas(key) {
638 | return getMapData(this, key).has(key);
639 | }
640 |
641 | /**
642 | * Sets the map `key` to `value`.
643 | *
644 | * @private
645 | * @name set
646 | * @memberOf MapCache
647 | * @param {string} key The key of the value to set.
648 | * @param {*} value The value to set.
649 | * @returns {Object} Returns the map cache instance.
650 | */
651 | function mapCacheSet(key, value) {
652 | var data = getMapData(this, key),
653 | size = data.size;
654 |
655 | data.set(key, value);
656 | this.size += data.size == size ? 0 : 1;
657 | return this;
658 | }
659 |
660 | // Add methods to `MapCache`.
661 | MapCache.prototype.clear = mapCacheClear;
662 | MapCache.prototype['delete'] = mapCacheDelete;
663 | MapCache.prototype.get = mapCacheGet;
664 | MapCache.prototype.has = mapCacheHas;
665 | MapCache.prototype.set = mapCacheSet;
666 |
667 | /*------------------------------------------------------------------------*/
668 |
669 | /**
670 | * Assigns `value` to `key` of `object` if the existing value is not equivalent
671 | * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
672 | * for equality comparisons.
673 | *
674 | * @private
675 | * @param {Object} object The object to modify.
676 | * @param {string} key The key of the property to assign.
677 | * @param {*} value The value to assign.
678 | */
679 | function assignValue(object, key, value) {
680 | var objValue = object[key];
681 | if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
682 | (value === undefined && !(key in object))) {
683 | baseAssignValue(object, key, value);
684 | }
685 | }
686 |
687 | /**
688 | * Gets the index at which the `key` is found in `array` of key-value pairs.
689 | *
690 | * @private
691 | * @param {Array} array The array to inspect.
692 | * @param {*} key The key to search for.
693 | * @returns {number} Returns the index of the matched value, else `-1`.
694 | */
695 | function assocIndexOf(array, key) {
696 | var length = array.length;
697 | while (length--) {
698 | if (eq(array[length][0], key)) {
699 | return length;
700 | }
701 | }
702 | return -1;
703 | }
704 |
705 | /**
706 | * The base implementation of `assignValue` and `assignMergeValue` without
707 | * value checks.
708 | *
709 | * @private
710 | * @param {Object} object The object to modify.
711 | * @param {string} key The key of the property to assign.
712 | * @param {*} value The value to assign.
713 | */
714 | function baseAssignValue(object, key, value) {
715 | if (key == '__proto__' && defineProperty) {
716 | defineProperty(object, key, {
717 | 'configurable': true,
718 | 'enumerable': true,
719 | 'value': value,
720 | 'writable': true
721 | });
722 | } else {
723 | object[key] = value;
724 | }
725 | }
726 |
727 | /**
728 | * The base implementation of `_.get` without support for default values.
729 | *
730 | * @private
731 | * @param {Object} object The object to query.
732 | * @param {Array|string} path The path of the property to get.
733 | * @returns {*} Returns the resolved value.
734 | */
735 | function baseGet(object, path) {
736 | path = castPath(path, object);
737 |
738 | var index = 0,
739 | length = path.length;
740 |
741 | while (object != null && index < length) {
742 | object = object[toKey(path[index++])];
743 | }
744 | return (index && index == length) ? object : undefined;
745 | }
746 |
747 | /**
748 | * The base implementation of `getTag` without fallbacks for buggy environments.
749 | *
750 | * @private
751 | * @param {*} value The value to query.
752 | * @returns {string} Returns the `toStringTag`.
753 | */
754 | function baseGetTag(value) {
755 | if (value == null) {
756 | return value === undefined ? undefinedTag : nullTag;
757 | }
758 | return (symToStringTag && symToStringTag in Object(value))
759 | ? getRawTag(value)
760 | : objectToString(value);
761 | }
762 |
763 | /**
764 | * The base implementation of `_.isNative` without bad shim checks.
765 | *
766 | * @private
767 | * @param {*} value The value to check.
768 | * @returns {boolean} Returns `true` if `value` is a native function,
769 | * else `false`.
770 | */
771 | function baseIsNative(value) {
772 | if (!isObject(value) || isMasked(value)) {
773 | return false;
774 | }
775 | var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
776 | return pattern.test(toSource(value));
777 | }
778 |
779 | /**
780 | * The base implementation of `_.set`.
781 | *
782 | * @private
783 | * @param {Object} object The object to modify.
784 | * @param {Array|string} path The path of the property to set.
785 | * @param {*} value The value to set.
786 | * @param {Function} [customizer] The function to customize path creation.
787 | * @returns {Object} Returns `object`.
788 | */
789 | function baseSet(object, path, value, customizer) {
790 | if (!isObject(object)) {
791 | return object;
792 | }
793 | path = castPath(path, object);
794 |
795 | var index = -1,
796 | length = path.length,
797 | lastIndex = length - 1,
798 | nested = object;
799 |
800 | while (nested != null && ++index < length) {
801 | var key = toKey(path[index]),
802 | newValue = value;
803 |
804 | if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
805 | return object;
806 | }
807 |
808 | if (index != lastIndex) {
809 | var objValue = nested[key];
810 | newValue = customizer ? customizer(objValue, key, nested) : undefined;
811 | if (newValue === undefined) {
812 | newValue = isObject(objValue)
813 | ? objValue
814 | : (isIndex(path[index + 1]) ? [] : {});
815 | }
816 | }
817 | assignValue(nested, key, newValue);
818 | nested = nested[key];
819 | }
820 | return object;
821 | }
822 |
823 | /**
824 | * The base implementation of `_.slice` without an iteratee call guard.
825 | *
826 | * @private
827 | * @param {Array} array The array to slice.
828 | * @param {number} [start=0] The start position.
829 | * @param {number} [end=array.length] The end position.
830 | * @returns {Array} Returns the slice of `array`.
831 | */
832 | function baseSlice(array, start, end) {
833 | var index = -1,
834 | length = array.length;
835 |
836 | if (start < 0) {
837 | start = -start > length ? 0 : (length + start);
838 | }
839 | end = end > length ? length : end;
840 | if (end < 0) {
841 | end += length;
842 | }
843 | length = start > end ? 0 : ((end - start) >>> 0);
844 | start >>>= 0;
845 |
846 | var result = Array(length);
847 | while (++index < length) {
848 | result[index] = array[index + start];
849 | }
850 | return result;
851 | }
852 |
853 | /**
854 | * The base implementation of `_.toString` which doesn't convert nullish
855 | * values to empty strings.
856 | *
857 | * @private
858 | * @param {*} value The value to process.
859 | * @returns {string} Returns the string.
860 | */
861 | function baseToString(value) {
862 | // Exit early for strings to avoid a performance hit in some environments.
863 | if (typeof value == 'string') {
864 | return value;
865 | }
866 | if (isArray(value)) {
867 | // Recursively convert values (susceptible to call stack limits).
868 | return arrayMap(value, baseToString) + '';
869 | }
870 | if (isSymbol(value)) {
871 | return symbolToString ? symbolToString.call(value) : '';
872 | }
873 | var result = (value + '');
874 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
875 | }
876 |
877 | /**
878 | * Casts `value` to a path array if it's not one.
879 | *
880 | * @private
881 | * @param {*} value The value to inspect.
882 | * @param {Object} [object] The object to query keys on.
883 | * @returns {Array} Returns the cast property path array.
884 | */
885 | function castPath(value, object) {
886 | if (isArray(value)) {
887 | return value;
888 | }
889 | return isKey(value, object) ? [value] : stringToPath(toString(value));
890 | }
891 |
892 | /**
893 | * Gets the data for `map`.
894 | *
895 | * @private
896 | * @param {Object} map The map to query.
897 | * @param {string} key The reference key.
898 | * @returns {*} Returns the map data.
899 | */
900 | function getMapData(map, key) {
901 | var data = map.__data__;
902 | return isKeyable(key)
903 | ? data[typeof key == 'string' ? 'string' : 'hash']
904 | : data.map;
905 | }
906 |
907 | /**
908 | * Gets the native function at `key` of `object`.
909 | *
910 | * @private
911 | * @param {Object} object The object to query.
912 | * @param {string} key The key of the method to get.
913 | * @returns {*} Returns the function if it's native, else `undefined`.
914 | */
915 | function getNative(object, key) {
916 | var value = getValue(object, key);
917 | return baseIsNative(value) ? value : undefined;
918 | }
919 |
920 | /**
921 | * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
922 | *
923 | * @private
924 | * @param {*} value The value to query.
925 | * @returns {string} Returns the raw `toStringTag`.
926 | */
927 | function getRawTag(value) {
928 | var isOwn = hasOwnProperty.call(value, symToStringTag),
929 | tag = value[symToStringTag];
930 |
931 | try {
932 | value[symToStringTag] = undefined;
933 | var unmasked = true;
934 | } catch (e) {}
935 |
936 | var result = nativeObjectToString.call(value);
937 | if (unmasked) {
938 | if (isOwn) {
939 | value[symToStringTag] = tag;
940 | } else {
941 | delete value[symToStringTag];
942 | }
943 | }
944 | return result;
945 | }
946 |
947 | /**
948 | * Checks if `value` is a valid array-like index.
949 | *
950 | * @private
951 | * @param {*} value The value to check.
952 | * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
953 | * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
954 | */
955 | function isIndex(value, length) {
956 | var type = typeof value;
957 | length = length == null ? MAX_SAFE_INTEGER : length;
958 |
959 | return !!length &&
960 | (type == 'number' ||
961 | (type != 'symbol' && reIsUint.test(value))) &&
962 | (value > -1 && value % 1 == 0 && value < length);
963 | }
964 |
965 | /**
966 | * Checks if the given arguments are from an iteratee call.
967 | *
968 | * @private
969 | * @param {*} value The potential iteratee value argument.
970 | * @param {*} index The potential iteratee index or key argument.
971 | * @param {*} object The potential iteratee object argument.
972 | * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
973 | * else `false`.
974 | */
975 | function isIterateeCall(value, index, object) {
976 | if (!isObject(object)) {
977 | return false;
978 | }
979 | var type = typeof index;
980 | if (type == 'number'
981 | ? (isArrayLike(object) && isIndex(index, object.length))
982 | : (type == 'string' && index in object)
983 | ) {
984 | return eq(object[index], value);
985 | }
986 | return false;
987 | }
988 |
989 | /**
990 | * Checks if `value` is a property name and not a property path.
991 | *
992 | * @private
993 | * @param {*} value The value to check.
994 | * @param {Object} [object] The object to query keys on.
995 | * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
996 | */
997 | function isKey(value, object) {
998 | if (isArray(value)) {
999 | return false;
1000 | }
1001 | var type = typeof value;
1002 | if (type == 'number' || type == 'symbol' || type == 'boolean' ||
1003 | value == null || isSymbol(value)) {
1004 | return true;
1005 | }
1006 | return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
1007 | (object != null && value in Object(object));
1008 | }
1009 |
1010 | /**
1011 | * Checks if `value` is suitable for use as unique object key.
1012 | *
1013 | * @private
1014 | * @param {*} value The value to check.
1015 | * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
1016 | */
1017 | function isKeyable(value) {
1018 | var type = typeof value;
1019 | return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
1020 | ? (value !== '__proto__')
1021 | : (value === null);
1022 | }
1023 |
1024 | /**
1025 | * Checks if `func` has its source masked.
1026 | *
1027 | * @private
1028 | * @param {Function} func The function to check.
1029 | * @returns {boolean} Returns `true` if `func` is masked, else `false`.
1030 | */
1031 | function isMasked(func) {
1032 | return !!maskSrcKey && (maskSrcKey in func);
1033 | }
1034 |
1035 | /**
1036 | * A specialized version of `_.memoize` which clears the memoized function's
1037 | * cache when it exceeds `MAX_MEMOIZE_SIZE`.
1038 | *
1039 | * @private
1040 | * @param {Function} func The function to have its output memoized.
1041 | * @returns {Function} Returns the new memoized function.
1042 | */
1043 | function memoizeCapped(func) {
1044 | var result = memoize(func, function(key) {
1045 | if (cache.size === MAX_MEMOIZE_SIZE) {
1046 | cache.clear();
1047 | }
1048 | return key;
1049 | });
1050 |
1051 | var cache = result.cache;
1052 | return result;
1053 | }
1054 |
1055 | /**
1056 | * Converts `value` to a string using `Object.prototype.toString`.
1057 | *
1058 | * @private
1059 | * @param {*} value The value to convert.
1060 | * @returns {string} Returns the converted string.
1061 | */
1062 | function objectToString(value) {
1063 | return nativeObjectToString.call(value);
1064 | }
1065 |
1066 | /**
1067 | * Converts `string` to a property path array.
1068 | *
1069 | * @private
1070 | * @param {string} string The string to convert.
1071 | * @returns {Array} Returns the property path array.
1072 | */
1073 | var stringToPath = memoizeCapped(function(string) {
1074 | var result = [];
1075 | if (string.charCodeAt(0) === 46 /* . */) {
1076 | result.push('');
1077 | }
1078 | string.replace(rePropName, function(match, number, quote, subString) {
1079 | result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
1080 | });
1081 | return result;
1082 | });
1083 |
1084 | /**
1085 | * Converts `value` to a string key if it's not a string or symbol.
1086 | *
1087 | * @private
1088 | * @param {*} value The value to inspect.
1089 | * @returns {string|symbol} Returns the key.
1090 | */
1091 | function toKey(value) {
1092 | if (typeof value == 'string' || isSymbol(value)) {
1093 | return value;
1094 | }
1095 | var result = (value + '');
1096 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
1097 | }
1098 |
1099 | /**
1100 | * Converts `func` to its source code.
1101 | *
1102 | * @private
1103 | * @param {Function} func The function to convert.
1104 | * @returns {string} Returns the source code.
1105 | */
1106 | function toSource(func) {
1107 | if (func != null) {
1108 | try {
1109 | return funcToString.call(func);
1110 | } catch (e) {}
1111 | try {
1112 | return (func + '');
1113 | } catch (e) {}
1114 | }
1115 | return '';
1116 | }
1117 |
1118 | /*------------------------------------------------------------------------*/
1119 |
1120 | /**
1121 | * Creates an array of elements split into groups the length of `size`.
1122 | * If `array` can't be split evenly, the final chunk will be the remaining
1123 | * elements.
1124 | *
1125 | * @static
1126 | * @memberOf _
1127 | * @since 3.0.0
1128 | * @category Array
1129 | * @param {Array} array The array to process.
1130 | * @param {number} [size=1] The length of each chunk
1131 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
1132 | * @returns {Array} Returns the new array of chunks.
1133 | * @example
1134 | *
1135 | * _.chunk(['a', 'b', 'c', 'd'], 2);
1136 | * // => [['a', 'b'], ['c', 'd']]
1137 | *
1138 | * _.chunk(['a', 'b', 'c', 'd'], 3);
1139 | * // => [['a', 'b', 'c'], ['d']]
1140 | */
1141 | function chunk(array, size, guard) {
1142 | if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
1143 | size = 1;
1144 | } else {
1145 | size = nativeMax(toInteger(size), 0);
1146 | }
1147 | var length = array == null ? 0 : array.length;
1148 | if (!length || size < 1) {
1149 | return [];
1150 | }
1151 | var index = 0,
1152 | resIndex = 0,
1153 | result = Array(nativeCeil(length / size));
1154 |
1155 | while (index < length) {
1156 | result[resIndex++] = baseSlice(array, index, (index += size));
1157 | }
1158 | return result;
1159 | }
1160 |
1161 | /*------------------------------------------------------------------------*/
1162 |
1163 | /**
1164 | * Creates a function that memoizes the result of `func`. If `resolver` is
1165 | * provided, it determines the cache key for storing the result based on the
1166 | * arguments provided to the memoized function. By default, the first argument
1167 | * provided to the memoized function is used as the map cache key. The `func`
1168 | * is invoked with the `this` binding of the memoized function.
1169 | *
1170 | * **Note:** The cache is exposed as the `cache` property on the memoized
1171 | * function. Its creation may be customized by replacing the `_.memoize.Cache`
1172 | * constructor with one whose instances implement the
1173 | * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
1174 | * method interface of `clear`, `delete`, `get`, `has`, and `set`.
1175 | *
1176 | * @static
1177 | * @memberOf _
1178 | * @since 0.1.0
1179 | * @category Function
1180 | * @param {Function} func The function to have its output memoized.
1181 | * @param {Function} [resolver] The function to resolve the cache key.
1182 | * @returns {Function} Returns the new memoized function.
1183 | * @example
1184 | *
1185 | * var object = { 'a': 1, 'b': 2 };
1186 | * var other = { 'c': 3, 'd': 4 };
1187 | *
1188 | * var values = _.memoize(_.values);
1189 | * values(object);
1190 | * // => [1, 2]
1191 | *
1192 | * values(other);
1193 | * // => [3, 4]
1194 | *
1195 | * object.a = 2;
1196 | * values(object);
1197 | * // => [1, 2]
1198 | *
1199 | * // Modify the result cache.
1200 | * values.cache.set(object, ['a', 'b']);
1201 | * values(object);
1202 | * // => ['a', 'b']
1203 | *
1204 | * // Replace `_.memoize.Cache`.
1205 | * _.memoize.Cache = WeakMap;
1206 | */
1207 | function memoize(func, resolver) {
1208 | if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
1209 | throw new TypeError(FUNC_ERROR_TEXT);
1210 | }
1211 | var memoized = function() {
1212 | var args = arguments,
1213 | key = resolver ? resolver.apply(this, args) : args[0],
1214 | cache = memoized.cache;
1215 |
1216 | if (cache.has(key)) {
1217 | return cache.get(key);
1218 | }
1219 | var result = func.apply(this, args);
1220 | memoized.cache = cache.set(key, result) || cache;
1221 | return result;
1222 | };
1223 | memoized.cache = new (memoize.Cache || MapCache);
1224 | return memoized;
1225 | }
1226 |
1227 | // Expose `MapCache`.
1228 | memoize.Cache = MapCache;
1229 |
1230 | /*------------------------------------------------------------------------*/
1231 |
1232 | /**
1233 | * Performs a
1234 | * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
1235 | * comparison between two values to determine if they are equivalent.
1236 | *
1237 | * @static
1238 | * @memberOf _
1239 | * @since 4.0.0
1240 | * @category Lang
1241 | * @param {*} value The value to compare.
1242 | * @param {*} other The other value to compare.
1243 | * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1244 | * @example
1245 | *
1246 | * var object = { 'a': 1 };
1247 | * var other = { 'a': 1 };
1248 | *
1249 | * _.eq(object, object);
1250 | * // => true
1251 | *
1252 | * _.eq(object, other);
1253 | * // => false
1254 | *
1255 | * _.eq('a', 'a');
1256 | * // => true
1257 | *
1258 | * _.eq('a', Object('a'));
1259 | * // => false
1260 | *
1261 | * _.eq(NaN, NaN);
1262 | * // => true
1263 | */
1264 | function eq(value, other) {
1265 | return value === other || (value !== value && other !== other);
1266 | }
1267 |
1268 | /**
1269 | * Checks if `value` is classified as an `Array` object.
1270 | *
1271 | * @static
1272 | * @memberOf _
1273 | * @since 0.1.0
1274 | * @category Lang
1275 | * @param {*} value The value to check.
1276 | * @returns {boolean} Returns `true` if `value` is an array, else `false`.
1277 | * @example
1278 | *
1279 | * _.isArray([1, 2, 3]);
1280 | * // => true
1281 | *
1282 | * _.isArray(document.body.children);
1283 | * // => false
1284 | *
1285 | * _.isArray('abc');
1286 | * // => false
1287 | *
1288 | * _.isArray(_.noop);
1289 | * // => false
1290 | */
1291 | var isArray = Array.isArray;
1292 |
1293 | /**
1294 | * Checks if `value` is array-like. A value is considered array-like if it's
1295 | * not a function and has a `value.length` that's an integer greater than or
1296 | * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
1297 | *
1298 | * @static
1299 | * @memberOf _
1300 | * @since 4.0.0
1301 | * @category Lang
1302 | * @param {*} value The value to check.
1303 | * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
1304 | * @example
1305 | *
1306 | * _.isArrayLike([1, 2, 3]);
1307 | * // => true
1308 | *
1309 | * _.isArrayLike(document.body.children);
1310 | * // => true
1311 | *
1312 | * _.isArrayLike('abc');
1313 | * // => true
1314 | *
1315 | * _.isArrayLike(_.noop);
1316 | * // => false
1317 | */
1318 | function isArrayLike(value) {
1319 | return value != null && isLength(value.length) && !isFunction(value);
1320 | }
1321 |
1322 | /**
1323 | * Checks if `value` is classified as a `Function` object.
1324 | *
1325 | * @static
1326 | * @memberOf _
1327 | * @since 0.1.0
1328 | * @category Lang
1329 | * @param {*} value The value to check.
1330 | * @returns {boolean} Returns `true` if `value` is a function, else `false`.
1331 | * @example
1332 | *
1333 | * _.isFunction(_);
1334 | * // => true
1335 | *
1336 | * _.isFunction(/abc/);
1337 | * // => false
1338 | */
1339 | function isFunction(value) {
1340 | if (!isObject(value)) {
1341 | return false;
1342 | }
1343 | // The use of `Object#toString` avoids issues with the `typeof` operator
1344 | // in Safari 9 which returns 'object' for typed arrays and other constructors.
1345 | var tag = baseGetTag(value);
1346 | return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
1347 | }
1348 |
1349 | /**
1350 | * Checks if `value` is a valid array-like length.
1351 | *
1352 | * **Note:** This method is loosely based on
1353 | * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
1354 | *
1355 | * @static
1356 | * @memberOf _
1357 | * @since 4.0.0
1358 | * @category Lang
1359 | * @param {*} value The value to check.
1360 | * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
1361 | * @example
1362 | *
1363 | * _.isLength(3);
1364 | * // => true
1365 | *
1366 | * _.isLength(Number.MIN_VALUE);
1367 | * // => false
1368 | *
1369 | * _.isLength(Infinity);
1370 | * // => false
1371 | *
1372 | * _.isLength('3');
1373 | * // => false
1374 | */
1375 | function isLength(value) {
1376 | return typeof value == 'number' &&
1377 | value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
1378 | }
1379 |
1380 | /**
1381 | * Checks if `value` is the
1382 | * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
1383 | * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1384 | *
1385 | * @static
1386 | * @memberOf _
1387 | * @since 0.1.0
1388 | * @category Lang
1389 | * @param {*} value The value to check.
1390 | * @returns {boolean} Returns `true` if `value` is an object, else `false`.
1391 | * @example
1392 | *
1393 | * _.isObject({});
1394 | * // => true
1395 | *
1396 | * _.isObject([1, 2, 3]);
1397 | * // => true
1398 | *
1399 | * _.isObject(_.noop);
1400 | * // => true
1401 | *
1402 | * _.isObject(null);
1403 | * // => false
1404 | */
1405 | function isObject(value) {
1406 | var type = typeof value;
1407 | return value != null && (type == 'object' || type == 'function');
1408 | }
1409 |
1410 | /**
1411 | * Checks if `value` is object-like. A value is object-like if it's not `null`
1412 | * and has a `typeof` result of "object".
1413 | *
1414 | * @static
1415 | * @memberOf _
1416 | * @since 4.0.0
1417 | * @category Lang
1418 | * @param {*} value The value to check.
1419 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
1420 | * @example
1421 | *
1422 | * _.isObjectLike({});
1423 | * // => true
1424 | *
1425 | * _.isObjectLike([1, 2, 3]);
1426 | * // => true
1427 | *
1428 | * _.isObjectLike(_.noop);
1429 | * // => false
1430 | *
1431 | * _.isObjectLike(null);
1432 | * // => false
1433 | */
1434 | function isObjectLike(value) {
1435 | return value != null && typeof value == 'object';
1436 | }
1437 |
1438 | /**
1439 | * Checks if `value` is classified as a `Symbol` primitive or object.
1440 | *
1441 | * @static
1442 | * @memberOf _
1443 | * @since 4.0.0
1444 | * @category Lang
1445 | * @param {*} value The value to check.
1446 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
1447 | * @example
1448 | *
1449 | * _.isSymbol(Symbol.iterator);
1450 | * // => true
1451 | *
1452 | * _.isSymbol('abc');
1453 | * // => false
1454 | */
1455 | function isSymbol(value) {
1456 | return typeof value == 'symbol' ||
1457 | (isObjectLike(value) && baseGetTag(value) == symbolTag);
1458 | }
1459 |
1460 | /**
1461 | * Converts `value` to a finite number.
1462 | *
1463 | * @static
1464 | * @memberOf _
1465 | * @since 4.12.0
1466 | * @category Lang
1467 | * @param {*} value The value to convert.
1468 | * @returns {number} Returns the converted number.
1469 | * @example
1470 | *
1471 | * _.toFinite(3.2);
1472 | * // => 3.2
1473 | *
1474 | * _.toFinite(Number.MIN_VALUE);
1475 | * // => 5e-324
1476 | *
1477 | * _.toFinite(Infinity);
1478 | * // => 1.7976931348623157e+308
1479 | *
1480 | * _.toFinite('3.2');
1481 | * // => 3.2
1482 | */
1483 | function toFinite(value) {
1484 | if (!value) {
1485 | return value === 0 ? value : 0;
1486 | }
1487 | value = toNumber(value);
1488 | if (value === INFINITY || value === -INFINITY) {
1489 | var sign = (value < 0 ? -1 : 1);
1490 | return sign * MAX_INTEGER;
1491 | }
1492 | return value === value ? value : 0;
1493 | }
1494 |
1495 | /**
1496 | * Converts `value` to an integer.
1497 | *
1498 | * **Note:** This method is loosely based on
1499 | * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
1500 | *
1501 | * @static
1502 | * @memberOf _
1503 | * @since 4.0.0
1504 | * @category Lang
1505 | * @param {*} value The value to convert.
1506 | * @returns {number} Returns the converted integer.
1507 | * @example
1508 | *
1509 | * _.toInteger(3.2);
1510 | * // => 3
1511 | *
1512 | * _.toInteger(Number.MIN_VALUE);
1513 | * // => 0
1514 | *
1515 | * _.toInteger(Infinity);
1516 | * // => 1.7976931348623157e+308
1517 | *
1518 | * _.toInteger('3.2');
1519 | * // => 3
1520 | */
1521 | function toInteger(value) {
1522 | var result = toFinite(value),
1523 | remainder = result % 1;
1524 |
1525 | return result === result ? (remainder ? result - remainder : result) : 0;
1526 | }
1527 |
1528 | /**
1529 | * Converts `value` to a number.
1530 | *
1531 | * @static
1532 | * @memberOf _
1533 | * @since 4.0.0
1534 | * @category Lang
1535 | * @param {*} value The value to process.
1536 | * @returns {number} Returns the number.
1537 | * @example
1538 | *
1539 | * _.toNumber(3.2);
1540 | * // => 3.2
1541 | *
1542 | * _.toNumber(Number.MIN_VALUE);
1543 | * // => 5e-324
1544 | *
1545 | * _.toNumber(Infinity);
1546 | * // => Infinity
1547 | *
1548 | * _.toNumber('3.2');
1549 | * // => 3.2
1550 | */
1551 | function toNumber(value) {
1552 | if (typeof value == 'number') {
1553 | return value;
1554 | }
1555 | if (isSymbol(value)) {
1556 | return NAN;
1557 | }
1558 | if (isObject(value)) {
1559 | var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
1560 | value = isObject(other) ? (other + '') : other;
1561 | }
1562 | if (typeof value != 'string') {
1563 | return value === 0 ? value : +value;
1564 | }
1565 | value = baseTrim(value);
1566 | var isBinary = reIsBinary.test(value);
1567 | return (isBinary || reIsOctal.test(value))
1568 | ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
1569 | : (reIsBadHex.test(value) ? NAN : +value);
1570 | }
1571 |
1572 | /**
1573 | * Converts `value` to a string. An empty string is returned for `null`
1574 | * and `undefined` values. The sign of `-0` is preserved.
1575 | *
1576 | * @static
1577 | * @memberOf _
1578 | * @since 4.0.0
1579 | * @category Lang
1580 | * @param {*} value The value to convert.
1581 | * @returns {string} Returns the converted string.
1582 | * @example
1583 | *
1584 | * _.toString(null);
1585 | * // => ''
1586 | *
1587 | * _.toString(-0);
1588 | * // => '-0'
1589 | *
1590 | * _.toString([1, 2, 3]);
1591 | * // => '1,2,3'
1592 | */
1593 | function toString(value) {
1594 | return value == null ? '' : baseToString(value);
1595 | }
1596 |
1597 | /*------------------------------------------------------------------------*/
1598 |
1599 | /**
1600 | * Gets the value at `path` of `object`. If the resolved value is
1601 | * `undefined`, the `defaultValue` is returned in its place.
1602 | *
1603 | * @static
1604 | * @memberOf _
1605 | * @since 3.7.0
1606 | * @category Object
1607 | * @param {Object} object The object to query.
1608 | * @param {Array|string} path The path of the property to get.
1609 | * @param {*} [defaultValue] The value returned for `undefined` resolved values.
1610 | * @returns {*} Returns the resolved value.
1611 | * @example
1612 | *
1613 | * var object = { 'a': [{ 'b': { 'c': 3 } }] };
1614 | *
1615 | * _.get(object, 'a[0].b.c');
1616 | * // => 3
1617 | *
1618 | * _.get(object, ['a', '0', 'b', 'c']);
1619 | * // => 3
1620 | *
1621 | * _.get(object, 'a.b.c', 'default');
1622 | * // => 'default'
1623 | */
1624 | function get(object, path, defaultValue) {
1625 | var result = object == null ? undefined : baseGet(object, path);
1626 | return result === undefined ? defaultValue : result;
1627 | }
1628 |
1629 | /**
1630 | * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
1631 | * it's created. Arrays are created for missing index properties while objects
1632 | * are created for all other missing properties. Use `_.setWith` to customize
1633 | * `path` creation.
1634 | *
1635 | * **Note:** This method mutates `object`.
1636 | *
1637 | * @static
1638 | * @memberOf _
1639 | * @since 3.7.0
1640 | * @category Object
1641 | * @param {Object} object The object to modify.
1642 | * @param {Array|string} path The path of the property to set.
1643 | * @param {*} value The value to set.
1644 | * @returns {Object} Returns `object`.
1645 | * @example
1646 | *
1647 | * var object = { 'a': [{ 'b': { 'c': 3 } }] };
1648 | *
1649 | * _.set(object, 'a[0].b.c', 4);
1650 | * console.log(object.a[0].b.c);
1651 | * // => 4
1652 | *
1653 | * _.set(object, ['x', '0', 'y', 'z'], 5);
1654 | * console.log(object.x[0].y.z);
1655 | * // => 5
1656 | */
1657 | function set(object, path, value) {
1658 | return object == null ? object : baseSet(object, path, value);
1659 | }
1660 |
1661 | /*------------------------------------------------------------------------*/
1662 |
1663 | // Add methods that return wrapped values in chain sequences.
1664 | lodash.chunk = chunk;
1665 | lodash.memoize = memoize;
1666 | lodash.set = set;
1667 |
1668 | /*------------------------------------------------------------------------*/
1669 |
1670 | // Add methods that return unwrapped values in chain sequences.
1671 | lodash.eq = eq;
1672 | lodash.get = get;
1673 | lodash.isArray = isArray;
1674 | lodash.isArrayLike = isArrayLike;
1675 | lodash.isFunction = isFunction;
1676 | lodash.isLength = isLength;
1677 | lodash.isObject = isObject;
1678 | lodash.isObjectLike = isObjectLike;
1679 | lodash.isSymbol = isSymbol;
1680 | lodash.toFinite = toFinite;
1681 | lodash.toInteger = toInteger;
1682 | lodash.toNumber = toNumber;
1683 | lodash.toString = toString;
1684 |
1685 | /*------------------------------------------------------------------------*/
1686 |
1687 | /**
1688 | * The semantic version number.
1689 | *
1690 | * @static
1691 | * @memberOf _
1692 | * @type {string}
1693 | */
1694 | lodash.VERSION = VERSION;
1695 |
1696 | /*--------------------------------------------------------------------------*/
1697 |
1698 | if (freeModule) {
1699 | // Export for Node.js.
1700 | (freeModule.exports = lodash)._ = lodash;
1701 | // Export for CommonJS support.
1702 | freeExports._ = lodash;
1703 | }
1704 | }.call(this));
1705 |
--------------------------------------------------------------------------------