summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-26 23:07:19 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-26 23:07:19 +0200
commit5069d380a8678062d9ca6f5127a8cadb545dbb3e (patch)
treea3818eef26967e165ca07ca160e6aa3208aaad03 /Libraries/LibWeb
parent16accb71a35ad4c947cd9fefc6dc97c2a1ce3adb (diff)
downloadserenity-5069d380a8678062d9ca6f5127a8cadb545dbb3e.zip
LibWeb: Let Element cache its list of classes
Instead of string splitting every time you call Element::has_class(), we now split the "class" attribute value when it changes, and cache the individual classes as FlyStrings in Element::m_classes. This makes has_class() significantly faster and moves the pain point of selector matching somewhere else.
Diffstat (limited to 'Libraries/LibWeb')
-rw-r--r--Libraries/LibWeb/DOM/Element.cpp20
-rw-r--r--Libraries/LibWeb/DOM/Element.h4
2 files changed, 15 insertions, 9 deletions
diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp
index 85fbfc90dc..6b546b97c3 100644
--- a/Libraries/LibWeb/DOM/Element.cpp
+++ b/Libraries/LibWeb/DOM/Element.cpp
@@ -97,14 +97,10 @@ void Element::set_attributes(Vector<Attribute>&& attributes)
parse_attribute(attribute.name(), attribute.value());
}
-bool Element::has_class(const StringView& class_name) const
+bool Element::has_class(const FlyString& class_name) const
{
- auto value = attribute("class");
- if (value.is_empty())
- return false;
- auto parts = value.split_view(' ');
- for (auto& part : parts) {
- if (part == class_name)
+ for (auto& class_ : m_classes) {
+ if (class_ == class_name)
return true;
}
return false;
@@ -140,8 +136,16 @@ RefPtr<LayoutNode> Element::create_layout_node(const StyleProperties* parent_sty
return adopt(*new LayoutInline(*this, move(style)));
}
-void Element::parse_attribute(const FlyString&, const String&)
+void Element::parse_attribute(const FlyString& name, const String& value)
{
+ if (name == "class") {
+ auto new_classes = value.split_view(' ');
+ m_classes.clear();
+ m_classes.ensure_capacity(new_classes.size());
+ for (auto& new_class : new_classes) {
+ m_classes.unchecked_append(new_class);
+ }
+ }
}
enum class StyleDifference {
diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h
index 70c9d83f6b..7fbf3ab394 100644
--- a/Libraries/LibWeb/DOM/Element.h
+++ b/Libraries/LibWeb/DOM/Element.h
@@ -58,7 +58,7 @@ public:
callback(attribute.name(), attribute.value());
}
- bool has_class(const StringView&) const;
+ bool has_class(const FlyString&) const;
virtual void apply_presentational_hints(StyleProperties&) const { }
virtual void parse_attribute(const FlyString& name, const String& value);
@@ -86,6 +86,8 @@ private:
Vector<Attribute> m_attributes;
RefPtr<StyleProperties> m_resolved_style;
+
+ Vector<FlyString> m_classes;
};
template<>