diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 9014a1d99f2..80f3c9284cf 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -2276,7 +2276,7 @@ void Document::adopt_node(Node& node) // 1. For each inclusiveDescendant in node’s shadow-including inclusive descendants: node.for_each_shadow_including_inclusive_descendant([&](DOM::Node& inclusive_descendant) { // 1. Set inclusiveDescendant’s node document to document. - inclusive_descendant.set_document({}, *this); + inclusive_descendant.set_document(Badge {}, *this); // FIXME: 2. If inclusiveDescendant is an element, then set the node document of each attribute in inclusiveDescendant’s // attribute list to document. diff --git a/Libraries/LibWeb/DOM/NamedNodeMap.cpp b/Libraries/LibWeb/DOM/NamedNodeMap.cpp index 11056826d3d..ce66fc971eb 100644 --- a/Libraries/LibWeb/DOM/NamedNodeMap.cpp +++ b/Libraries/LibWeb/DOM/NamedNodeMap.cpp @@ -237,17 +237,23 @@ void NamedNodeMap::replace_attribute(Attr& old_attribute, Attr& new_attribute, s { VERIFY(old_attribute.owner_element()); - // 1. Replace oldAttr by newAttr in oldAttr’s element’s attribute list. + // 1. Let element be oldAttribute’s element. + auto* element = old_attribute.owner_element(); + + // 2. Replace oldAttribute by newAttribute in element’s attribute list. m_attributes.remove(old_attribute_index); m_attributes.insert(old_attribute_index, new_attribute); - // 2. Set newAttr’s element to oldAttr’s element. - new_attribute.set_owner_element(old_attribute.owner_element()); + // 3. Set newAttribute’s element to element. + new_attribute.set_owner_element(element); - // 3. Set oldAttr’s element to null. + // 4. Set newAttribute’s node document to element’s node document. + new_attribute.set_document(Badge {}, element->document()); + + // 5. Set oldAttribute’s element to null. old_attribute.set_owner_element(nullptr); - // 4. Handle attribute changes for oldAttr with newAttr’s element, oldAttr’s value, and newAttr’s value. + // 6. Handle attribute changes for oldAttribute with element, oldAttribute’s value, and newAttribute’s value. old_attribute.handle_attribute_changes(*new_attribute.owner_element(), old_attribute.value(), new_attribute.value()); } @@ -260,7 +266,10 @@ void NamedNodeMap::append_attribute(Attr& attribute) // 2. Set attribute’s element to element. attribute.set_owner_element(&associated_element()); - // 3. Handle attribute changes for attribute with element, null, and attribute’s value. + // 3. Set attribute’s node document to element’s node document. + attribute.set_document(Badge {}, associated_element().document()); + + // 4. Handle attribute changes for attribute with element, null, and attribute’s value. attribute.handle_attribute_changes(associated_element(), {}, attribute.value()); } diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index 9e348595957..ae4814e90da 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -1281,6 +1281,11 @@ void Node::set_document(Badge, Document& document) set_document(document); } +void Node::set_document(Badge, Document& document) +{ + set_document(document); +} + void Node::set_document(Document& document) { if (m_document.ptr() == &document) diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index 3b9e369b94c..f659cd5333d 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -302,6 +302,7 @@ public: void invalidate_style(StyleInvalidationReason, Vector const&, StyleInvalidationOptions); void set_document(Badge, Document&); + void set_document(Badge, Document&); virtual EventTarget* get_parent(Event const&) override; diff --git a/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.txt b/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.txt new file mode 100644 index 00000000000..9052945dd36 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.txt @@ -0,0 +1,7 @@ +Harness status: OK + +Found 2 tests + +2 Pass +Pass Moving an attribute between documents +Pass Replacing an attribute across documents \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.html b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.html new file mode 100644 index 00000000000..dadd4af2848 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.html @@ -0,0 +1,8 @@ + + + + + + +
+ diff --git a/Tests/LibWeb/Text/input/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.js b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.js new file mode 100644 index 00000000000..af2090d7d39 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/attributes-namednodemap-cross-document.window.js @@ -0,0 +1,31 @@ +"use strict"; + +test(() => { + const element = document.createElement("div"); + element.setAttribute("x", "first"); + const attribute = element.attributes[0]; + assert_equals(attribute.ownerDocument, document); + + const otherDocument = new Document(); + const otherElement = otherDocument.createElement("other"); + assert_throws_dom("InUseAttributeError", () => otherElement.attributes.setNamedItem(attribute)); + + element.removeAttribute("x"); + otherElement.attributes.setNamedItem(attribute); + assert_equals(attribute.ownerDocument, otherDocument); +}, "Moving an attribute between documents"); + +test(() => { + const element = document.createElement("div"); + element.setAttribute("x", "first"); + const attribute = element.attributes[0]; + element.removeAttribute("x"); + + const otherDocument = new Document(); + const otherElement = otherDocument.createElement("other"); + otherElement.setAttribute("x", "second"); + + otherElement.attributes.setNamedItem(attribute); + assert_equals(attribute.ownerDocument, otherDocument); + assert_equals(otherElement.getAttribute("x"), "first"); +}, "Replacing an attribute across documents");