summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2023-05-15 10:08:13 +0200
committerAndreas Kling <kling@serenityos.org>2023-05-15 14:08:20 +0200
commit20e2c9a7dd207bfb3575933b41edc1a905baebb0 (patch)
treec9f581a069235bc92d6580b40abd08cb5f937e9a /Userland
parent990e7219d655d39b76105ddd2678966c89be1ad3 (diff)
downloadserenity-20e2c9a7dd207bfb3575933b41edc1a905baebb0.zip
LibWeb: Cache state of the contenteditable attribute on HTMLElement
Instead of recomputing the state whenever someone asks for it, we now cache it when the attribute is added/changed/removed. Before this change, HTMLElement::is_editable() was 6.5% of CPU time when furiously resizing Hacker News. After, it's less than 0.5%. :^)
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLElement.cpp38
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLElement.h3
2 files changed, 25 insertions, 16 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp
index 817b364655..6dc2953e0b 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp
@@ -77,22 +77,9 @@ void HTMLElement::set_dir(DeprecatedString const& dir)
MUST(set_attribute(HTML::AttributeNames::dir, dir));
}
-HTMLElement::ContentEditableState HTMLElement::content_editable_state() const
-{
- auto contenteditable = attribute(HTML::AttributeNames::contenteditable);
- // "true", an empty string or a missing value map to the "true" state.
- if ((!contenteditable.is_null() && contenteditable.is_empty()) || contenteditable.equals_ignoring_ascii_case("true"sv))
- return ContentEditableState::True;
- // "false" maps to the "false" state.
- if (contenteditable.equals_ignoring_ascii_case("false"sv))
- return ContentEditableState::False;
- // Having no such attribute or an invalid value maps to the "inherit" state.
- return ContentEditableState::Inherit;
-}
-
bool HTMLElement::is_editable() const
{
- switch (content_editable_state()) {
+ switch (m_content_editable_state) {
case ContentEditableState::True:
return true;
case ContentEditableState::False:
@@ -106,7 +93,7 @@ bool HTMLElement::is_editable() const
DeprecatedString HTMLElement::content_editable() const
{
- switch (content_editable_state()) {
+ switch (m_content_editable_state) {
case ContentEditableState::True:
return "true";
case ContentEditableState::False:
@@ -242,6 +229,19 @@ void HTMLElement::parse_attribute(DeprecatedFlyString const& name, DeprecatedStr
{
Element::parse_attribute(name, value);
+ if (name == HTML::AttributeNames::contenteditable) {
+ if ((!value.is_null() && value.is_empty()) || value.equals_ignoring_ascii_case("true"sv)) {
+ // "true", an empty string or a missing value map to the "true" state.
+ m_content_editable_state = ContentEditableState::True;
+ } else if (value.equals_ignoring_ascii_case("false"sv)) {
+ // "false" maps to the "false" state.
+ m_content_editable_state = ContentEditableState::False;
+ } else {
+ // Having no such attribute or an invalid value maps to the "inherit" state.
+ m_content_editable_state = ContentEditableState::Inherit;
+ }
+ }
+
// 1. If namespace is not null, or localName is not the name of an event handler content attribute on element, then return.
// FIXME: Add the namespace part once we support attribute namespaces.
#undef __ENUMERATE
@@ -253,6 +253,14 @@ void HTMLElement::parse_attribute(DeprecatedFlyString const& name, DeprecatedStr
#undef __ENUMERATE
}
+void HTMLElement::did_remove_attribute(DeprecatedFlyString const& name)
+{
+ Base::did_remove_attribute(name);
+ if (name == HTML::AttributeNames::contenteditable) {
+ m_content_editable_state = ContentEditableState::Inherit;
+ }
+}
+
// https://html.spec.whatwg.org/multipage/interaction.html#dom-focus
void HTMLElement::focus()
{
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.h b/Userland/Libraries/LibWeb/HTML/HTMLElement.h
index 4bfc1c6a96..86bda36d39 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.h
@@ -67,6 +67,7 @@ protected:
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
virtual void parse_attribute(DeprecatedFlyString const& name, DeprecatedString const& value) override;
+ virtual void did_remove_attribute(DeprecatedFlyString const& name) override;
virtual void visit_edges(Cell::Visitor&) override;
@@ -81,7 +82,7 @@ private:
False,
Inherit,
};
- ContentEditableState content_editable_state() const;
+ ContentEditableState m_content_editable_state { ContentEditableState::Inherit };
JS::GCPtr<DOMStringMap> m_dataset;