Skip to content

Commit b247bab

Browse files
committed
Merge pull request #1755 from megawac/keys-fix
Keys shim misses non enumerable properties
2 parents cfb18ef + f916c5e commit b247bab

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

test/objects.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,24 @@
1313
deepEqual(_.keys(1), []);
1414
deepEqual(_.keys('a'), []);
1515
deepEqual(_.keys(true), []);
16+
17+
// keys that may be missed if the implementation isn't careful
18+
var trouble = {
19+
'constructor': Object,
20+
'valueOf': _.noop,
21+
'hasOwnProperty': null,
22+
'toString': 5,
23+
'toLocaleString': undefined,
24+
'propertyIsEnumerable': /a/,
25+
'isPrototypeOf': this,
26+
'__defineGetter__': Boolean,
27+
'__defineSetter__': {},
28+
'__lookupSetter__': false,
29+
'__lookupGetter__': []
30+
};
31+
var troubleKeys = ['constructor', 'valueOf', 'hasOwnProperty', 'toString', 'toLocaleString', 'propertyIsEnumerable',
32+
'isPrototypeOf', '__defineGetter__', '__defineSetter__', '__lookupSetter__', '__lookupGetter__'].sort();
33+
deepEqual(_.keys(trouble).sort(), troubleKeys, 'matches non-enumerable properties');
1634
});
1735

1836
test('values', function() {

underscore.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,13 +849,24 @@
849849
// Object Functions
850850
// ----------------
851851

852+
// keys that won't be iterated by `for key in ...` and thus missed
853+
var hasEnumBug = !({toString: null}).propertyIsEnumerable('toString');
854+
var nonEnumerableProps = ['constructor', 'valueOf', 'isPrototypeOf', 'toString',
855+
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
856+
852857
// Retrieve the names of an object's properties.
853858
// Delegates to **ECMAScript 5**'s native `Object.keys`
854859
_.keys = function(obj) {
855860
if (!_.isObject(obj)) return [];
856861
if (nativeKeys) return nativeKeys(obj);
857-
var keys = [];
862+
var keys = [], nonEnumIdx = 7;
858863
for (var key in obj) if (_.has(obj, key)) keys.push(key);
864+
if (hasEnumBug) {
865+
while (nonEnumIdx--) {
866+
var prop = nonEnumerableProps[nonEnumIdx];
867+
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
868+
}
869+
}
859870
return keys;
860871
};
861872

0 commit comments

Comments
 (0)