Ensure _.mixin does not extend lodash when an object is provided with an empty options object. [closes #650]

This commit is contained in:
John-David Dalton
2014-08-01 16:36:44 -07:00
parent 4dc41749fb
commit faf6584652
2 changed files with 22 additions and 13 deletions

View File

@@ -1917,17 +1917,16 @@
} }
/** /**
* The base implementation of `_.functions` which creates an array of function * The base implementation of `_.functions` which creates an array of
* property names from those returned by `keysFunc`. * `object` function property names filtered from those provided.
* *
* @private * @private
* @param {Object} object The object to inspect. * @param {Object} object The object to inspect.
* @param {Function} keysFunc The function to get the keys of `object`. * @param {Array} props The property names to filter.
* @returns {Array} Returns the new sorted array of property names. * @returns {Array} Returns the new array of filtered property names.
*/ */
function baseFunctions(object, keysFunc) { function baseFunctions(object, props) {
var index = -1, var index = -1,
props = keysFunc(object),
length = props.length, length = props.length,
resIndex = -1, resIndex = -1,
result = []; result = [];
@@ -6848,14 +6847,14 @@
* @alias methods * @alias methods
* @category Object * @category Object
* @param {Object} object The object to inspect. * @param {Object} object The object to inspect.
* @returns {Array} Returns the new sorted array of property names. * @returns {Array} Returns the new array of property names.
* @example * @example
* *
* _.functions(_); * _.functions(_);
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/ */
function functions(object) { function functions(object) {
return baseFunctions(object, keysIn); return baseFunctions(object, keysIn(object));
} }
/** /**
@@ -8784,16 +8783,20 @@
*/ */
function mixin(object, source, options) { function mixin(object, source, options) {
var chain = true, var chain = true,
methodNames = source && baseFunctions(source, keys); isObj = isObject(source),
noOpts = options == null,
props = noOpts && isObj && keys(source),
methodNames = props && baseFunctions(source, props);
if (!source || (!options && !methodNames.length)) { if (!source || (props && props.length && !methodNames.length) || (noOpts && !isObj)) {
if (options == null) { if (noOpts) {
options = source; options = source;
} }
methodNames = false;
source = object; source = object;
object = this; object = this;
methodNames = baseFunctions(source, keys);
} }
methodNames || (methodNames = baseFunctions(source, keys(source)));
if (options === false) { if (options === false) {
chain = false; chain = false;
} else if (isObject(options) && 'chain' in options) { } else if (isObject(options) && 'chain' in options) {
@@ -8801,7 +8804,7 @@
} }
var index = -1, var index = -1,
isFunc = isFunction(object), isFunc = isFunction(object),
length = methodNames ? methodNames.length : 0; length = methodNames.length;
while (++index < length) { while (++index < length) {
var methodName = methodNames[index], var methodName = methodNames[index],

View File

@@ -7554,6 +7554,12 @@
}); });
}); });
test('should not extend lodash when an `object` is provided with an empty `options` object', 1, function() {
_.mixin({ 'a': _.noop }, {});
ok(!('a' in _));
delete _.a;
});
test('should not error for non-object `options` values', 2, function() { test('should not error for non-object `options` values', 2, function() {
var pass = true; var pass = true;