]> source.dussan.org Git - jquery.git/commitdiff
Selector:Manipulation: Fix DOM manip within template contents
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Mon, 14 Nov 2022 17:36:53 +0000 (18:36 +0100)
committerMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Mon, 14 Nov 2022 22:17:23 +0000 (23:17 +0100)
The `<template/>` element `contents` property is a document fragment that may
have a `null` `documentElement`. In Safari 16 this happens in more cases due
to recent spec changes - in particular, even if that document fragment is
explicitly adopted into an outer document. We're testing both of those cases
now.

The crash used to happen in `jQuery.contains`. As it turns out, we don't need
to query the supposed container `documentElement` if it has the
`Node.DOCUMENT_NODE` (9) `nodeType`; we can call `.contains()` directly on
the `document`. That avoids the crash.

Fixes gh-5147
Closes gh-5158

src/selector/contains.js
test/unit/manipulation.js
test/unit/selector.js

index a62b97ab5bb4953dd4c08bd1b2f3a07ecf84c16c..137b54388c8d8aa47b84b552fd82944109ec8591 100644 (file)
@@ -2,15 +2,14 @@ import jQuery from "../core.js";
 
 // Note: an element does not contain itself
 jQuery.contains = function( a, b ) {
-       var adown = a.nodeType === 9 ? a.documentElement : a,
-               bup = b && b.parentNode;
+       var bup = b && b.parentNode;
 
        return a === bup || !!( bup && bup.nodeType === 1 && (
 
                // Support: IE 9 - 11+
                // IE doesn't have `contains` on SVG.
-               adown.contains ?
-                       adown.contains( bup ) :
+               a.contains ?
+                       a.contains( bup ) :
                        a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
        ) );
 };
index f86474f239c620d298825e81434c354980342367..d51c0665cc97f5222deeb41962532945c6bf32e7 100644 (file)
@@ -2830,6 +2830,46 @@ QUnit.test( "Make sure tr is not appended to the wrong tbody (gh-3439)", functio
        assert.strictEqual( htmlOut, htmlExpected );
 } );
 
+[ true, false ].forEach( function( adoptedCase ) {
+       QUnit.testUnlessIE(
+               "Manip within <template /> content moved back & forth doesn't throw - " + (
+                       adoptedCase ? "explicitly adopted" : "not explicitly adopted"
+               ) + " (gh-5147)",
+               function( assert ) {
+                       assert.expect( 1 );
+
+                       var fragment, diva, divb,
+                               div = jQuery( "" +
+                                       "<div>\n" +
+                                       "       <div><div class='a'></div></div>\n" +
+                                       "       <div><div class='b'></div></div>\n" +
+                                       "</div>" +
+                                       "" ),
+                               template = jQuery( "<template></template>" );
+
+                       jQuery( "#qunit-fixture" )
+                               .append( div )
+                               .append( template );
+
+                       fragment = template[ 0 ].content;
+                       diva = div.find( ".a" );
+                       divb = div.find( ".b" );
+
+                       if ( adoptedCase ) {
+                               document.adoptNode( fragment );
+                       }
+
+                       fragment.appendChild( div.children()[ 0 ] );
+                       fragment.appendChild( div.children()[ 0 ] );
+
+                       diva.insertBefore( divb );
+
+                       assert.strictEqual( diva.siblings( ".b" ).length, 1,
+                               "Insertion worked" );
+               }
+       );
+} );
+
 QUnit.test( "Make sure tags with single-character names are found (gh-4124)", function( assert ) {
        assert.expect( 1 );
 
index 12297fae9fdbb3da953a0b67b75b2f37f12ed3b6..47837d6ce10a44c3e4e1318168ddf4207a9759bd 100644 (file)
@@ -1895,6 +1895,19 @@ QUnit.test( "jQuery.contains in SVG (jQuery trac-10832)", function( assert ) {
                "parent (negative)" );
 } );
 
+QUnit.testUnlessIE( "jQuery.contains within <template/> doesn't throw (gh-5147)", function( assert ) {
+       assert.expect( 1 );
+
+       var template = jQuery( "<template><div><div class='a'></div></div></template>" ),
+               a = jQuery( template[ 0 ].content ).find( ".a" );
+
+       template.appendTo( "#qunit-fixture" );
+
+       jQuery.contains( a[ 0 ].ownerDocument, a[ 0 ] );
+
+       assert.ok( true, "Didn't throw" );
+} );
+
 QUnit.test( "jQuery.uniqueSort", function( assert ) {
        assert.expect( 14 );