diff --git a/Libraries/LibWeb/CSS/PseudoClasses.json b/Libraries/LibWeb/CSS/PseudoClasses.json index fce688f5b8d..6a187d0f8de 100644 --- a/Libraries/LibWeb/CSS/PseudoClasses.json +++ b/Libraries/LibWeb/CSS/PseudoClasses.json @@ -155,6 +155,9 @@ "stalled": { "argument": "" }, + "state": { + "argument": "" + }, "suboptimal-value": { "argument": "" }, diff --git a/Libraries/LibWeb/CSS/Selector.cpp b/Libraries/LibWeb/CSS/Selector.cpp index 711c4bdf5f4..c8f48b2ddd0 100644 --- a/Libraries/LibWeb/CSS/Selector.cpp +++ b/Libraries/LibWeb/CSS/Selector.cpp @@ -61,6 +61,7 @@ static bool can_selector_use_fast_matches(Selector const& selector) PseudoClass::LocalLink, PseudoClass::OnlyChild, PseudoClass::Root, + PseudoClass::State, PseudoClass::Visited)) return false; } else if (!first_is_one_of(simple_selector.type, diff --git a/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Libraries/LibWeb/CSS/SelectorEngine.cpp index 5eb13d3a89a..74dfb7378b7 100644 --- a/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1059,6 +1060,15 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla return false; } + case CSS::PseudoClass::State: { + // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-custom + // The :state(identifier) pseudo-class must match all custom elements whose states set's set entries contains identifier. + if (!element.is_custom()) + return false; + if (auto* custom_state_set = element.custom_state_set()) + return custom_state_set->has_state(pseudo_class.ident->string_value); + return false; + } } return false; diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/selectors/invalidation/state-in-has.txt b/Tests/LibWeb/Text/expected/wpt-import/css/selectors/invalidation/state-in-has.txt index 5f8d0f8dcaf..5d0b2114781 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/selectors/invalidation/state-in-has.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/selectors/invalidation/state-in-has.txt @@ -2,5 +2,5 @@ Harness status: OK Found 1 tests -1 Fail -Fail Test :has() invalidation with :state() pseudo-classes \ No newline at end of file +1 Pass +Pass Test :has() invalidation with :state() pseudo-classes \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector-nth-of.txt b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector-nth-of.txt new file mode 100644 index 00000000000..e07684bfcaf --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector-nth-of.txt @@ -0,0 +1,8 @@ +Harness status: OK + +Found 3 tests + +3 Pass +Pass state selector has influence on nth-of when state is applied +Pass state selector only applies on given ident +Pass style is invalided on clear() \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector-shadow-dom.txt b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector-shadow-dom.txt new file mode 100644 index 00000000000..6467df1fb29 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector-shadow-dom.txt @@ -0,0 +1,8 @@ +Harness status: OK + +Found 3 tests + +3 Pass +Pass state selector has no influence when state is not applied +Pass state selector has influence when state is applied +Pass state selector only applies on given ident \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector.txt b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector.txt new file mode 100644 index 00000000000..cd68de4f3b1 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-css-selector.txt @@ -0,0 +1,15 @@ +Harness status: OK + +Found 10 tests + +10 Pass +Pass state selector has no influence when state is not applied +Pass state selector has no influence on sibling selectors when not applied +Pass state selector has influence when state is applied +Pass state selector influences siblings when state is applied +Pass state selector influences has() when state is applied +Pass state selector only applies on given ident +Pass state selector only applies to siblings on given ident +Pass state selector only applies to has() on given ident +Pass states added multiple times counts as one +Pass style is invalided on clear() \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-pseudo-class.txt b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-pseudo-class.txt new file mode 100644 index 00000000000..ccaf82cb301 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/state/state-pseudo-class.txt @@ -0,0 +1,14 @@ +Harness status: OK + +Found 8 tests + +6 Pass +2 Fail +Pass :state() parsing passes +Pass :state() parsing failures +Pass deprecated :--state parsing failures +Fail :state(foo) serialization +Pass :state(foo) in simple cases +Pass :state(foo) and other pseudo classes +Fail :state(foo) and ::part() +Pass :state(foo) and :host() \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector-nth-of.html b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector-nth-of.html new file mode 100644 index 00000000000..e549bc25198 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector-nth-of.html @@ -0,0 +1,92 @@ + + + + + + + :state() css selector applies to nth-of selectors + + + + + + First Element +

First Sibling

+ Second Element +

Second Sibling

+ + + + diff --git a/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector-shadow-dom.html b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector-shadow-dom.html new file mode 100644 index 00000000000..312319511e9 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector-shadow-dom.html @@ -0,0 +1,74 @@ + + + + + + + + :state() css selector applies in shadow roots + + + + + + I should be green + + + + diff --git a/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector.html b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector.html new file mode 100644 index 00000000000..a8160e0d3d0 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-css-selector.html @@ -0,0 +1,130 @@ + + + + + + + + :state() css selector applies + + + + + + I should be green +

I should be blue

+

I should be blue

+ + + + diff --git a/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-pseudo-class.html b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-pseudo-class.html new file mode 100644 index 00000000000..247047f1022 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/custom-elements/state/state-pseudo-class.html @@ -0,0 +1,146 @@ + + + + + + + +