aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2022-11-14 18:36:53 +0100
committerMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2022-11-14 23:17:23 +0100
commit3299236c898136dc1aa57dc5148811203e931895 (patch)
tree1a9b0c2629362272653a6c5d59f1cd8d5a27ace9
parent0208224b5b76d54a39986f78aac97dbf1cccbe38 (diff)
downloadjquery-3299236c898136dc1aa57dc5148811203e931895.tar.gz
jquery-3299236c898136dc1aa57dc5148811203e931895.zip
Selector:Manipulation: Fix DOM manip within template contents
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
-rw-r--r--src/selector/contains.js7
-rw-r--r--test/unit/manipulation.js40
-rw-r--r--test/unit/selector.js13
3 files changed, 56 insertions, 4 deletions
diff --git a/src/selector/contains.js b/src/selector/contains.js
index a62b97ab5..137b54388 100644
--- a/src/selector/contains.js
+++ b/src/selector/contains.js
@@ -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
) );
};
diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js
index f86474f23..d51c0665c 100644
--- a/test/unit/manipulation.js
+++ b/test/unit/manipulation.js
@@ -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 );
diff --git a/test/unit/selector.js b/test/unit/selector.js
index 12297fae9..47837d6ce 100644
--- a/test/unit/selector.js
+++ b/test/unit/selector.js
@@ -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 );