Make iteration fix in _.keysIn less constructor specific.

This commit is contained in:
John-David Dalton
2014-11-01 01:24:10 -07:00
parent 4fb83fe0a5
commit ab70f306cd
2 changed files with 45 additions and 33 deletions

View File

@@ -8049,7 +8049,7 @@
}
if (support.nonEnumShadows && object !== objectProto) {
var className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object),
nonEnum = nonEnumProps[className] || nonEnumProps[objectClass];
nonEnums = nonEnumProps[className] || nonEnumProps[objectClass];
if (className == objectClass) {
proto = objectProto;
@@ -8057,8 +8057,9 @@
length = shadowedProps.length;
while (length--) {
key = shadowedProps[length];
if (!(isProto && nonEnum[key]) &&
(key == 'constructor' ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {
var nonEnum = nonEnums[key];
if (!(isProto && nonEnum) &&
(nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {
result.push(key);
}
}

View File

@@ -4535,36 +4535,6 @@
deepEqual(props.sort(), shadowedProps);
});
test('`_.' + methodName + '` does not iterate over non-enumerable properties (test in IE < 9)', 10, function() {
_.forOwn({
'Array': arrayProto,
'Boolean': Boolean.prototype,
'Date': Date.prototype,
'Error': errorProto,
'Function': funcProto,
'Object': objectProto,
'Number': Number.prototype,
'TypeError': TypeError.prototype,
'RegExp': RegExp.prototype,
'String': stringProto
},
function(proto, key) {
var message = 'non-enumerable properties on ' + key + '.prototype',
props = [];
func(proto, function(value, prop) { props.push(prop); });
if (/Error/.test(key)) {
ok(_.every(['constructor', 'toString'], function(prop) {
return !_.contains(props, prop);
}), message);
}
else {
deepEqual(props, [], message);
}
});
});
test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
function Foo() {}
Foo.prototype.a = 1;
@@ -7094,6 +7064,47 @@
deepEqual(func(new Foo).sort(), actual);
});
test('`_.' + methodName + '` skips non-enumerable properties (test in IE < 9)', 50, function() {
_.forOwn({
'Array': arrayProto,
'Boolean': Boolean.prototype,
'Date': Date.prototype,
'Error': errorProto,
'Function': funcProto,
'Object': objectProto,
'Number': Number.prototype,
'TypeError': TypeError.prototype,
'RegExp': RegExp.prototype,
'String': stringProto
},
function(proto, key) {
_.each([proto, _.create(proto)], function(object, index) {
var actual = func(proto),
isErr = /Error/.test(key),
message = 'enumerable properties ' + (index ? 'inherited from' : 'on') + ' `' + key + '.prototype`',
props = isErr ? ['constructor', 'toString'] : ['constructor'];
actual = isErr ? _.difference(props, actual) : actual;
strictEqual(_.isEmpty(actual), !isErr, 'skips non-' + message);
proto.a = 1;
actual = func(object);
delete proto.a;
strictEqual(_.contains(actual, 'a'), !(isKeys && index), 'includes ' + message);
if (index) {
object.constructor = 1;
if (isErr) {
object.toString = 2;
}
actual = func(object);
ok(_.isEmpty(_.difference(props, actual)), 'includes shadowed properties on objects that inherit from `' + key + '.prototype`');
}
});
});
});
test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
function Foo() {}
Foo.a = 1;