Kaynağa Gözat

LibWeb: Properly append attributes to element when creating an Element

The main behavioural difference here is that the full qualified name is
appended to the element, rather than just the local name and value.
Shannon Booth 1 yıl önce
ebeveyn
işleme
e5d45eeeb1

+ 18 - 0
Tests/LibWeb/Text/expected/SVG/svg-href-qualified-name.txt

@@ -0,0 +1,18 @@
+     ---------------
+explicit-xlink-href
+---------------
+localName -> href
+name -> xlink:href
+namespaceURI -> http://www.w3.org/1999/xlink
+ownerElement -> explicit-xlink-href
+prefix -> xlink
+value -> test
+---------------
+implicit-xlink-href
+---------------
+localName -> href
+name -> href
+namespaceURI -> null
+ownerElement -> implicit-xlink-href
+prefix -> null
+value -> test

+ 24 - 0
Tests/LibWeb/Text/input/SVG/svg-href-qualified-name.html

@@ -0,0 +1,24 @@
+<script src="../include.js"></script>
+<svg xmlns="http://www.w3.org/2000/svg">
+    <script id="explicit-xlink-href" xlink:href="test"></script>
+    <script id="implicit-xlink-href" href="test"></script>
+</svg>
+<script id="svg-script-element">
+    function dumpAttribute(elementName) {
+        println("---------------");
+        println(elementName);
+        println("---------------");
+        const attr = document.getElementById(elementName).attributes[1];
+        println(`localName -> ${attr.localName}`);
+        println(`name -> ${attr.name}`);
+        println(`namespaceURI -> ${attr.namespaceURI}`);
+        println(`ownerElement -> ${attr.ownerElement.id}`);
+        println(`prefix -> ${attr.prefix}`);
+        println(`value -> ${attr.value}`);
+    }
+
+    test(() => {
+        dumpAttribute('explicit-xlink-href');
+        dumpAttribute('implicit-xlink-href');
+    });
+</script>

+ 7 - 3
Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp

@@ -13,12 +13,14 @@
 #include <LibWeb/Bindings/MainThreadVM.h>
 #include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
+#include <LibWeb/DOM/Attr.h>
 #include <LibWeb/DOM/Comment.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/DocumentType.h>
 #include <LibWeb/DOM/ElementFactory.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/ProcessingInstruction.h>
+#include <LibWeb/DOM/QualifiedName.h>
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/HTML/CustomElements/CustomElementDefinition.h>
 #include <LibWeb/HTML/EventLoop/EventLoop.h>
@@ -649,6 +651,7 @@ HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_ins
     return adjusted_insertion_location;
 }
 
+// https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token
 JS::NonnullGCPtr<DOM::Element> HTMLParser::create_element_for(HTMLToken const& token, Optional<FlyString> const& namespace_, DOM::Node& intended_parent)
 {
     // FIXME: 1. If the active speculative HTML parser is not null, then return the result of creating a speculative mock element given given namespace, the tag name of the given token, and the attributes of the given token.
@@ -692,9 +695,10 @@ JS::NonnullGCPtr<DOM::Element> HTMLParser::create_element_for(HTMLToken const& t
     auto element = create_element(*document, local_name, namespace_, {}, is_value, will_execute_script).release_value_but_fixme_should_propagate_errors();
 
     // 10. Append each attribute in the given token to element.
-    // FIXME: This isn't the exact `append` the spec is talking about.
-    token.for_each_attribute([&](auto& attribute) {
-        MUST(element->set_attribute(attribute.local_name, attribute.value));
+    token.for_each_attribute([&](auto const& attribute) {
+        DOM::QualifiedName qualified_name { attribute.local_name, attribute.prefix, attribute.namespace_ };
+        auto dom_attribute = realm().heap().allocate<DOM::Attr>(realm(), *document, move(qualified_name), attribute.value, element);
+        element->append_attribute(dom_attribute);
         return IterationDecision::Continue;
     });