From 0c2d1aee5421b650159116b6bdcb74a4fe96f9ad Mon Sep 17 00:00:00 2001 From: Rick Waldron Date: Sat, 30 Apr 2011 10:42:36 -0400 Subject: [PATCH 01/40] jQuery.buildFragment, ensure doc is a document; Includes comments; Adds unit test. Fixes #8950 --- src/manipulation.js | 21 +++++++++++++++++---- test/unit/manipulation.js | 11 ++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/manipulation.js b/src/manipulation.js index 610d19b7..aeea083a 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -437,8 +437,21 @@ function cloneFixAttributes( src, dest ) { } jQuery.buildFragment = function( args, nodes, scripts ) { - var fragment, cacheable, cacheresults, - doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); + var fragment, cacheable, cacheresults, doc; + + // nodes may contain either an explicit document object, + // a jQuery collection or context object. + // If nodes[0] contains a valid object to assign to doc + if ( nodes && nodes[0] ) { + doc = nodes[0].ownerDocument || nodes[0]; + } + + // Ensure that an attr object doesn't incorrectly stand in as a document object + // Chrome and Firefox seem to allow this to occur and will throw exception + // Fixes #8950 + if ( !doc.createDocumentFragment ) { + doc = document; + } // Only cache "small" (1/2 KB) HTML strings that are associated with the main document // Cloning options loses the selected state, so don't cache them @@ -500,7 +513,7 @@ jQuery.each({ function getAll( elem ) { if ( "getElementsByTagName" in elem ) { return elem.getElementsByTagName( "*" ); - + } else if ( "querySelectorAll" in elem ) { return elem.querySelectorAll( "*" ); @@ -746,4 +759,4 @@ function evalScript( i, elem ) { } } -})( jQuery ); +})( jQuery ); \ No newline at end of file diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index b71b6962..a2b5c2e5 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -1382,6 +1382,15 @@ test("jQuery.buildFragment - no plain-text caching (Bug #6779)", function() { } catch(e) {} } - equals($f.text(), bad.join(""), "Cached strings that match Object properties"); + equals($f.text(), bad.join(""), "Cached strings that match Object properties"); $f.remove(); }); + +test("jQuery.buildFragment - plain objects are not a document #8950", function() { + expect(1); + + try { + jQuery('', {}); + ok( true, "Does not allow attribute object to be treated like a doc object"); + } catch (e) {} +}); From 076c347605c752821dfb6457044df4ba87b601c1 Mon Sep 17 00:00:00 2001 From: louisremi Date: Mon, 9 May 2011 17:35:51 +0200 Subject: [PATCH 02/40] .animate() Callbacks should fire in correct order (fix #9100 + unit test) --- src/effects.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/effects.js b/src/effects.js index 832ef5da..95600508 100644 --- a/src/effects.js +++ b/src/effects.js @@ -253,7 +253,6 @@ jQuery.fn.extend({ if ( !gotoEnd ) { jQuery._unmark( true, this ); } - // go in reverse order so anything added to the queue during the loop is ignored while ( i-- ) { if ( timers[i].elem === this ) { if (gotoEnd) { @@ -517,11 +516,9 @@ jQuery.fx.prototype = { jQuery.extend( jQuery.fx, { tick: function() { - var timers = jQuery.timers, - i = timers.length; - while ( i-- ) { + for ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) { if ( !timers[i]() ) { - timers.splice(i, 1); + timers.splice(i--, 1); } } From f34a90b3f7a5d54beb267ce08295cb1e64c3a2af Mon Sep 17 00:00:00 2001 From: louisremi Date: Mon, 9 May 2011 17:46:00 +0200 Subject: [PATCH 03/40] oops unit test --- test/unit/effects.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/unit/effects.js b/test/unit/effects.js index d0518217..f015fc91 100644 --- a/test/unit/effects.js +++ b/test/unit/effects.js @@ -993,3 +993,20 @@ test("animate unit-less properties (#4966)", 2, function() { start(); }); }); + +test("callbacks should fire in correct order (#9100)", function() { + stop(); + var a = 1, + cb = 0, + $lis = jQuery("

