diff options
author | Luke Wilde <lukew@serenityos.org> | 2022-07-11 16:40:01 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-07-11 22:35:08 +0200 |
commit | a718c62c01aeb073da446f0983e5dcec0d19212e (patch) | |
tree | cc6a9f877be378361a8e774d50190b978c470dcd | |
parent | 1ca8782c99ac5c0578b759d7a331673508cedc54 (diff) | |
download | serenity-a718c62c01aeb073da446f0983e5dcec0d19212e.zip |
LibWeb: Implement all "attributes" mutation records for MutationObserver
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Attribute.cpp | 36 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Attribute.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp | 25 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/NamedNodeMap.h | 2 |
4 files changed, 62 insertions, 6 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.cpp b/Userland/Libraries/LibWeb/DOM/Attribute.cpp index 77b5ebb1e7..da29d7cdc0 100644 --- a/Userland/Libraries/LibWeb/DOM/Attribute.cpp +++ b/Userland/Libraries/LibWeb/DOM/Attribute.cpp @@ -7,6 +7,8 @@ #include <LibWeb/DOM/Attribute.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Element.h> +#include <LibWeb/DOM/MutationType.h> +#include <LibWeb/DOM/StaticNodeList.h> namespace Web::DOM { @@ -23,6 +25,11 @@ Attribute::Attribute(Document& document, FlyString local_name, String value, Ele { } +Element* Attribute::owner_element() +{ + return m_owner_element; +} + Element const* Attribute::owner_element() const { return m_owner_element; @@ -33,4 +40,33 @@ void Attribute::set_owner_element(Element const* owner_element) m_owner_element = owner_element; } +// https://dom.spec.whatwg.org/#set-an-existing-attribute-value +void Attribute::set_value(String value) +{ + // 1. If attributeās element is null, then set attributeās value to value. + if (!owner_element()) { + m_value = move(value); + return; + } + + // 2. Otherwise, change attribute to value. + // https://dom.spec.whatwg.org/#concept-element-attributes-change + // 1. Handle attribute changes for attribute with attributeās element, attributeās value, and value. + handle_attribute_changes(*owner_element(), m_value, value); + + // 2. Set attributeās value to value. + m_value = move(value); +} + +// https://dom.spec.whatwg.org/#handle-attribute-changes +void Attribute::handle_attribute_changes(Element& element, String const& old_value, [[maybe_unused]] String const& new_value) +{ + // 1. Queue a mutation record of "attributes" for element with attributeās local name, attributeās namespace, oldValue, Ā« Ā», Ā« Ā», null, and null. + element.queue_mutation_record(MutationType::attributes, local_name(), namespace_uri(), old_value, StaticNodeList::create({}), StaticNodeList::create({}), nullptr, nullptr); + + // FIXME: 2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing attributeās local name, oldValue, newValue, and attributeās namespace. + + // FIXME: 3. Run the attribute change steps with element, attributeās local name, oldValue, newValue, and attributeās namespace. +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.h b/Userland/Libraries/LibWeb/DOM/Attribute.h index 5019a25926..1431d3083b 100644 --- a/Userland/Libraries/LibWeb/DOM/Attribute.h +++ b/Userland/Libraries/LibWeb/DOM/Attribute.h @@ -30,14 +30,17 @@ public: String const& name() const { return m_qualified_name.as_string(); } String const& value() const { return m_value; } - void set_value(String value) { m_value = move(value); } + void set_value(String value); + Element* owner_element(); Element const* owner_element() const; void set_owner_element(Element const* owner_element); // Always returns true: https://dom.spec.whatwg.org/#dom-attr-specified constexpr bool specified() const { return true; } + void handle_attribute_changes(Element&, String const& old_value, String const& new_value); + private: Attribute(Document&, FlyString local_name, String value, Element const*); diff --git a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp index fe049c55c4..30f4d21574 100644 --- a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp +++ b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp @@ -154,8 +154,8 @@ ExceptionOr<Attribute const*> NamedNodeMap::set_attribute(Attribute& attribute) void NamedNodeMap::replace_attribute(Attribute& old_attribute, Attribute& new_attribute, size_t old_attribute_index) { // 1. Handle attribute changes for oldAttr with oldAttrās element, oldAttrās value, and newAttrās value. - // FIXME: The steps to handle an attribute change deal with mutation records and custom element states. - // Once those are supported, implement these steps: https://dom.spec.whatwg.org/#handle-attribute-changes + VERIFY(old_attribute.owner_element()); + old_attribute.handle_attribute_changes(*old_attribute.owner_element(), old_attribute.value(), new_attribute.value()); // 2. Replace oldAttr by newAttr in oldAttrās elementās attribute list. m_attributes.remove(old_attribute_index); @@ -172,8 +172,7 @@ void NamedNodeMap::replace_attribute(Attribute& old_attribute, Attribute& new_at void NamedNodeMap::append_attribute(Attribute& attribute) { // 1. Handle attribute changes for attribute with element, null, and attributeās value. - // FIXME: The steps to handle an attribute change deal with mutation records and custom element states. - // Once those are supported, implement these steps: https://dom.spec.whatwg.org/#handle-attribute-changes + attribute.handle_attribute_changes(associated_element(), {}, attribute.value()); // 2. Append attribute to elementās attribute list. m_attributes.append(attribute); @@ -182,6 +181,22 @@ void NamedNodeMap::append_attribute(Attribute& attribute) attribute.set_owner_element(&associated_element()); } +// https://dom.spec.whatwg.org/#concept-element-attributes-remove +void NamedNodeMap::remove_attribute_at_index(size_t attribute_index) +{ + NonnullRefPtr<Attribute> attribute = m_attributes.at(attribute_index); + + // 1. Handle attribute changes for attribute with attributeās element, attributeās value, and null. + VERIFY(attribute->owner_element()); + attribute->handle_attribute_changes(*attribute->owner_element(), attribute->value(), {}); + + // 2. Remove attribute from attributeās elementās attribute list. + m_attributes.remove(attribute_index); + + // 3. Set attributeās element to null. + attribute->set_owner_element(nullptr); +} + // https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-name Attribute const* NamedNodeMap::remove_attribute(StringView qualified_name) { @@ -192,7 +207,7 @@ Attribute const* NamedNodeMap::remove_attribute(StringView qualified_name) // 2. If attr is non-null, then remove attr. if (attribute) - m_attributes.remove(item_index); + remove_attribute_at_index(item_index); // 3. Return attr. return attribute; diff --git a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h index 510475bcc1..c13be70230 100644 --- a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h +++ b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.h @@ -55,6 +55,8 @@ private: Element& associated_element() { return ref_count_target(); } Element const& associated_element() const { return ref_count_target(); } + void remove_attribute_at_index(size_t attribute_index); + NonnullRefPtrVector<Attribute> m_attributes; }; |