Permalink
Browse files

Handling iteration over inherited properties before own properties. F…

…ixes #12199
  • Loading branch information...
1 parent a13cada commit c606c6436c1e5ab5dbb02f50df8e4981b102881b @bjohn465 committed Mar 6, 2013
Showing with 57 additions and 15 deletions.
  1. +10 −2 src/core.js
  2. +17 −2 src/support.js
  3. +11 −1 test/unit/core.js
  4. +19 −10 test/unit/support.js
View
@@ -452,6 +452,8 @@ jQuery.extend({
},
isPlainObject: function( obj ) {
+ var key;
+
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
@@ -471,10 +473,16 @@ jQuery.extend({
return false;
}
+ // Support: IE<9
+ // Handle iteration over inherited properties before own properties.
+ if ( jQuery.support.iteratesOwnLast ) {
+ for( key in obj ) {
+ return core_hasOwn.call( obj, key );
+ }
+ }
+
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
-
- var key;
for ( key in obj ) {}
return key === undefined || core_hasOwn.call( obj, key );
View
@@ -1,6 +1,7 @@
jQuery.support = (function( support ) {
- var all, a, input, select, fragment, opt, eventName, isSupported, i,
+ var all, a, input, select, fragment, opt, eventName, isSupported, i, func,
+ props,
div = document.createElement("div");
// Setup
@@ -141,6 +142,20 @@ jQuery.support = (function( support ) {
div.cloneNode( true ).style.backgroundClip = "";
support.clearCloneStyle = div.style.backgroundClip === "content-box";
+ // Support: IE<9
+ // Iteration over object's inherited properties before its own.
+ func = function() {
+ this.a = 0;
+ };
+ func.prototype = {
+ b: 1
+ };
+ props = [];
+ for( i in new func() ) {
+ props.push( i );
+ }
+ support.iteratesOwnLast = props[0] !== "a";
+
// Run tests that need a body at doc ready
jQuery(function() {
var container, marginDiv, tds,
@@ -231,7 +246,7 @@ jQuery.support = (function( support ) {
});
// Null elements to avoid leaks in IE
- all = select = fragment = opt = a = input = null;
+ all = select = fragment = opt = a = input = func = props = null;
return support;
})({});
View
@@ -296,7 +296,7 @@ test("type", function() {
});
asyncTest("isPlainObject", function() {
- expect(15);
+ expect(16);
var pass, iframe, doc,
fn = function() {};
@@ -330,6 +330,16 @@ asyncTest("isPlainObject", function() {
// Again, instantiated objects shouldn't be matched
ok( !jQuery.isPlainObject(new fn()), "new fn" );
+ // Make it even harder to detect in IE < 9
+ fn = function() {
+ this.a = "a";
+ };
+ fn.prototype = {
+ b: "b"
+ };
+
+ ok( !jQuery.isPlainObject(new fn()), "fn (inherited and own properties)");
+
// DOM Element
ok( !jQuery.isPlainObject( document.createElement("div") ), "DOM Element" );
View
@@ -76,7 +76,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":true,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": false
};
} else if ( /opera.*version\/12\.1/i.test( userAgent ) ) {
expected = {
@@ -110,7 +111,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":true,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": false
};
} else if ( /msie 10\.0/i.test( userAgent ) ) {
expected = {
@@ -144,7 +146,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":true,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": false
+ "clearCloneStyle": false,
+ "iteratesOwnLast": false
};
} else if ( /msie 9\.0/i.test( userAgent ) ) {
expected = {
@@ -178,7 +181,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":false,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": false
+ "clearCloneStyle": false,
+ "iteratesOwnLast": false
};
} else if ( /msie 8\.0/i.test( userAgent ) ) {
expected = {
@@ -212,7 +216,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":false,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": true
};
} else if ( /msie 7\.0/i.test( userAgent ) ) {
expected = {
@@ -246,7 +251,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"submitBubbles": false,
"tbody": false,
"style": false,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": true
};
} else if ( /msie 6\.0/i.test( userAgent ) ) {
expected = {
@@ -280,7 +286,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":false,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": true
};
} else if ( /5\.1\.1 safari/i.test( userAgent ) ) {
expected = {
@@ -314,7 +321,8 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":true,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": false
};
} else if ( /firefox/i.test( userAgent ) ) {
expected = {
@@ -348,13 +356,14 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo
"ajax":true,
"cors":true,
"doesNotIncludeMarginInBodyOffset":true,
- "clearCloneStyle": true
+ "clearCloneStyle": true,
+ "iteratesOwnLast": false
};
}
if ( expected ) {
test("Verify that the support tests resolve as expected per browser", function() {
- expect( 31 );
+ expect( 32 );
for ( var i in expected ) {
if ( jQuery.ajax || i !== "ajax" && i !== "cors" ) {

0 comments on commit c606c64

Please sign in to comment.