").appendTo("#qunit-fixture") + // The test will always pass if no properties are animated or if the duration is 0 + .animate({fontSize: 12}, 13, function() { + console.log(jQuery(this).data("operation")) + a *= jQuery(this).data("operation") === "*2" ? 2 : a; + cb++; + if ( cb === 2 ) { + equal( a, 4, "test value has been *2 and _then_ ^2"); + start(); + } + }); +}); \ No newline at end of file From 4526c8b0a05ea16397a0640875bfbb54645a9482 Mon Sep 17 00:00:00 2001 From: timmywil Date: Tue, 10 May 2011 00:27:52 -0400 Subject: [PATCH 04/40] Add fallback to prop for the window and document. Switch value to use the property instead of the attribute for back compat. --- src/attributes.js | 47 ++++++++++++++++++++++++++++++----------- test/unit/attributes.js | 36 +++++++++++++++++-------------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/attributes.js b/src/attributes.js index c207a001..bc26d735 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -301,10 +301,15 @@ jQuery.extend({ if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } - + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - + // Normalize the name if needed name = notxml && jQuery.attrFix[ name ] || name; @@ -381,7 +386,7 @@ jQuery.extend({ // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to it's default in case type is set after value // This is for element creation - var val = elem.getAttribute("value"); + var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; @@ -404,7 +409,7 @@ jQuery.extend({ } } }, - + propFix: { tabindex: "tabIndex", readonly: "readOnly", @@ -422,32 +427,32 @@ jQuery.extend({ prop: function( elem, name, value ) { var nType = elem.nodeType; - + // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } - + var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - + // Try to normalize/fix the name name = notxml && jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; - + if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; - + } else { return (elem[ name ] = value); } - + } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { return ret; - + } else { return elem[ name ]; } @@ -485,6 +490,24 @@ boolHook = { } }; +// Use the value property for back compat +// Use the formHook for button elements in IE6/7 (#1954) +jQuery.attrHooks.value = { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return elem.value; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } +}; + // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { @@ -492,7 +515,7 @@ if ( !jQuery.support.getSetAttribute ) { jQuery.attrFix = jQuery.propFix; // Use this for any attribute on a form in IE6/7 - formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = { + formHook = jQuery.attrHooks.name = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); diff --git a/test/unit/attributes.js b/test/unit/attributes.js index ce7775d1..d2d43475 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -117,9 +117,9 @@ if ( !isLocal ) { test("attr(String) in XML Files", function() { expect(2); stop(); - jQuery.get("data/dashboard.xml", function(xml) { - equals( jQuery("locations", xml).attr("class"), "foo", "Check class attribute in XML document" ); - equals( jQuery("location", xml).attr("for"), "bar", "Check for attribute in XML document" ); + jQuery.get("data/dashboard.xml", function( xml ) { + equals( jQuery( "locations", xml ).attr("class"), "foo", "Check class attribute in XML document" ); + equals( jQuery( "location", xml ).attr("for"), "bar", "Check for attribute in XML document" ); start(); }); }); @@ -144,7 +144,7 @@ test("attr(Hash)", function() { }); test("attr(String, Object)", function() { - expect(59); + expect(66); var div = jQuery("div").attr("foo", "bar"), fail = false; @@ -206,9 +206,6 @@ test("attr(String, Object)", function() { equals( document.getElementById("name").maxLength, 5, "Set maxlength attribute" ); jQuery("#name").attr("maxLength", "10"); equals( document.getElementById("name").maxLength, 10, "Set maxlength attribute" ); - var $p = jQuery("#firstp").attr("nonexisting", "foo"); - equals( $p.attr("nonexisting"), "foo", "attr(name, value) works correctly for non existing attributes (bug #7500)."); - $p.removeAttr("nonexisting"); var $text = jQuery("#text1").attr("autofocus", true); if ( "autofocus" in $text[0] ) { @@ -227,12 +224,19 @@ test("attr(String, Object)", function() { var attributeNode = document.createAttribute("irrelevant"), commentNode = document.createComment("some comment"), - textNode = document.createTextNode("some text"); + textNode = document.createTextNode("some text"), + obj = {}; - jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) { - var $ele = jQuery( ele ); - $ele.attr( "nonexisting", "foo" ); - strictEqual( $ele.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." ); + jQuery.each( [commentNode, textNode, attributeNode], function( i, elem ) { + var $elem = jQuery( elem ); + $elem.attr( "nonexisting", "foo" ); + strictEqual( $elem.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." ); + }); + + jQuery.each( [window, document, obj, "#firstp"], function( i, elem ) { + var $elem = jQuery( elem ); + strictEqual( $elem.attr("nonexisting"), undefined, "attr works correctly for non existing attributes (bug #7500)." ); + equal( $elem.attr("something", "foo" ).attr("something"), "foo", "attr falls back to prop on unsupported arguments" ); }); var table = jQuery("#table").append("cellcellcellcellcell"), @@ -244,7 +248,7 @@ test("attr(String, Object)", function() { table.attr("cellspacing", "2"); equals( table[0].cellSpacing, "2", "Check cellspacing is correctly set" ); - equals( jQuery("#area1").attr("value"), undefined, "Value attribute retrieved correctly on textarea." ); + equals( jQuery("#area1").attr("value"), "foobar", "Value attribute retrieves the property for backwards compatibility." ); // for #1070 jQuery("#name").attr("someAttr", "0"); @@ -350,10 +354,10 @@ if ( !isLocal ) { test("attr(String, Object) - Loaded via XML document", function() { expect(2); stop(); - jQuery.get("data/dashboard.xml", function(xml) { + jQuery.get("data/dashboard.xml", function( xml ) { var titles = []; - jQuery("tab", xml).each(function() { - titles.push(jQuery(this).attr("title")); + jQuery( "tab", xml ).each(function() { + titles.push( jQuery(this).attr("title") ); }); equals( titles[0], "Location", "attr() in XML context: Check first title" ); equals( titles[1], "Users", "attr() in XML context: Check second title" ); From 966c2fe46a785a2555ec9a1048fc4a9014c40aa3 Mon Sep 17 00:00:00 2001 From: louisremi Date: Tue, 10 May 2011 12:18:40 +0200 Subject: [PATCH 05/40] oops console --- test/unit/effects.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/effects.js b/test/unit/effects.js index f015fc91..6fbbbfe3 100644 --- a/test/unit/effects.js +++ b/test/unit/effects.js @@ -1001,7 +1001,6 @@ test("callbacks should fire in correct order (#9100)", function() { $lis = jQuery("

