From fb25bacf9b809a08c29e76decd8cda1579fdf192 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Fri, 10 Apr 2015 15:57:18 -0400 Subject: [PATCH] Manipulation: Make an HTML interception point Fixes gh-1747 Closes gh-2203 (cherry picked from commit 225bde37c997f5ddd9fe00fdfb8e9a43545cfbbc) Conflicts: src/manipulation.js test/unit/manipulation.js --- src/manipulation.js | 9 ++- test/unit/core.js | 12 ++-- test/unit/manipulation.js | 115 +++++++++++++++++++++++++------------- 3 files changed, 85 insertions(+), 51 deletions(-) diff --git a/src/manipulation.js b/src/manipulation.js index 4f2cd1b1c..564620368 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -217,6 +217,10 @@ function fixCloneNodeIssues( src, dest ) { } jQuery.extend({ + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + clone: function( elem, dataAndEvents, deepDataAndEvents ) { var destElements, node, clone, i, srcElements, inPage = jQuery.contains( elem.ownerDocument, elem ); @@ -304,8 +308,7 @@ jQuery.extend({ // Deserialize a standard representation tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; - - tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; // Descend through wrappers to the right content j = wrap[0]; @@ -549,7 +552,7 @@ jQuery.fn.extend({ ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { - value = value.replace( rxhtmlTag, "<$1>" ); + value = jQuery.htmlPrefilter( value ); try { for (; i < l; i++ ) { diff --git a/test/unit/core.js b/test/unit/core.js index cccb2df98..7d6ebb767 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -19,8 +19,7 @@ test("jQuery()", function() { img = jQuery(""), div = jQuery("

"), exec = false, - lng = "", - expected = 22, + expected = 23, attrObj = { "text": "test", "class": "test2", @@ -141,12 +140,9 @@ test("jQuery()", function() { } equal( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" ); - // manually clean up detached elements - elem.remove(); - - for ( i = 0; i < 128; i++ ) { - lng += "12345678"; - } + elem = jQuery( "", {} ); + strictEqual( elem[ 0 ].ownerDocument, document, + "Empty attributes object is not interpreted as a document (trac-8950)" ); }); test("jQuery(selector, context)", function() { diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 12ea6194b..5edbe294b 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -2137,7 +2137,7 @@ test( "jQuery.cleanData", function() { } }); -test( "jQuery.buildFragment - no plain-text caching (Bug #6779)", function() { +test( "domManip plain-text caching (trac-6779)", function() { expect( 1 ); @@ -2156,42 +2156,43 @@ test( "jQuery.buildFragment - no plain-text caching (Bug #6779)", function() { $f.remove(); }); -test( "jQuery.html - execute scripts escaped with html comment or CDATA (#9221)", function() { +test( "domManip executes scripts containing html comments or CDATA (trac-9221)", function() { expect( 3 ); - jQuery([ - "" - ].join("\n")).appendTo("#qunit-fixture"); - jQuery([ - "" - ].join("\n")).appendTo("#qunit-fixture"); - jQuery([ - "" - ].join("\n")).appendTo("#qunit-fixture"); -}); - -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 ) {} -}); + jQuery( [ + "" + ].join( "\n" ) ).appendTo( "#qunit-fixture" ); + + jQuery( [ + "" + ].join( "\n" ) ).appendTo( "#qunit-fixture" ); + + jQuery( [ + "" + ].join( "\n" ) ).appendTo( "#qunit-fixture" ); +}); + +testIframeWithCallback( + "domManip tolerates window-valued document[0] in IE9/10 (trac-12266)", + "manipulation/iframe-denied.html", + function( test ) { + expect( 1 ); + ok( test.status, test.description ); + } +); test( "jQuery.clone - no exceptions for object elements #9587", function() { @@ -2360,12 +2361,6 @@ test( "manipulate mixed jQuery and text (#12384, #12346)", function() { equal( div.find("*").length, 3, "added 2 paragraphs after inner div" ); }); -testIframeWithCallback( "buildFragment works even if document[0] is iframe's window object in IE9/10 (#12266)", "manipulation/iframe-denied.html", function( test ) { - expect( 1 ); - - ok( test.status, test.description ); -}); - test( "script evaluation (#11795)", function() { expect( 13 ); @@ -2449,6 +2444,46 @@ test( "jQuery._evalUrl (#12838)", function() { jQuery._evalUrl = evalUrl; }); +test( "jQuery.htmlPrefilter (gh-1747)", function( assert ) { + + assert.expect( 5 ); + + var expectedArgument, + invocations = 0, + htmlPrefilter = jQuery.htmlPrefilter, + fixture = jQuery( "
" ).appendTo( "#qunit-fixture" ), + poison = "", + done = assert.async(); + + jQuery.htmlPrefilter = function( html ) { + invocations++; + assert.equal( html, expectedArgument, "Expected input" ); + + // Remove