diff options
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Selector.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Selector.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/SelectorEngine.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Dump.cpp | 3 |
6 files changed, 23 insertions, 12 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 59d1a7f173..0b7d0cf58a 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -479,6 +479,8 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Root); if (pseudo_name.equals_ignoring_ascii_case("visited"sv)) return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Visited); + if (pseudo_name.equals_ignoring_ascii_case("scope"sv)) + return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Scope); // Single-colon syntax allowed for ::after, ::before, ::first-letter and ::first-line for compatibility. // https://www.w3.org/TR/selectors/#pseudo-element-syntax diff --git a/Userland/Libraries/LibWeb/CSS/Selector.cpp b/Userland/Libraries/LibWeb/CSS/Selector.cpp index 25c13c9ac1..d0c6636218 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.cpp +++ b/Userland/Libraries/LibWeb/CSS/Selector.cpp @@ -227,6 +227,7 @@ ErrorOr<String> Selector::SimpleSelector::serialize() const case Selector::SimpleSelector::PseudoClass::Type::Enabled: case Selector::SimpleSelector::PseudoClass::Type::Checked: case Selector::SimpleSelector::PseudoClass::Type::Active: + case Selector::SimpleSelector::PseudoClass::Type::Scope: // If the pseudo-class does not accept arguments append ":" (U+003A), followed by the name of the pseudo-class, to s. TRY(s.try_append(':')); TRY(s.try_append(pseudo_class_name(pseudo_class.type))); diff --git a/Userland/Libraries/LibWeb/CSS/Selector.h b/Userland/Libraries/LibWeb/CSS/Selector.h index dd1da6cdbd..eef67017ee 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.h +++ b/Userland/Libraries/LibWeb/CSS/Selector.h @@ -111,6 +111,7 @@ public: Where, Active, Lang, + Scope, }; Type type; @@ -292,6 +293,8 @@ constexpr StringView pseudo_class_name(Selector::SimpleSelector::PseudoClass::Ty return "where"sv; case Selector::SimpleSelector::PseudoClass::Type::Lang: return "lang"sv; + case Selector::SimpleSelector::PseudoClass::Type::Scope: + return "scope"sv; } VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 92e8c1313f..8c8505c2c9 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -202,7 +202,7 @@ static inline DOM::Element const* next_sibling_with_same_tag_name(DOM::Element c return nullptr; } -static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClass const& pseudo_class, DOM::Element const& element) +static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClass const& pseudo_class, DOM::Element const& element, JS::GCPtr<DOM::ParentNode const> scope) { switch (pseudo_class.type) { case CSS::Selector::SimpleSelector::PseudoClass::Type::Link: @@ -245,6 +245,8 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla } case CSS::Selector::SimpleSelector::PseudoClass::Type::Root: return is<HTML::HTMLHtmlElement>(element); + case CSS::Selector::SimpleSelector::PseudoClass::Type::Scope: + return scope ? &element == scope : is<HTML::HTMLHtmlElement>(element); case CSS::Selector::SimpleSelector::PseudoClass::Type::FirstOfType: return !previous_sibling_with_same_tag_name(element); case CSS::Selector::SimpleSelector::PseudoClass::Type::LastOfType: @@ -373,7 +375,7 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla return false; } -static inline bool matches(CSS::Selector::SimpleSelector const& component, DOM::Element const& element) +static inline bool matches(CSS::Selector::SimpleSelector const& component, DOM::Element const& element, JS::GCPtr<DOM::ParentNode const> scope) { switch (component.type) { case CSS::Selector::SimpleSelector::Type::Universal: @@ -390,7 +392,7 @@ static inline bool matches(CSS::Selector::SimpleSelector const& component, DOM:: case CSS::Selector::SimpleSelector::Type::Attribute: return matches_attribute(component.attribute(), element); case CSS::Selector::SimpleSelector::Type::PseudoClass: - return matches_pseudo_class(component.pseudo_class(), element); + return matches_pseudo_class(component.pseudo_class(), element, scope); case CSS::Selector::SimpleSelector::Type::PseudoElement: // Pseudo-element matching/not-matching is handled in the top level matches(). return true; @@ -399,11 +401,11 @@ static inline bool matches(CSS::Selector::SimpleSelector const& component, DOM:: } } -static inline bool matches(CSS::Selector const& selector, int component_list_index, DOM::Element const& element) +static inline bool matches(CSS::Selector const& selector, int component_list_index, DOM::Element const& element, JS::GCPtr<DOM::ParentNode const> scope) { auto& relative_selector = selector.compound_selectors()[component_list_index]; for (auto& simple_selector : relative_selector.simple_selectors) { - if (!matches(simple_selector, element)) + if (!matches(simple_selector, element, scope)) return false; } switch (relative_selector.combinator) { @@ -414,7 +416,7 @@ static inline bool matches(CSS::Selector const& selector, int component_list_ind for (auto* ancestor = element.parent(); ancestor; ancestor = ancestor->parent()) { if (!is<DOM::Element>(*ancestor)) continue; - if (matches(selector, component_list_index - 1, static_cast<DOM::Element const&>(*ancestor))) + if (matches(selector, component_list_index - 1, static_cast<DOM::Element const&>(*ancestor), scope)) return true; } return false; @@ -422,16 +424,16 @@ static inline bool matches(CSS::Selector const& selector, int component_list_ind VERIFY(component_list_index != 0); if (!element.parent() || !is<DOM::Element>(*element.parent())) return false; - return matches(selector, component_list_index - 1, static_cast<DOM::Element const&>(*element.parent())); + return matches(selector, component_list_index - 1, static_cast<DOM::Element const&>(*element.parent()), scope); case CSS::Selector::Combinator::NextSibling: VERIFY(component_list_index != 0); if (auto* sibling = element.previous_element_sibling()) - return matches(selector, component_list_index - 1, *sibling); + return matches(selector, component_list_index - 1, *sibling, scope); return false; case CSS::Selector::Combinator::SubsequentSibling: VERIFY(component_list_index != 0); for (auto* sibling = element.previous_element_sibling(); sibling; sibling = sibling->previous_element_sibling()) { - if (matches(selector, component_list_index - 1, *sibling)) + if (matches(selector, component_list_index - 1, *sibling, scope)) return true; } return false; @@ -441,14 +443,14 @@ static inline bool matches(CSS::Selector const& selector, int component_list_ind VERIFY_NOT_REACHED(); } -bool matches(CSS::Selector const& selector, DOM::Element const& element, Optional<CSS::Selector::PseudoElement> pseudo_element) +bool matches(CSS::Selector const& selector, DOM::Element const& element, Optional<CSS::Selector::PseudoElement> pseudo_element, JS::GCPtr<DOM::ParentNode const> scope) { VERIFY(!selector.compound_selectors().is_empty()); if (pseudo_element.has_value() && selector.pseudo_element() != pseudo_element) return false; if (!pseudo_element.has_value() && selector.pseudo_element().has_value()) return false; - return matches(selector, selector.compound_selectors().size() - 1, element); + return matches(selector, selector.compound_selectors().size() - 1, element, scope); } } diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.h b/Userland/Libraries/LibWeb/CSS/SelectorEngine.h index e39fa9cb8a..c92f06a684 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.h +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.h @@ -11,6 +11,6 @@ namespace Web::SelectorEngine { -bool matches(CSS::Selector const&, DOM::Element const&, Optional<CSS::Selector::PseudoElement> = {}); +bool matches(CSS::Selector const&, DOM::Element const&, Optional<CSS::Selector::PseudoElement> = {}, JS::GCPtr<DOM::ParentNode const> scope = {}); } diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index 666924b989..147e0491c1 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -456,6 +456,9 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector) case CSS::Selector::SimpleSelector::PseudoClass::Type::Lang: pseudo_class_description = "Lang"; break; + case CSS::Selector::SimpleSelector::PseudoClass::Type::Scope: + pseudo_class_description = "Scope"; + break; } builder.appendff(" pseudo_class={}", pseudo_class_description); |