").appendTo("#qunit-fixture") // The test will always pass if no properties are animated or if the duration is 0 .animate({fontSize: 12}, 13, function() { - console.log(jQuery(this).data("operation")) a *= jQuery(this).data("operation") === "*2" ? 2 : a; cb++; if ( cb === 2 ) { From 38de389a8e675c0c2d1172dd23339325ae82539a Mon Sep 17 00:00:00 2001 From: jaubourg Date: Tue, 10 May 2011 12:23:53 +0200 Subject: [PATCH 06/40] Adds unit/support.js to unit tests. Still have to test for #8763 has to be done in its own file however, since Firefox refuses to notify global errors in the iframe (attachEvent, window.onerror and script.onerror all fail). --- test/boxModelIE.html | 33 --------------------------- test/data/support/boxModelIE.html | 27 ++++++++++++++++++++++ test/data/support/hiddenIFrameFF.html | 25 ++++++++++++++++++++ test/index.html | 1 + test/unit/support.js | 32 ++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 33 deletions(-) delete mode 100644 test/boxModelIE.html create mode 100644 test/data/support/boxModelIE.html create mode 100644 test/data/support/hiddenIFrameFF.html create mode 100644 test/unit/support.js diff --git a/test/boxModelIE.html b/test/boxModelIE.html deleted file mode 100644 index f8e6a431..00000000 --- a/test/boxModelIE.html +++ /dev/null @@ -1,33 +0,0 @@ - - - -

jQuery Test boxModel detection in IE 6 & 7 compatMode="CSS1Compat"

-
document.compatMode = ?
-
jQuery.support.boxModel = ?
- - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/data/support/boxModelIE.html b/test/data/support/boxModelIE.html new file mode 100644 index 00000000..1b11d2a5 --- /dev/null +++ b/test/data/support/boxModelIE.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/data/support/hiddenIFrameFF.html b/test/data/support/hiddenIFrameFF.html new file mode 100644 index 00000000..000ac851 --- /dev/null +++ b/test/data/support/hiddenIFrameFF.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/index.html b/test/index.html index 3d421a56..4b4c9855 100644 --- a/test/index.html +++ b/test/index.html @@ -34,6 +34,7 @@ + diff --git a/test/unit/support.js b/test/unit/support.js new file mode 100644 index 00000000..9d99529a --- /dev/null +++ b/test/unit/support.js @@ -0,0 +1,32 @@ +module("support", { teardown: moduleTeardown }); + +function supportIFrameTest( title, url, noDisplay, func ) { + + if ( noDisplay !== true ) { + func = noDisplay; + noDisplay = false; + } + + test( title, function() { + var iframe; + + stop(); + window.supportCallback = function() { + var self = this, + args = arguments; + setTimeout( function() { + window.supportCallback = undefined; + iframe.remove(); + func.apply( self, args ); + start(); + }, 0 ); + }; + iframe = jQuery( "
" ).css( "display", noDisplay ? "none" : "block" ).append( + jQuery( "