]> source.dussan.org Git - jquery.git/commitdiff
Manipulation: Make an HTML interception point
authorRichard Gibson <richard.gibson@gmail.com>
Fri, 10 Apr 2015 19:57:18 +0000 (15:57 -0400)
committerRichard Gibson <richard.gibson@gmail.com>
Thu, 30 Apr 2015 17:16:28 +0000 (13:16 -0400)
Fixes gh-1747
Closes gh-2203

(cherry picked from commit 225bde37c997f5ddd9fe00fdfb8e9a43545cfbbc)

Conflicts:
src/manipulation.js
test/unit/manipulation.js

src/manipulation.js
test/unit/core.js
test/unit/manipulation.js

index 4f2cd1b1c362677d5cd52059515218d4a186e753..564620368e85d2a838d401ca93287cbf4c642951 100644 (file)
@@ -217,6 +217,10 @@ function fixCloneNodeIssues( src, dest ) {
 }
 
 jQuery.extend({
+       htmlPrefilter: function( html ) {
+               return html.replace( rxhtmlTag, "<$1></$2>" );
+       },
+
        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></$2>" ) + 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></$2>" );
+                               value = jQuery.htmlPrefilter( value );
 
                                try {
                                        for (; i < l; i++ ) {
index cccb2df981942e2cdd073abf97a10b8fa45f786c..7d6ebb767e1d5f3f60e865947341f86b9f45ed4f 100644 (file)
@@ -19,8 +19,7 @@ test("jQuery()", function() {
                img = jQuery("<img/>"),
                div = jQuery("<div/><hr/><code/><b/>"),
                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( "<input type='hidden'>", {} );
+       strictEqual( elem[ 0 ].ownerDocument, document,
+               "Empty attributes object is not interpreted as a document (trac-8950)" );
 });
 
 test("jQuery(selector, context)", function() {
index 12ea6194ba2ab3a10d46c02096f95f12df37ea2a..5edbe294bba9481acaf156c86c8a22fb63193bad 100644 (file)
@@ -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([
-                               "<script type='text/javascript'>",
-                               "<!--",
-                               "ok( true, '<!-- handled' );",
-                               "//-->",
-                               "</script>"
-                       ].join("\n")).appendTo("#qunit-fixture");
-       jQuery([
-                               "<script type='text/javascript'>",
-                               "<![CDATA[",
-                               "ok( true, '<![CDATA[ handled' );",
-                               "//]]>",
-                               "</script>"
-                       ].join("\n")).appendTo("#qunit-fixture");
-       jQuery([
-                               "<script type='text/javascript'>",
-                               "<!--//--><![CDATA[//><!--",
-                               "ok( true, '<!--//--><![CDATA[//><!-- (Drupal case) handled' );",
-                               "//--><!]]>",
-                               "</script>"
-                       ].join("\n")).appendTo("#qunit-fixture");
-});
-
-test( "jQuery.buildFragment - plain objects are not a document #8950", function() {
-
-       expect( 1 );
-
-       try {
-               jQuery( "<input type='hidden'>", {} );
-               ok( true, "Does not allow attribute object to be treated like a doc object" );
-       } catch ( e ) {}
-});
+       jQuery( [
+               "<script type='text/javascript'>",
+               "<!--",
+               "ok( true, '<!-- handled' );",
+               "//-->",
+               "</script>"
+       ].join( "\n" ) ).appendTo( "#qunit-fixture" );
+
+       jQuery( [
+               "<script type='text/javascript'>",
+               "<![CDATA[",
+               "ok( true, '<![CDATA[ handled' );",
+               "//]]>",
+               "</script>"
+       ].join( "\n" ) ).appendTo( "#qunit-fixture" );
+
+       jQuery( [
+               "<script type='text/javascript'>",
+               "<!--//--><![CDATA[//><!--",
+               "ok( true, '<!--//--><![CDATA[//><!-- (Drupal case) handled' );",
+               "//--><!]]>",
+               "</script>"
+       ].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( "<div/>" ).appendTo( "#qunit-fixture" ),
+               poison = "<script>jQuery.htmlPrefilter.assert.ok( false, 'script not executed' );</script>",
+               done = assert.async();
+
+       jQuery.htmlPrefilter = function( html ) {
+               invocations++;
+               assert.equal( html, expectedArgument, "Expected input" );
+
+               // Remove <script> and <del> elements
+               return htmlPrefilter.apply( this, arguments )
+                       .replace( /<(script|del)(?=[\s>])[\w\W]*?<\/\1\s*>/ig, "" );
+       };
+       jQuery.htmlPrefilter.assert = assert;
+
+       expectedArgument = "A-" + poison + "B-" + poison + poison + "C-";
+       fixture.html( expectedArgument );
+
+       expectedArgument = "D-" + poison + "E-" + "<del/><div>" + poison + poison + "</div>" + "F-";
+       fixture.append( expectedArgument );
+
+       expectedArgument = poison;
+       fixture.find( "div" ).replaceWith( expectedArgument );
+
+       assert.equal( invocations, 3, "htmlPrefilter invoked for all DOM manipulations" );
+       assert.equal( fixture.html(), "A-B-C-D-E-F-", "htmlPrefilter modified HTML" );
+
+       // Allow asynchronous script execution to generate assertions
+       setTimeout( function() {
+               jQuery.htmlPrefilter = htmlPrefilter;
+               done();
+       }, 100 );
+});
+
 test( "insertAfter, insertBefore, etc do not work when destination is original element. Element is removed (#4087)", function() {
 
        expect( 10 );