summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@gmail.com>2021-07-28 12:34:05 +0100
committerAndreas Kling <kling@serenityos.org>2021-07-31 00:18:11 +0200
commit1b72766e4eeffa6d19b77e9c7c7bd6cff2951bb8 (patch)
tree8a769aef42e3351fd1756f9715063f5ba83a01b0 /Userland/Libraries/LibWeb
parent242c342fadb2e81ee9d02787b7a846174d10c45e (diff)
downloadserenity-1b72766e4eeffa6d19b77e9c7c7bd6cff2951bb8.zip
LibWeb: Fix issues with CSS attribute selector handling
This is three small, related changes: 1. Element::has_attribute() now returns true if the attribute exists but has no value. (eg, `<div foo />` -> `has_attribute("foo")`) 2. SelectorEngine::matches_attribute() now makes sure there is a first segment before comparing it, fixing a crash. 3. CSS::Parser now converts attribute names in attribute selectors to lowercase, to match the expectations of the rest of the system. Converting to lowercase is not always correct, depending on language, but since we only currently support HTML, and that expects them to be case-insensitive, it is fine for now.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp7
-rw-r--r--Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp6
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.h2
3 files changed, 11 insertions, 4 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 6d787eeaef..0a00a88a7b 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -416,7 +416,12 @@ Result<Selector::SimpleSelector, Parser::SelectorParsingResult> Parser::parse_si
.type = Selector::SimpleSelector::Type::Attribute,
.attribute = {
.match_type = Selector::SimpleSelector::Attribute::MatchType::HasAttribute,
- .name = attribute_part.token().ident(),
+ // FIXME: Case-sensitivity is defined by the document language.
+ // HTML is insensitive with attribute names, and our code generally assumes
+ // they are converted to lowercase, so we do that here too. If we want to be
+ // correct with XML later, we'll need to keep the original case and then do
+ // a case-insensitive compare later.
+ .name = attribute_part.token().ident().to_lowercase_string(),
}
};
diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
index 026dee981b..d614a3d3d4 100644
--- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
+++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
@@ -40,9 +40,11 @@ static bool matches_attribute(CSS::Selector::SimpleSelector::Attribute const& at
case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsString:
return element.attribute(attribute.name).contains(attribute.value);
break;
- case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment:
- return element.attribute(attribute.name).split_view('-').first() == attribute.value;
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: {
+ auto segments = element.attribute(attribute.name).split_view('-');
+ return !segments.is_empty() && segments.first() == attribute.value;
break;
+ }
case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString:
return element.attribute(attribute.name).starts_with(attribute.value);
break;
diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h
index c4b360f84e..3878cc433d 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.h
+++ b/Userland/Libraries/LibWeb/DOM/Element.h
@@ -45,7 +45,7 @@ public:
// NOTE: This is for the JS bindings
const FlyString& namespace_uri() const { return namespace_(); }
- bool has_attribute(const FlyString& name) const { return !attribute(name).is_null(); }
+ bool has_attribute(const FlyString& name) const { return find_attribute(name) != nullptr; }
bool has_attributes() const { return !m_attributes.is_empty(); }
String attribute(const FlyString& name) const;
String get_attribute(const FlyString& name) const { return attribute(name); }