diff options
author | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2022-11-14 18:36:53 +0100 |
---|---|---|
committer | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2022-11-14 23:17:23 +0100 |
commit | 3299236c898136dc1aa57dc5148811203e931895 (patch) | |
tree | 1a9b0c2629362272653a6c5d59f1cd8d5a27ace9 | |
parent | 0208224b5b76d54a39986f78aac97dbf1cccbe38 (diff) | |
download | jquery-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.js | 7 | ||||
-rw-r--r-- | test/unit/manipulation.js | 40 | ||||
-rw-r--r-- | test/unit/selector.js | 13 |
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 ); |