fix(angular.equals): do not match keys defined in the prototype chain

Merely testing for object[key] will give incorrect results on keys
defined in Object.prototype.
Note: IE8 is generally broken in this regard since `for...in` never returns
certain property keys even if they are defined directly on the object.

See #2141 - partially merges this PR
This commit is contained in:
Daniel Luz 2013-07-08 11:00:59 +01:00 committed by Pete Bacon Darwin
parent d88dc4a64f
commit 7829c50f9e
2 changed files with 19 additions and 1 deletions

View file

@ -2,6 +2,16 @@
////////////////////////////////////
/**
* hasOwnProperty may be overriden by a property of the same name, or entirely
* absent from an object that does not inherit Object.prototype; this copy is
* used instead
*/
var hasOwnPropertyFn = Object.prototype.hasOwnProperty;
var hasOwnPropertyLocal = function(obj, key) {
return hasOwnPropertyFn.call(obj, key);
};
/**
* @ngdoc function
* @name angular.lowercase
@ -685,7 +695,7 @@ function equals(o1, o2) {
keySet[key] = true;
}
for(key in o2) {
if (!keySet[key] &&
if (!keySet.hasOwnProperty(key) &&
key.charAt(0) !== '$' &&
o2[key] !== undefined &&
!isFunction(o2[key])) return false;

View file

@ -270,6 +270,14 @@ describe('angular', function() {
expect(equals(new Date(0), 0)).toBe(false);
expect(equals(0, new Date(0))).toBe(false);
});
it('should correctly test for keys that are present on Object.prototype', function() {
// MS IE8 just doesn't work for this kind of thing, since "for ... in" doesn't return
// things like hasOwnProperty even if it is explicitly defined on the actual object!
if (msie<=8) return;
expect(equals({}, {hasOwnProperty: 1})).toBe(false);
expect(equals({}, {toString: null})).toBe(false);
});
});
describe('size', function() {