diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 8f3a82a9cd..f929326525 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -877,11 +877,22 @@ DOM::ExceptionOr> Document::create_element(String const& return DOM::create_element(*this, tag_name, Namespace::HTML); } +// https://dom.spec.whatwg.org/#dom-document-createelementns // https://dom.spec.whatwg.org/#internal-createelementns-steps // FIXME: This only implements step 4 of the algorithm and does not take in options. -DOM::ExceptionOr> Document::create_element_ns(const String& namespace_, const String& qualified_name) +DOM::ExceptionOr> Document::create_element_ns(String const& namespace_, String const& qualified_name) { - return DOM::create_element(*this, qualified_name, namespace_); + // 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(); + auto qname = result.release_value(); + + // FIXME: 2. Let is be null. + // FIXME: 3. If options is a dictionary and options["is"] exists, then set is to it. + + // 4. Return the result of creating an element given document, localName, namespace, prefix, is, and with the synchronous custom elements flag set. + return DOM::create_element(*this, qname.local_name(), qname.namespace_(), qname.prefix()); } NonnullRefPtr Document::create_document_fragment() diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index d29e50fff1..323f50d888 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -101,13 +101,15 @@ ExceptionOr Element::set_attribute(const FlyString& name, const String& va } // https://dom.spec.whatwg.org/#validate-and-extract -static ExceptionOr validate_and_extract(FlyString namespace_, FlyString qualified_name) +ExceptionOr 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. + // 2. Validate qualifiedName. + if (auto result = Document::validate_qualified_name(qualified_name); result.is_exception()) + return result.exception(); // 3. Let prefix be null. FlyString prefix = {}; diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 080094341e..78d4bd7ac9 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -160,4 +160,6 @@ private: template<> inline bool Node::fast_is() const { return is_element(); } +ExceptionOr validate_and_extract(FlyString namespace_, FlyString qualified_name); + } diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp index 61a1b43f7a..b5e0234eed 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -89,18 +89,30 @@ namespace Web::DOM { -NonnullRefPtr create_element(Document& document, FlyString tag_name, FlyString namespace_) +// https://dom.spec.whatwg.org/#concept-create-element +NonnullRefPtr create_element(Document& document, FlyString local_name, FlyString namespace_, FlyString prefix) { - auto lowercase_tag_name = tag_name.to_lowercase(); + // 1. If prefix was not given, let prefix be null. + // NOTE: This is already taken care of by `prefix` having a default value. - FlyString prefix; - auto parts = tag_name.view().split_view(':'); - if (parts.size() > 1) { - prefix = parts[0]; - tag_name = tag_name.view().substring_view_starting_from_substring(parts[1]); - } + // FIXME: 2. If is was not given, let is be null. + // FIXME: 3. Let result be null. + // FIXME: 4. Let definition be the result of looking up a custom element definition given document, namespace, localName, and is. + // FIXME: 5. If definition is non-null, and definition’s name is not equal to its local name (i.e., definition represents a customized built-in element), then: ... + // FIXME: 6. Otherwise, if definition is non-null, then: ... - auto qualified_name = QualifiedName(tag_name, prefix, namespace_); + // 7. Otherwise: + // 1. Let interface be the element interface for localName and namespace. + // 2. Set result to a new element that implements interface, with no attributes, namespace set to namespace, namespace prefix set to prefix, + // local name set to localName, custom element state set to "uncustomized", custom element definition set to null, is value set to is, + // and node document set to document. + // FIXME: 3. If namespace is the HTML namespace, and either localName is a valid custom element name or is is non-null, + // then set result’s custom element state to "undefined". + // 8. Return result. + + auto lowercase_tag_name = local_name.to_lowercase(); + + auto qualified_name = QualifiedName { local_name, prefix, namespace_ }; if (lowercase_tag_name == HTML::TagNames::a) return adopt_ref(*new HTML::HTMLAnchorElement(document, move(qualified_name))); if (lowercase_tag_name == HTML::TagNames::area) diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.h b/Userland/Libraries/LibWeb/DOM/ElementFactory.h index 8da8e9dec2..879b1e004b 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.h +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.h @@ -10,6 +10,6 @@ namespace Web::DOM { -NonnullRefPtr create_element(Document&, FlyString tag_name, FlyString namespace_); +NonnullRefPtr create_element(Document&, FlyString local_name, FlyString namespace_, FlyString prefix = {}); }