diff options
author | Andreas Kling <kling@serenityos.org> | 2023-05-15 10:08:13 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-15 14:08:20 +0200 |
commit | 20e2c9a7dd207bfb3575933b41edc1a905baebb0 (patch) | |
tree | c9f581a069235bc92d6580b40abd08cb5f937e9a /Userland | |
parent | 990e7219d655d39b76105ddd2678966c89be1ad3 (diff) | |
download | serenity-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.cpp | 38 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLElement.h | 3 |
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; |