Browse Source

LibWeb: Add a partial implementation of Element.setAttributeNS()

This implementation does some of the required validation and then passes
through the localName and value to Element.setAttribute().
Andreas Kling 3 years ago
parent
commit
e2c71b6725

+ 57 - 0
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -97,6 +97,63 @@ ExceptionOr<void> Element::set_attribute(const FlyString& name, const String& va
     return {};
 }
 
+// https://dom.spec.whatwg.org/#validate-and-extract
+static ExceptionOr<QualifiedName> validate_and_extract(FlyString namespace_, FlyString qualified_name)
+{
+    // 1. If namespace is the empty string, then set it to null.
+    if (namespace_.is_empty())
+        namespace_ = {};
+
+    // FIXME: 2. Validate qualifiedName.
+
+    // 3. Let prefix be null.
+    FlyString prefix = {};
+
+    // 4. Let localName be qualifiedName.
+    auto local_name = qualified_name;
+
+    // 5. If qualifiedName contains a U+003A (:), then strictly split the string on it and set prefix to the part before and localName to the part after.
+    if (qualified_name.view().contains(':')) {
+        auto parts = qualified_name.view().split_view(':');
+        // FIXME: Handle parts > 2
+        prefix = parts[0];
+        local_name = parts[1];
+    }
+
+    // 6. If prefix is non-null and namespace is null, then throw a "NamespaceError" DOMException.
+    if (!prefix.is_null() && namespace_.is_null())
+        return NamespaceError::create("Prefix is non-null and namespace is null.");
+
+    // 7. If prefix is "xml" and namespace is not the XML namespace, then throw a "NamespaceError" DOMException.
+    if (prefix == "xml"sv && namespace_ != Namespace::XML)
+        return NamespaceError::create("Prefix is 'xml' and namespace is not the XML namespace.");
+
+    // 8. If either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace, then throw a "NamespaceError" DOMException.
+    if ((qualified_name == "xmlns"sv || prefix == "xmlns"sv) && namespace_ != Namespace::XMLNS)
+        return NamespaceError::create("Either qualifiedName or prefix is 'xmlns' and namespace is not the XMLNS namespace.");
+
+    // 9. If namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns", then throw a "NamespaceError" DOMException.
+    if (namespace_ == Namespace::XMLNS && !(qualified_name == "xmlns"sv || prefix == "xmlns"sv))
+        return NamespaceError::create("Namespace is the XMLNS namespace and neither qualifiedName nor prefix is 'xmlns'.");
+
+    // 10. Return namespace, prefix, and localName.
+    return QualifiedName { namespace_, prefix, local_name };
+}
+
+// https://dom.spec.whatwg.org/#dom-element-setattributens
+ExceptionOr<void> Element::set_attribute_ns(FlyString const& namespace_, FlyString const& qualified_name, String const& value)
+{
+    // 1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract.
+    auto result = validate_and_extract(namespace_, qualified_name);
+    if (result.is_exception())
+        return result.exception();
+
+    // FIXME: 2. Set an attribute value for this using localName, value, and also prefix and namespace.
+
+    // FIXME: Don't just call through to setAttribute() here.
+    return set_attribute(result.value().local_name(), value);
+}
+
 // https://dom.spec.whatwg.org/#dom-element-removeattribute
 void Element::remove_attribute(const FlyString& name)
 {

+ 1 - 0
Userland/Libraries/LibWeb/DOM/Element.h

@@ -54,6 +54,7 @@ public:
     String attribute(const FlyString& name) const { return get_attribute(name); }
     String get_attribute(const FlyString& name) const;
     ExceptionOr<void> set_attribute(const FlyString& name, const String& value);
+    ExceptionOr<void> set_attribute_ns(FlyString const& namespace_, FlyString const& qualified_name, String const& value);
     void remove_attribute(const FlyString& name);
     size_t attribute_list_size() const { return m_attributes->length(); }
     NonnullRefPtr<NamedNodeMap> const& attributes() const { return m_attributes; }

+ 1 - 0
Userland/Libraries/LibWeb/DOM/Element.idl

@@ -6,6 +6,7 @@ interface Element : Node {
 
     DOMString? getAttribute(DOMString qualifiedName);
     undefined setAttribute(DOMString qualifiedName, DOMString value);
+    [CEReactions] undefined setAttributeNS(DOMString? namespace , DOMString qualifiedName , DOMString value);
     undefined removeAttribute(DOMString qualifiedName);
     boolean hasAttribute(DOMString qualifiedName);
     boolean hasAttributes();