From de92cc32e6473c5eca9497338797826109dfa113 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 24 Aug 2016 17:03:54 -0700 Subject: [PATCH] Add `__proto__` guards to more methods. --- lodash.js | 63 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/lodash.js b/lodash.js index 669282178..8d8c6d1f7 100644 --- a/lodash.js +++ b/lodash.js @@ -2383,7 +2383,7 @@ function assignMergeValue(object, key, value) { if ((value !== undefined && !eq(object[key], value)) || (typeof key == 'number' && value === undefined && !(key in object))) { - object[key] = value; + baseAssignValue(object, key, value); } } @@ -2401,16 +2401,7 @@ var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { - if (key == '__proto__' && defineProperty) { - defineProperty(object, key, { - 'configurable': true, - 'enumerable': true, - 'value': value, - 'writable': true - }); - } else { - object[key] = value; - } + baseAssignValue(object, key, value); } } @@ -2463,6 +2454,28 @@ return object && copyObject(source, keys(source), object); } + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + /** * The base implementation of `_.at` without support for individual paths. * @@ -3650,7 +3663,7 @@ value = object[key]; if (predicate(value, key)) { - result[key] = value; + baseAssignValue(result, key, value); } } return result; @@ -4617,6 +4630,7 @@ * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { + var isNew = !object; object || (object = {}); var index = -1, @@ -4629,7 +4643,14 @@ ? customizer(object[key], source[key], key, object, source) : undefined; - assignValue(object, key, newValue === undefined ? source[key] : newValue); + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } } return object; } @@ -8749,7 +8770,11 @@ * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { - hasOwnProperty.call(result, key) ? ++result[key] : assignValue(result, key, 1); + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } }); /** @@ -9072,7 +9097,7 @@ if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { - assignValue(result, key, [value]); + baseAssignValue(result, key, [value]); } }); @@ -9185,7 +9210,7 @@ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { - assignValue(result, key, value); + baseAssignValue(result, key, value); }); /** @@ -13008,7 +13033,7 @@ 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; } @@ -13046,7 +13071,7 @@ 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; } @@ -14900,7 +14925,7 @@ var bindAll = baseRest(function(object, methodNames) { arrayEach(baseFlatten(methodNames, 1), function(key) { key = toKey(key); - object[key] = bind(object[key], object); + baseAssignValue(object, key, bind(object[key], object)); }); return object; });