Selector: Remove the workaround for :has; test both on iPhone & iPad

Remove the workaround for a broken `:has` selector; we no longer test on any
browser with a buggy `:has`.

Test on last three iOS versions on an iPhone, but on the last two iPadOS
versions on an iPad.

Also, fix test issues on an iPad.

Closes gh-5714
Ref gh-5715
This commit is contained in:
Michał Gołębiowski-Owczarek 2025-10-27 17:57:23 +01:00 committed by GitHub
parent 98cc8c837e
commit 65e35450c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 77 deletions

View File

@ -34,9 +34,11 @@ jobs:
- 'Edge_latest-1'
- 'Firefox_latest'
- 'Firefox_latest-1'
- '__iOS_26'
- '__iOS_18'
- '__iOS_17'
- '_:iPhone 17_iOS_26'
- '_:iPhone 16_iOS_18'
- '_:iPhone 15 Pro_iOS_17'
- '_:iPad Air 13 2025_iOS_26'
- '_:iPad Air 13 2025_iOS_18'
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

View File

@ -1,36 +1,17 @@
import { isIE } from "../var/isIE.js";
import { whitespace } from "../var/whitespace.js";
import { support } from "./support.js";
// Build QSA regex.
// Regex strategy adopted from Diego Perini.
export var rbuggyQSA = [];
export var rbuggyQSA = isIE && new RegExp(
if ( isIE ) {
rbuggyQSA.push(
// Support: IE 9 - 11+
// IE's :disabled selector does not pick up the children of disabled fieldsets
":enabled|:disabled|" +
// Support: IE 9 - 11+
// IE's :disabled selector does not pick up the children of disabled fieldsets
":enabled",
":disabled",
// Support: IE 11+
// IE 11 doesn't find elements on a `[name='']` query in some cases.
// Adding a temporary attribute to the document before the selection works
// around the issue.
"\\[" + whitespace + "*name" + whitespace + "*=" +
whitespace + "*(?:''|\"\")"
// Support: IE 11+
// IE 11 doesn't find elements on a `[name='']` query in some cases.
// Adding a temporary attribute to the document before the selection works
// around the issue.
"\\[" + whitespace + "*name" + whitespace + "*=" +
whitespace + "*(?:''|\"\")"
);
}
if ( !support.cssHas ) {
// Our regular `try-catch` mechanism fails to detect natively-unsupported
// pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`)
// in browsers that parse the `:has()` argument as a forgiving selector list.
// https://drafts.csswg.org/selectors/#relational now requires the argument
// to be parsed unforgivingly, but browsers have not yet fully adjusted.
rbuggyQSA.push( ":has" );
}
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
);

View File

@ -1,20 +0,0 @@
import { document } from "../var/document.js";
import { support } from "../var/support.js";
// Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only
// Make sure the `:has()` argument is parsed unforgivingly.
// We include `*` in the test to detect buggy implementations that are
// _selectively_ forgiving (specifically when the list includes at least
// one valid selector).
// Note that we treat complete lack of support for `:has()` as if it were
// spec-compliant support, which is fine because use of `:has()` in such
// environments will fail in the qSA path and fall back to jQuery traversal
// anyway.
try {
document.querySelector( ":has(*,:jqfake)" );
support.cssHas = false;
} catch ( e ) {
support.cssHas = true;
}
export { support };

View File

@ -1438,10 +1438,17 @@ QUnit.test( "Submit event can be stopped (trac-11049)", function( assert ) {
form.remove();
} );
// Support: iOS <=7 - 18+
// Support: iOS <=7 - 26+
// iOS has the window.onbeforeunload field but doesn't support the beforeunload
// handler making it impossible to feature-detect the support.
QUnit[ /(ipad|iphone|ipod)/i.test( navigator.userAgent ) ? "skip" : "test" ](
QUnit[
/iphone os/i.test( navigator.userAgent ) || (
/\bversion\/\d+(?:\.\d+)+ safari/i.test( navigator.userAgent ) &&
navigator.maxTouchPoints > 1
) ?
"skip" :
"test"
](
"on(beforeunload)", function( assert ) {
assert.expect( 1 );
var iframe = jQuery( jQuery.parseHTML( "<iframe src='" + baseURL + "event/onbeforeunload.html'><iframe>" ) );

View File

@ -77,48 +77,31 @@ testIframe(
);
( function() {
var expected, browserKey,
var expected,
userAgent = window.navigator.userAgent,
expectedMap = {
ie_11: {
cssHas: true,
reliableColDimensions: 11,
reliableTrDimensions: false
},
chrome: {
cssHas: true,
reliableColDimensions: true,
reliableTrDimensions: true
},
safari: {
cssHas: true,
reliableColDimensions: false,
reliableTrDimensions: true
},
firefox: {
cssHas: true,
reliableColDimensions: false,
reliableTrDimensions: false
},
ios_16_3: {
cssHas: false,
reliableColDimensions: false,
reliableTrDimensions: true
},
ios: {
cssHas: true,
reliableColDimensions: false,
reliableTrDimensions: true
}
};
// Make the selector-native build pass tests.
for ( browserKey in expectedMap ) {
if ( !includesModule( "selector" ) ) {
delete expectedMap[ browserKey ].cssHas;
}
}
if ( QUnit.isIE ) {
expected = expectedMap.ie_11;
} else if ( /\b(?:headless)?chrome\//i.test( userAgent ) ) {
@ -127,12 +110,14 @@ testIframe(
expected = expectedMap.chrome;
} else if ( /\bfirefox\//i.test( userAgent ) ) {
expected = expectedMap.firefox;
} else if ( /\biphone os 16_[0123]/i.test( userAgent ) ) {
expected = expectedMap.ios_16_3;
} else if ( /\b(?:iphone|ipad);.*(?:iphone)? os \d+_/i.test( userAgent ) ) {
} else if ( /\biphone os \d+_/i.test( userAgent ) ) {
expected = expectedMap.ios;
} else if ( /\bversion\/\d+(?:\.\d+)+ safari/i.test( userAgent ) ) {
expected = expectedMap.safari;
if ( navigator.maxTouchPoints > 1 ) {
expected = expectedMap.ios;
} else {
expected = expectedMap.safari;
}
}
QUnit.test( "Verify that support tests resolve as expected per browser", function( assert ) {