[wpt-sync] Sync PR 29090 - Supports :has() pseudo class matching
Categories
(Core :: CSS Parsing and Computation, task, P4)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox91 | --- | fixed |
People
(Reporter: wpt-sync, Unassigned)
References
()
Details
(Whiteboard: [wptsync downstream])
Sync web-platform-tests PR 29090 into mozilla-central (this bug is closed when the sync is complete).
PR: https://github.com/web-platform-tests/wpt/pull/29090
Details from upstream follow.
b'Byungwoo Lee <blee@igalia.com>' wrote:
Supports :has() pseudo class matching
Add :has() pseudo class syntax support and matching logic behind a runtime
experimental feature (CSSPseudoHas)\<Syntax support>
Add syntax support for :has() pseudo class specified in Selectors Level 4.:has() pseudo class takes a relatvie selector list as an argument.
- :has(\<relative-selector-list>)
- \<relative-selector-list> = \<relative-selector>#
- \<relative-selector> = \<combinator>? \<complex-selector>
\<relative-selector> is also specified in Selectors Level 4,
and it is not supported yet.So this CL only supports argument selectors starting with descendant combinator.
- .a:has(.b)
Argument selectors starting with other combinators are not supported yet.
- .a:has(> .b)
- .a:has(~ .b)
- .a:has(+ .b)
\<Selector matching>
Add :has() pseudo class selector matching logic.This CL suggests stack-allocated :has() matching status cache
to prevent repetitive tree traversal and argument selector matching
operation.The cache stores each element status as below.
- Matched : Checked :has() and matched
- Checked : Checked :has() but not matched
- NotChecked : Not checked :has() (default)
Below is the pseudo code for :has matching with descendant relative selectors.
(e.g. ':has(.a)' or ':has(:scope .a)')
┬ Allocate cache on stack memory
├ Enter the style recalculation sequence (or Node selector js API sequence)
│ ├ ...
│ ├ Enter the selector matching sequence
│ │ ├ If matching :has pseudo class on an element
│ │ │ └ Enter :has selector matching sequence
│ │ │ ├ Get argument selector
│ │ │ ├ Get element status from cache
│ │ │ ├ If the element status is checked
│ │ │ │ └ If the element status is matched
│ │ │ │ └ Finish has pseudo class matching as matched
│ │ │ ├ Else
│ │ │ │ ├ Set the element status as checked
│ │ │ │ └ Traverse all descendants of the element
│ │ │ │ ├ Get the descendant status from cache
│ │ │ │ ├ If the descendant status is checked
│ │ │ │ │ └ If the descendant status is matched
│ │ │ │ │ ├ Set the element status as matched
│ │ │ │ │ └ Finish has pseudo class matching as matched
│ │ │ │ └ Else
│ │ │ │ ├ Set the descendant status as checked
│ │ │ │ └ If the descendant matches the argument selector
│ │ │ │ ├ Get start element of the shortest match
│ │ │ │ ├ Traverse it's ancestors until met the element
│ │ │ │ │ └ Set the ancestor status as matched
│ │ │ │ ├ Set the element status as matched
│ │ │ │ └ Finish has pseudo class matching as matched
│ │ │ └ Finish has pseudo class matching as not matched
│ │ └ Otherwise
│ │ └ Do other selector matching sequence
│ └ ...
└ Release cache from stack memoryOther cases will be handled later in separated CLs.
- :has(> .a) , :has(:scope > .a)
- :has(~ .a) , :has(:scope ~ .a)
- :has(+ .a) , :has(:scope + .a)
This CL supports :has with following javascript APIs.
- querySelector
- querySelectorAll
- matches
- closest
This CL merged 2 CLs to prevent a web_test failure (jquery/traversing.html)
- https://chromium-review.googlesource.com/c/chromium/src/+/2648150
- https://chromium-review.googlesource.com/c/chromium/src/+/2695192
Change-Id: I1992b70d86f47fc5f98437e1e6abea2da021ef6b
Bug: 669058
Reviewed-on: https://chromium-review.googlesource.com/2914717
WPT-Export-Revision: 9ad542085667cf694c7046e3d3f65a30f668a139
| Assignee | ||
Updated•4 years ago
|
| Assignee | ||
Comment 1•4 years ago
|
||
| Assignee | ||
Comment 2•4 years ago
|
||
CI Results
Ran 15 Firefox configurations based on mozilla-central, and Firefox, Chrome, and Safari on GitHub CI
Total 2 tests and 30 subtests
Status Summary
Firefox
OK : 2
PASS: 1
FAIL: 52
Chrome
OK : 2
PASS: 1
FAIL: 52
Safari
OK : 2
PASS: 1
FAIL: 52
Links
Gecko CI (Treeherder)
GitHub PR Head
GitHub PR Base
Details
New Tests That Don't Pass
/css/selectors/has-basic.html
:has(#a) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.ancestor) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.descendant) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.parent:has(.target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.sibling ~ .target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.parent:has(.sibling ~ .target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(:is(.target ~ .sibling .descendant)) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.parent:has(:is(.target ~ .sibling .descendant)) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.sibling:has(.descendant) ~ .target matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.sibling:has(.descendant) ~ .target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.sibling:has(.descendant) ~ .target) ~ .parent > .descendant matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(:scope .target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(:scope > .parent) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(> .target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
:has(:scope > .target) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.target:has(+ .sibling) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.target:has(:scope + .sibling) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.parent:has(~ #h) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.parent:has(:scope ~ #h) matches expected elements: FAIL (Chrome: FAIL, Safari: FAIL)
.sibling:has(.descendant) matches expected element: FAIL (Chrome: FAIL, Safari: FAIL)
closest(.ancestor:has(.descendant)) returns expected element: FAIL (Chrome: FAIL, Safari: FAIL)
:has(.target ~ .sibling .descendant) matches expectedly: FAIL (Chrome: FAIL, Safari: FAIL)
/css/selectors/parsing/parse-has.html
":has(a)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has(#a)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has(.a)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has([a])" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has([a="b"])" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has([a|="b"])" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has(:hover)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has(.a)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(.b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(:scope .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(> .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(:scope > .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(~ .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(:scope ~ .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(+ .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(:scope + .b)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(.b) .c" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a .b:has(.c)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a .b:has(.c .d)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a .b:has(.c .d) .e" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(.b:has(.c))" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(.b:is(.c .d))" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(.b:is(.c:has(.d) .e))" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:is(.b:has(.c) .d)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:not(:has(.b))" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(:not(.b))" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
".a:has(.b):has(.c)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
"|:has()" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
":has(|)" should be a valid selector: FAIL (Chrome: FAIL, Safari: FAIL)
Comment 4•4 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/18429dd46cdf
https://hg.mozilla.org/mozilla-central/rev/515dfcad6c24
Description
•