mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 13:00:29 +03:00
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%. :^)
This commit is contained in:
parent
990e7219d6
commit
20e2c9a7dd
Notes:
sideshowbarker
2024-07-16 22:17:03 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/20e2c9a7dd Pull-request: https://github.com/SerenityOS/serenity/pull/18848
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user