"./var/indexOf",
"./var/pop",
"./var/push",
+ "./selector/support",
// The following utils are attached directly to the jQuery object.
"./selector/contains",
"./selector/escapeSelector",
"./selector/uniqueSort"
-], function( jQuery, document, indexOf, pop, push ) {
+], function( jQuery, document, indexOf, pop, push, support ) {
"use strict";
// Thanks to Andrew Dupont for this technique.
if ( nodeType === 1 && rdescend.test( selector ) ) {
- // Capture the context ID, setting it first if necessary
- if ( ( nid = context.getAttribute( "id" ) ) ) {
- nid = jQuery.escapeSelector( nid );
- } else {
- context.setAttribute( "id", ( nid = expando ) );
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
+
+ // We can use :scope instead of the ID hack if the browser
+ // supports it & if we're not changing the context.
+ if ( newContext !== context || !support.scope ) {
+
+ // Capture the context ID, setting it first if necessary
+ if ( ( nid = context.getAttribute( "id" ) ) ) {
+ nid = jQuery.escapeSelector( nid );
+ } else {
+ context.setAttribute( "id", ( nid = expando ) );
+ }
}
// Prefix every selector in the list
groups = tokenize( selector );
i = groups.length;
while ( i-- ) {
- groups[ i ] = "#" + nid + " " + toSelector( groups[ i ] );
+ groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
+ toSelector( groups[ i ] );
}
newSelector = groups.join( "," );
-
- // Expand context for sibling selectors
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
- context;
}
try {
--- /dev/null
+define( [
+ "../var/document",
+ "../var/support"
+], function( document, support ) {
+
+"use strict";
+
+// Support: IE 9 - 11+, Edge 12 - 18+
+// IE/Edge don't support the :scope pseudo-class.
+try {
+ document.querySelectorAll( ":scope" );
+ support.scope = true;
+} catch ( e ) {}
+
+return support;
+
+} );
}
} );
+// Support: IE 11+, Edge 12 - 18+
+// IE/Edge don't support the :scope pseudo-class so they will trigger MutationObservers.
+// The test is skipped there.
+QUnit[
+ ( QUnit.isIE || /edge\//i.test( navigator.userAgent ) ) ?
+ "skip" :
+ "test"
+ ]( "selectors maintaining context don't trigger mutation observers", function( assert ) {
+ assert.expect( 1 );
+
+ var timeout,
+ done = assert.async(),
+ container = jQuery( "<div/>" ),
+ child = jQuery( "<div/>" );
+
+ child.appendTo( container );
+ container.appendTo( "#qunit-fixture" );
+
+ var observer = new MutationObserver( function() {
+ clearTimeout( timeout );
+ observer.disconnect();
+ assert.ok( false, "Mutation observer fired during selection" );
+ done();
+ } );
+ observer.observe( container[ 0 ], { attributes: true } );
+
+ container.find( "div div" );
+
+ timeout = setTimeout( function() {
+ observer.disconnect();
+ assert.ok( true, "Mutation observer didn't fire during selection" );
+ done();
+ } );
+} );
+
QUnit.test( "caching does not introduce bugs", function( assert ) {
assert.expect( 3 );
var expected,
userAgent = window.navigator.userAgent,
expectedMap = {
- edge: {},
- ie_11: {},
- chrome: {},
- safari: {},
- firefox: {},
- ios: {}
+ edge: {
+ scope: undefined
+ },
+ ie_11: {
+ scope: undefined
+ },
+ chrome: {
+ scope: true
+ },
+ safari: {
+ scope: true
+ },
+ firefox: {
+ scope: true
+ },
+ ios: {
+ scope: true
+ }
};
if ( /edge\//i.test( userAgent ) ) {
j++;
}
+ // Add an assertion per undefined support prop as it may
+ // not even exist on computedSupport but we still want to run
+ // the check.
+ for ( prop in expected ) {
+ if ( expected[ prop ] === undefined ) {
+ j++;
+ }
+ }
+
assert.expect( j );
for ( i in expected ) {
i++;
}
+ // Add an assertion per undefined support prop as it may
+ // not even exist on computedSupport but we still want to run
+ // the check.
+ for ( prop in expected ) {
+ if ( expected[ prop ] === undefined ) {
+ i++;
+ }
+ }
+
assert.expect( i );
// Record all support props and the failing ones and ensure every test
for ( browserKey in expectedMap ) {
for ( supportTestName in expectedMap[ browserKey ] ) {
supportProps[ supportTestName ] = true;
- if ( expectedMap[ browserKey ][ supportTestName ] !== true ) {
+ if ( !expectedMap[ browserKey ][ supportTestName ] ) {
failingSupportProps[ supportTestName ] = true;
}
}