diff --git a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp index d233b1fd20..1f6aa5d69d 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp @@ -89,9 +89,11 @@ NonnullRefPtr DOMImplementation::create_html_document(const String& ti } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype -NonnullRefPtr DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id) +ExceptionOr> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id) { - // FIXME: Validate qualified_name. + auto result = Document::validate_qualified_name(qualified_name); + if (result.is_exception()) + return result.exception(); auto document_type = DocumentType::create(document()); document_type->set_name(qualified_name); document_type->set_public_id(public_id); diff --git a/Userland/Libraries/LibWeb/DOM/DOMImplementation.h b/Userland/Libraries/LibWeb/DOM/DOMImplementation.h index 391ee2820e..4dc03900ad 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.h +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.h @@ -30,7 +30,7 @@ public: // FIXME: Add optional DocumentType once supported by IDL ExceptionOr> create_document(const String&, const String&) const; NonnullRefPtr create_html_document(const String& title) const; - NonnullRefPtr create_document_type(String const& qualified_name, String const& public_id, String const& system_id); + ExceptionOr> create_document_type(String const& qualified_name, String const& public_id, String const& system_id); // https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature bool has_feature() const { return true; } diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index c36ce5f5d2..95cc0ffe88 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -1390,4 +1390,54 @@ bool Document::is_valid_name(String const& name) return true; } +// https://dom.spec.whatwg.org/#validate +ExceptionOr Document::validate_qualified_name(String const& qualified_name) +{ + if (qualified_name.is_empty()) + return InvalidCharacterError::create("Empty string is not a valid qualified name."); + + Utf8View utf8view { qualified_name }; + if (!utf8view.validate()) + return InvalidCharacterError::create("Invalid qualified name."); + + Optional colon_offset; + + bool in_name = false; + + for (auto it = utf8view.begin(); it != utf8view.end(); ++it) { + auto code_point = *it; + if (code_point == ':') { + if (colon_offset.has_value()) + return InvalidCharacterError::create("More than one colon (:) in qualified name."); + colon_offset = utf8view.byte_offset_of(it); + continue; + } + if (in_name) { + if (!is_valid_name_start_character(code_point)) + return InvalidCharacterError::create("Invalid start of qualified name."); + in_name = false; + continue; + } + if (!is_valid_name_character(code_point)) + return InvalidCharacterError::create("Invalid character in qualified name."); + } + + if (!colon_offset.has_value()) + return Document::PrefixAndTagName { + .prefix = {}, + .tag_name = qualified_name, + }; + + if (*colon_offset == 0) + return InvalidCharacterError::create("Qualified name can't start with colon (:)."); + + if (*colon_offset >= (qualified_name.length() - 1)) + return InvalidCharacterError::create("Qualified name can't end with colon (:)."); + + return Document::PrefixAndTagName { + .prefix = qualified_name.substring_view(0, *colon_offset), + .tag_name = qualified_name.substring_view(*colon_offset + 1), + }; +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 19c382bd14..3d45e33f0f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -318,6 +318,12 @@ public: static bool is_valid_name(String const&); + struct PrefixAndTagName { + FlyString prefix; + FlyString tag_name; + }; + static ExceptionOr validate_qualified_name(String const& qualified_name); + private: explicit Document(const AK::URL&);