|
3719 | 3719 | * @returns {Array} Returns the new sorted array. |
3720 | 3720 | */ |
3721 | 3721 | function baseOrderBy(collection, iteratees, orders) { |
| 3722 | + if (iteratees.length) { |
| 3723 | + iteratees = arrayMap(iteratees, function(iteratee) { |
| 3724 | + if (isArray(iteratee)) { |
| 3725 | + return function(value) { |
| 3726 | + return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); |
| 3727 | + } |
| 3728 | + } |
| 3729 | + return iteratee; |
| 3730 | + }); |
| 3731 | + } else { |
| 3732 | + iteratees = [identity]; |
| 3733 | + } |
| 3734 | + |
3722 | 3735 | var index = -1; |
3723 | | - iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); |
| 3736 | + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); |
3724 | 3737 |
|
3725 | 3738 | var result = baseMap(collection, function(value, key, collection) { |
3726 | 3739 | var criteria = arrayMap(iteratees, function(iteratee) { |
|
3977 | 3990 | var key = toKey(path[index]), |
3978 | 3991 | newValue = value; |
3979 | 3992 |
|
| 3993 | + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { |
| 3994 | + return object; |
| 3995 | + } |
| 3996 | + |
3980 | 3997 | if (index != lastIndex) { |
3981 | 3998 | var objValue = nested[key]; |
3982 | 3999 | newValue = customizer ? customizer(objValue, key, nested) : undefined; |
|
4129 | 4146 | * into `array`. |
4130 | 4147 | */ |
4131 | 4148 | function baseSortedIndexBy(array, value, iteratee, retHighest) { |
4132 | | - value = iteratee(value); |
4133 | | - |
4134 | 4149 | var low = 0, |
4135 | | - high = array == null ? 0 : array.length, |
4136 | | - valIsNaN = value !== value, |
| 4150 | + high = array == null ? 0 : array.length; |
| 4151 | + if (high === 0) { |
| 4152 | + return 0; |
| 4153 | + } |
| 4154 | + |
| 4155 | + value = iteratee(value); |
| 4156 | + var valIsNaN = value !== value, |
4137 | 4157 | valIsNull = value === null, |
4138 | 4158 | valIsSymbol = isSymbol(value), |
4139 | 4159 | valIsUndefined = value === undefined; |
|
5618 | 5638 | if (arrLength != othLength && !(isPartial && othLength > arrLength)) { |
5619 | 5639 | return false; |
5620 | 5640 | } |
5621 | | - // Assume cyclic values are equal. |
5622 | | - var stacked = stack.get(array); |
5623 | | - if (stacked && stack.get(other)) { |
5624 | | - return stacked == other; |
| 5641 | + // Check that cyclic values are equal. |
| 5642 | + var arrStacked = stack.get(array); |
| 5643 | + var othStacked = stack.get(other); |
| 5644 | + if (arrStacked && othStacked) { |
| 5645 | + return arrStacked == other && othStacked == array; |
5625 | 5646 | } |
5626 | 5647 | var index = -1, |
5627 | 5648 | result = true, |
|
5783 | 5804 | return false; |
5784 | 5805 | } |
5785 | 5806 | } |
5786 | | - // Assume cyclic values are equal. |
5787 | | - var stacked = stack.get(object); |
5788 | | - if (stacked && stack.get(other)) { |
5789 | | - return stacked == other; |
| 5807 | + // Check that cyclic values are equal. |
| 5808 | + var objStacked = stack.get(object); |
| 5809 | + var othStacked = stack.get(other); |
| 5810 | + if (objStacked && othStacked) { |
| 5811 | + return objStacked == other && othStacked == object; |
5790 | 5812 | } |
5791 | 5813 | var result = true; |
5792 | 5814 | stack.set(object, other); |
|
9167 | 9189 | * // The `_.property` iteratee shorthand. |
9168 | 9190 | * _.filter(users, 'active'); |
9169 | 9191 | * // => objects for ['barney'] |
| 9192 | + * |
| 9193 | + * // Combining several predicates using `_.overEvery` or `_.overSome`. |
| 9194 | + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); |
| 9195 | + * // => objects for ['fred', 'barney'] |
9170 | 9196 | */ |
9171 | 9197 | function filter(collection, predicate) { |
9172 | 9198 | var func = isArray(collection) ? arrayFilter : baseFilter; |
|
9916 | 9942 | * var users = [ |
9917 | 9943 | * { 'user': 'fred', 'age': 48 }, |
9918 | 9944 | * { 'user': 'barney', 'age': 36 }, |
9919 | | - * { 'user': 'fred', 'age': 40 }, |
| 9945 | + * { 'user': 'fred', 'age': 30 }, |
9920 | 9946 | * { 'user': 'barney', 'age': 34 } |
9921 | 9947 | * ]; |
9922 | 9948 | * |
9923 | 9949 | * _.sortBy(users, [function(o) { return o.user; }]); |
9924 | | - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] |
| 9950 | + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] |
9925 | 9951 | * |
9926 | 9952 | * _.sortBy(users, ['user', 'age']); |
9927 | | - * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] |
| 9953 | + * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] |
9928 | 9954 | */ |
9929 | 9955 | var sortBy = baseRest(function(collection, iteratees) { |
9930 | 9956 | if (collection == null) { |
@@ -14799,11 +14825,11 @@ |
14799 | 14825 |
|
14800 | 14826 | // Use a sourceURL for easier debugging. |
14801 | 14827 | // The sourceURL gets injected into the source that's eval-ed, so be careful |
14802 | | - // with lookup (in case of e.g. prototype pollution), and strip newlines if any. |
14803 | | - // A newline wouldn't be a valid sourceURL anyway, and it'd enable code injection. |
| 14828 | + // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in |
| 14829 | + // and escape the comment, thus injecting code that gets evaled. |
14804 | 14830 | var sourceURL = '//# sourceURL=' + |
14805 | 14831 | (hasOwnProperty.call(options, 'sourceURL') |
14806 | | - ? (options.sourceURL + '').replace(/[\r\n]/g, ' ') |
| 14832 | + ? (options.sourceURL + '').replace(/\s/g, ' ') |
14807 | 14833 | : ('lodash.templateSources[' + (++templateCounter) + ']') |
14808 | 14834 | ) + '\n'; |
14809 | 14835 |
|
|
14836 | 14862 |
|
14837 | 14863 | // If `variable` is not specified wrap a with-statement around the generated |
14838 | 14864 | // code to add the data object to the top of the scope chain. |
14839 | | - // Like with sourceURL, we take care to not check the option's prototype, |
14840 | | - // as this configuration is a code injection vector. |
14841 | 14865 | var variable = hasOwnProperty.call(options, 'variable') && options.variable; |
14842 | 14866 | if (!variable) { |
14843 | 14867 | source = 'with (obj) {\n' + source + '\n}\n'; |
|
15544 | 15568 | * values against any array or object value, respectively. See `_.isEqual` |
15545 | 15569 | * for a list of supported value comparisons. |
15546 | 15570 | * |
| 15571 | + * **Note:** Multiple values can be checked by combining several matchers |
| 15572 | + * using `_.overSome` |
| 15573 | + * |
15547 | 15574 | * @static |
15548 | 15575 | * @memberOf _ |
15549 | 15576 | * @since 3.0.0 |
|
15559 | 15586 | * |
15560 | 15587 | * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); |
15561 | 15588 | * // => [{ 'a': 4, 'b': 5, 'c': 6 }] |
| 15589 | + * |
| 15590 | + * // Checking for several possible values |
| 15591 | + * _.filter(users, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })])); |
| 15592 | + * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] |
15562 | 15593 | */ |
15563 | 15594 | function matches(source) { |
15564 | 15595 | return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); |
|
15573 | 15604 | * `srcValue` values against any array or object value, respectively. See |
15574 | 15605 | * `_.isEqual` for a list of supported value comparisons. |
15575 | 15606 | * |
| 15607 | + * **Note:** Multiple values can be checked by combining several matchers |
| 15608 | + * using `_.overSome` |
| 15609 | + * |
15576 | 15610 | * @static |
15577 | 15611 | * @memberOf _ |
15578 | 15612 | * @since 3.2.0 |
|
15589 | 15623 | * |
15590 | 15624 | * _.find(objects, _.matchesProperty('a', 4)); |
15591 | 15625 | * // => { 'a': 4, 'b': 5, 'c': 6 } |
| 15626 | + * |
| 15627 | + * // Checking for several possible values |
| 15628 | + * _.filter(users, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)])); |
| 15629 | + * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] |
15592 | 15630 | */ |
15593 | 15631 | function matchesProperty(path, srcValue) { |
15594 | 15632 | return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG)); |
|
15812 | 15850 | * Creates a function that checks if **all** of the `predicates` return |
15813 | 15851 | * truthy when invoked with the arguments it receives. |
15814 | 15852 | * |
| 15853 | + * Following shorthands are possible for providing predicates. |
| 15854 | + * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate. |
| 15855 | + * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them. |
| 15856 | + * |
15815 | 15857 | * @static |
15816 | 15858 | * @memberOf _ |
15817 | 15859 | * @since 4.0.0 |
|
15838 | 15880 | * Creates a function that checks if **any** of the `predicates` return |
15839 | 15881 | * truthy when invoked with the arguments it receives. |
15840 | 15882 | * |
| 15883 | + * Following shorthands are possible for providing predicates. |
| 15884 | + * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate. |
| 15885 | + * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them. |
| 15886 | + * |
15841 | 15887 | * @static |
15842 | 15888 | * @memberOf _ |
15843 | 15889 | * @since 4.0.0 |
|
15857 | 15903 | * |
15858 | 15904 | * func(NaN); |
15859 | 15905 | * // => false |
| 15906 | + * |
| 15907 | + * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }]) |
| 15908 | + * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]]) |
15860 | 15909 | */ |
15861 | 15910 | var overSome = createOver(arraySome); |
15862 | 15911 |
|
|
0 commit comments