diff options
author | Richard Gibson <richard.gibson@gmail.com> | 2012-11-19 09:50:19 -0500 |
---|---|---|
committer | Richard Gibson <richard.gibson@gmail.com> | 2012-11-19 09:50:19 -0500 |
commit | e889134058232c5e19156353c5fc3bf3b4915a94 (patch) | |
tree | 3a792e2b88248fc97224f21310fb7ee32d25d76b /test/unit/manipulation.js | |
parent | 90f9f4965a49232cbad6b3f4427a6c3172a3e15c (diff) | |
download | jquery-e889134058232c5e19156353c5fc3bf3b4915a94.tar.gz jquery-e889134058232c5e19156353c5fc3bf3b4915a94.zip |
Fix #11795, #10470: keep scripts in DOM; execute only on first insertion. Close gh-864.
Diffstat (limited to 'test/unit/manipulation.js')
-rw-r--r-- | test/unit/manipulation.js | 239 |
1 files changed, 161 insertions, 78 deletions
diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 19897af74..8047bdf49 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -1372,7 +1372,9 @@ test("clone()", function() { equal( jQuery(form).clone().children().length, 1, "Make sure we just get the form back." ); - equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" ); + var body = jQuery("body").clone(); + equal( body.children()[0].id, "qunit-header", "Make sure cloning body works" ); + body.remove(); }); test("clone(script type=non-javascript) (#11359)", function() { @@ -1382,6 +1384,7 @@ test("clone(script type=non-javascript) (#11359)", function() { equal( dest[0].text, "Lorem ipsum dolor sit amet", "Cloning preserves script text" ); equal( dest.last().html(), src.last().html(), "Cloning preserves nested script text" ); ok( /^\s*<scr.pt\s+type=['"]?text\/filler['"]?\s*>consectetur adipiscing elit<\/scr.pt>\s*$/i.test( dest.last().html() ), "Cloning preserves nested script text" ); + dest.remove(); }); test("clone(form element) (Bug #3879, #6655)", function() { @@ -1449,100 +1452,124 @@ test("html() on empty set", function() { strictEqual( jQuery().html(), undefined, ".html() returns undefined for empty sets (#11962)" ); }); -var testHtml = function(valueObj) { - expect(35); - - jQuery["scriptorder"] = 0; +var childNodeNames = function( node ) { + return jQuery.map( node.childNodes, function( child ) { + return child.nodeName.toUpperCase(); + }).join(" "); +}; - var div = jQuery("#qunit-fixture > div"); - div.html(valueObj("<b>test</b>")); - var pass = true; - for ( var i = 0; i < div.size(); i++ ) { - if ( div.get(i).childNodes.length != 1 ) { - pass = false; - } - } - ok( pass, "Set HTML" ); +var testHtml = function( valueObj ) { + expect( 37 ); - div = jQuery("<div/>").html( valueObj("<div id='parent_1'><div id='child_1'/></div><div id='parent_2'/>") ); + var actual, expected, tmp, + div = jQuery("<div></div>"), + fixture = jQuery("#qunit-fixture"); - equal( div.children().length, 2, "Make sure two child nodes exist." ); - equal( div.children().children().length, 1, "Make sure that a grandchild exists." ); + div.html( valueObj("<div id='parent_1'><div id='child_1'/></div><div id='parent_2'/>") ); + equal( div.children().length, 2, "Found children" ); + equal( div.children().children().length, 1, "Found grandchild" ); - var space = jQuery("<div/>").html(valueObj(" "))[0].innerHTML; - ok( /^\xA0$|^ $/.test( space ), "Make sure entities are passed through correctly." ); - equal( jQuery("<div/>").html(valueObj("&"))[0].innerHTML, "&", "Make sure entities are passed through correctly." ); + actual = []; expected = []; + tmp = jQuery("<map/>").html( valueObj("<area alt='area'/>") ).each(function() { + expected.push("AREA"); + actual.push( childNodeNames( this ) ); + }); + equal( expected.length, 1, "Expecting one parent" ); + deepEqual( actual, expected, "Found the inserted area element" ); - jQuery("#qunit-fixture").html(valueObj("<style>.foobar{color:green;}</style>")); + equal( div.html( valueObj(5) ).html(), "5", "Setting a number as html" ); + equal( div.html( valueObj(0) ).html(), "0", "Setting a zero as html" ); - equal( jQuery("#qunit-fixture").children().length, 1, "Make sure there is a child element." ); - equal( jQuery("#qunit-fixture").children()[0].nodeName.toUpperCase(), "STYLE", "And that a style element was inserted." ); + div.html( valueObj(" &") ); + equal( + div[0].innerHTML.replace( /\xA0/, " " ), + " &", + "Entities are passed through correctly" + ); - QUnit.reset(); - // using contents will get comments regular, text, and comment nodes - var j = jQuery("#nonnodes").contents(); - j.html(valueObj("<b>bold</b>")); + tmp = "<div>hello1</div>"; + equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html" ); + tmp = "x" + tmp; + equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html, leading x" ); + tmp = " " + tmp.slice(1); + equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html, leading space" ); + + actual = []; expected = []; tmp = {}; + jQuery("#nonnodes").contents().html( valueObj("<b>bold</b>") ).each(function() { + var html = jQuery( this ).html(); + tmp[ this.nodeType ] = true; + expected.push( this.nodeType === 1 ? "<b>bold</b>" : undefined ); + actual.push( html ? html.toLowerCase() : html ); + }); + deepEqual( actual, expected, "Set containing element, text node, comment" ); + ok( tmp[1], "element" ); + ok( tmp[3], "text node" ); + ok( tmp[8], "comment" ); + + actual = []; expected = []; + fixture.find("> div").html( valueObj("<b>test</b>") ).each(function() { + expected.push("B"); + actual.push( childNodeNames( this ) ); + }); + equal( expected.length, 6, "Expecting many parents" ); + deepEqual( actual, expected, "Correct childNodes after setting HTML" ); - // this is needed, or the expando added by jQuery unique will yield a different html - j.find("b").removeData(); - equal( j.html().replace(/ xmlns="[^"]+"/g, "").toLowerCase(), "<b>bold</b>", "Check node,textnode,comment with html()" ); + actual = []; expected = []; + fixture.html( valueObj("<style>.foobar{color:green;}</style>") ).each(function() { + expected.push("STYLE"); + actual.push( childNodeNames( this ) ); + }); + equal( expected.length, 1, "Expecting one parent" ); + deepEqual( actual, expected, "Found the inserted style element" ); - jQuery("#qunit-fixture").html(valueObj("<select/>")); - jQuery("#qunit-fixture select").html(valueObj("<option>O1</option><option selected='selected'>O2</option><option>O3</option>")); + fixture.html( valueObj("<select/>") ); + jQuery("#qunit-fixture select").html( valueObj("<option>O1</option><option selected='selected'>O2</option><option>O3</option>") ); equal( jQuery("#qunit-fixture select").val(), "O2", "Selected option correct" ); - var $div = jQuery("<div />"); - equal( $div.html(valueObj( 5 )).html(), "5", "Setting a number as html" ); - equal( $div.html(valueObj( 0 )).html(), "0", "Setting a zero as html" ); - - var $div2 = jQuery("<div/>"), insert = "<div>hello1</div>"; - equal( $div2.html(insert).html().replace(/>/g, ">"), insert, "Verify escaped insertion." ); - equal( $div2.html("x" + insert).html().replace(/>/g, ">"), "x" + insert, "Verify escaped insertion." ); - equal( $div2.html(" " + insert).html().replace(/>/g, ">"), " " + insert, "Verify escaped insertion." ); - - var map = jQuery("<map/>").html(valueObj("<area id='map01' shape='rect' coords='50,50,150,150' href='http://www.jquery.com/' alt='jQuery'>")); - - equal( map[0].childNodes.length, 1, "The area was inserted." ); - equal( map[0].firstChild.nodeName.toLowerCase(), "area", "The area was inserted." ); - - QUnit.reset(); - - jQuery("#qunit-fixture").html(valueObj("<script type='something/else'>ok( false, 'Non-script evaluated.' );</script><script type='text/javascript'>ok( true, 'text/javascript is evaluated.' );</script><script>ok( true, 'No type is evaluated.' );</script><div><script type='text/javascript'>ok( true, 'Inner text/javascript is evaluated.' );</script><script>ok( true, 'Inner No type is evaluated.' );</script><script type='something/else'>ok( false, 'Non-script evaluated.' );</script><script type='type/ecmascript'>ok( true, 'type/ecmascript evaluated.' );</script></div>")); - - var child = jQuery("#qunit-fixture").find("script"); - - equal( child.length, 2, "Make sure that two non-JavaScript script tags are left." ); - equal( child[0].type, "something/else", "Verify type of script tag." ); - equal( child[1].type, "something/else", "Verify type of script tag." ); - - jQuery("#qunit-fixture").html(valueObj("<script>ok( true, 'Test repeated injection of script.' );</script>")); - jQuery("#qunit-fixture").html(valueObj("<script>ok( true, 'Test repeated injection of script.' );</script>")); - jQuery("#qunit-fixture").html(valueObj("<script>ok( true, 'Test repeated injection of script.' );</script>")); - - jQuery("#qunit-fixture").html(valueObj("<script type='text/javascript'>ok( true, 'jQuery().html().evalScripts() Evals Scripts Twice in Firefox, see #975 (1)' );</script>")); - - jQuery("#qunit-fixture").html(valueObj("foo <form><script type='text/javascript'>ok( true, 'jQuery().html().evalScripts() Evals Scripts Twice in Firefox, see #975 (2)' );</script></form>")); - - jQuery("#qunit-fixture").html(valueObj("<script>equal(jQuery.scriptorder++, 0, 'Script is executed in order');equal(jQuery('#scriptorder').length, 1,'Execute after html (even though appears before)')<\/script><span id='scriptorder'><script>equal(jQuery.scriptorder++, 1, 'Script (nested) is executed in order');equal(jQuery('#scriptorder').length, 1,'Execute after html')<\/script></span><script>equal(jQuery.scriptorder++, 2, 'Script (unnested) is executed in order');equal(jQuery('#scriptorder').length, 1,'Execute after html')<\/script>")); + tmp = fixture.html( + valueObj([ + "<script type='something/else'>ok( false, 'evaluated: non-script' );</script>", + "<script type='text/javascript'>ok( true, 'evaluated: text/javascript' );</script>", + "<script type='text/ecmascript'>ok( true, 'evaluated: text/ecmascript' );</script>", + "<script>ok( true, 'evaluated: no type' );</script>", + "<div>", + "<script type='something/else'>ok( false, 'evaluated: inner non-script' );</script>", + "<script type='text/javascript'>ok( true, 'evaluated: inner text/javascript' );</script>", + "<script type='text/ecmascript'>ok( true, 'evaluated: inner text/ecmascript' );</script>", + "<script>ok( true, 'evaluated: inner no type' );</script>", + "</div>" + ].join("")) + ).find("script"); + equal( tmp.length, 8, "All script tags remain." ); + equal( tmp[0].type, "something/else", "Non-evaluated type." ); + equal( tmp[1].type, "text/javascript", "Evaluated type." ); + + fixture.html( valueObj("<script type='text/javascript'>ok( true, 'Injection of identical script' );</script>") ); + fixture.html( valueObj("<script type='text/javascript'>ok( true, 'Injection of identical script' );</script>") ); + fixture.html( valueObj("<script type='text/javascript'>ok( true, 'Injection of identical script' );</script>") ); + fixture.html( valueObj("foo <form><script type='text/javascript'>ok( true, 'Injection of identical script (#975)' );</script></form>") ); + + jQuery.scriptorder = 0; + fixture.html( valueObj([ + "<script>", + "equal( jQuery('#scriptorder').length, 1,'Execute after html' );", + "equal( jQuery.scriptorder++, 0, 'Script is executed in order' );", + "</script>", + "<span id='scriptorder'><script>equal( jQuery.scriptorder++, 1, 'Script (nested) is executed in order');</script></span>", + "<script>equal( jQuery.scriptorder++, 2, 'Script (unnested) is executed in order' );</script>" + ].join("")) ); + + QUnit.reset(); + fixture.html( valueObj( fixture.text() ) ); + ok( /^[^<]*[^<\s][^<]*$/.test( fixture.html() ), "Replace html with text" ); }; test("html(String)", function() { - testHtml(manipulationBareObj); + testHtml( manipulationBareObj ); }); test("html(Function)", function() { - testHtml(manipulationFunctionReturningObj); - - expect(37); - - QUnit.reset(); - - jQuery("#qunit-fixture").html(function(){ - return jQuery(this).text(); - }); - - ok( !/</.test( jQuery("#qunit-fixture").html() ), "Replace html with text." ); - ok( jQuery("#qunit-fixture").html().length > 0, "Make sure text exists." ); + testHtml( manipulationFunctionReturningObj ); }); test("html(Function) with incoming value", function() { @@ -2083,3 +2110,59 @@ testIframeWithCallback( "buildFragment works even if document[0] is iframe's win ok( test.status, test.description ); }); + +test("script evaluation (#11795)", function() { + expect(11); + + var scriptsIn, scriptsOut, + fixture = jQuery("#qunit-fixture").empty(), + objGlobal = (function(){ return this; })(), + isOk = objGlobal.ok, + notOk = function() { + var args = arguments; + args[0] = !args[0]; + return isOk.apply( this, args ); + }; + + objGlobal.ok = notOk; + scriptsIn = jQuery([ + "<script type='something/else'>ok( false, 'evaluated: non-script' );</script>", + "<script type='text/javascript'>ok( true, 'evaluated: text/javascript' );</script>", + "<script type='text/ecmascript'>ok( true, 'evaluated: text/ecmascript' );</script>", + "<script>ok( true, 'evaluated: no type' );</script>", + "<div>", + "<script type='something/else'>ok( false, 'evaluated: inner non-script' );</script>", + "<script type='text/javascript'>ok( true, 'evaluated: inner text/javascript' );</script>", + "<script type='text/ecmascript'>ok( true, 'evaluated: inner text/ecmascript' );</script>", + "<script>ok( true, 'evaluated: inner no type' );</script>", + "</div>" + ].join("")); + scriptsIn.appendTo( jQuery("<div class='detached'/>") ); + objGlobal.ok = isOk; + + scriptsOut = fixture.append( scriptsIn ).find("script"); + equal( scriptsOut[0].type, "something/else", "Non-evaluated type." ); + equal( scriptsOut[1].type, "text/javascript", "Evaluated type." ); + deepEqual( scriptsOut.get(), fixture.find("script").get(), "All script tags remain." ); + + objGlobal.ok = notOk; + scriptsOut = scriptsOut.add( scriptsOut.clone() ).appendTo( fixture.find("div") ); + deepEqual( fixture.find("div script").get(), scriptsOut.get(), "Scripts cloned without reevaluation" ); + fixture.append( scriptsOut.detach() ); + deepEqual( fixture.find("> script").get(), scriptsOut.get(), "Scripts detached without reevaluation" ); + objGlobal.ok = isOk; +}); + +test("wrapping scripts (#10470)", function() { + expect(2); + + var script = document.createElement("script"); + script.text = script.textContent = + "ok( !document.eval10470, 'script evaluated once' ); document.eval10470 = true;"; + + document.eval10470 = false; + jQuery("#qunit-fixture").empty()[0].appendChild( script ); + jQuery("#qunit-fixture script").wrap("<b></b>"); + strictEqual( script.parentNode, jQuery("#qunit-fixture > b")[0], "correctly wrapped" ); + jQuery( script ).remove(); +}); |