Bladeren bron

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 jaar geleden
bovenliggende
commit
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/Bindings/MainThreadVM.h>
 #include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
 #include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
+#include <LibWeb/DOM/Attr.h>
 #include <LibWeb/DOM/Comment.h>
 #include <LibWeb/DOM/Comment.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/DocumentType.h>
 #include <LibWeb/DOM/DocumentType.h>
 #include <LibWeb/DOM/ElementFactory.h>
 #include <LibWeb/DOM/ElementFactory.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/ProcessingInstruction.h>
 #include <LibWeb/DOM/ProcessingInstruction.h>
+#include <LibWeb/DOM/QualifiedName.h>
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/HTML/CustomElements/CustomElementDefinition.h>
 #include <LibWeb/HTML/CustomElements/CustomElementDefinition.h>
 #include <LibWeb/HTML/EventLoop/EventLoop.h>
 #include <LibWeb/HTML/EventLoop/EventLoop.h>
@@ -649,6 +651,7 @@ HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_ins
     return adjusted_insertion_location;
     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)
 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.
     // 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();
     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.
     // 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;
         return IterationDecision::Continue;
     });
     });