diff --git a/Libraries/LibWeb/DOM/DOMImplementation.cpp b/Libraries/LibWeb/DOM/DOMImplementation.cpp index dc31d69e713..dd22a104473 100644 --- a/Libraries/LibWeb/DOM/DOMImplementation.cpp +++ b/Libraries/LibWeb/DOM/DOMImplementation.cpp @@ -137,14 +137,16 @@ GC::Ref DOMImplementation::create_html_document(Optional const } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype -WebIDL::ExceptionOr> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id) +WebIDL::ExceptionOr> DOMImplementation::create_document_type(String const& name, String const& public_id, String const& system_id) { - // 1. Validate qualifiedName. - TRY(Document::validate_qualified_name(realm(), qualified_name)); - // 2. Return a new doctype, with qualifiedName as its name, publicId as its public ID, and systemId as its system ID, and with its node document set to the associated document of this. + // 1. If name is not a valid doctype name, then throw an "InvalidCharacterError" DOMException. + if (!is_valid_doctype_name(name)) + return WebIDL::InvalidCharacterError::create(realm(), "Invalid doctype name"_string); + + // 2. Return a new doctype, with name as its name, publicId as its public ID, and systemId as its system ID, and with its node document set to the associated document of this. auto document_type = DocumentType::create(document()); - document_type->set_name(qualified_name); + document_type->set_name(name); document_type->set_public_id(public_id); document_type->set_system_id(system_id); return document_type; diff --git a/Libraries/LibWeb/DOM/DOMImplementation.h b/Libraries/LibWeb/DOM/DOMImplementation.h index d131ef2f798..85d8fbac08c 100644 --- a/Libraries/LibWeb/DOM/DOMImplementation.h +++ b/Libraries/LibWeb/DOM/DOMImplementation.h @@ -23,7 +23,7 @@ public: WebIDL::ExceptionOr> create_document(Optional const&, String const&, GC::Ptr) const; GC::Ref create_html_document(Optional const& title) const; - WebIDL::ExceptionOr> create_document_type(String const& qualified_name, String const& public_id, String const& system_id); + WebIDL::ExceptionOr> create_document_type(String const& name, String const& public_id, String const& system_id); // https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature bool has_feature() const diff --git a/Libraries/LibWeb/DOM/DocumentType.cpp b/Libraries/LibWeb/DOM/DocumentType.cpp index 8ae25b002ce..988ef89f414 100644 --- a/Libraries/LibWeb/DOM/DocumentType.cpp +++ b/Libraries/LibWeb/DOM/DocumentType.cpp @@ -28,4 +28,12 @@ void DocumentType::initialize(JS::Realm& realm) Base::initialize(realm); } +// https://dom.spec.whatwg.org/#valid-doctype-name +bool is_valid_doctype_name(String const& name) +{ + // A string is a valid doctype name if it does not contain ASCII whitespace, U+0000 NULL, or U+003E (>). + constexpr Array INVALID_DOCTYPE_CHARACTERS { '\t', '\n', '\f', '\r', ' ', '\0', '>' }; + return !name.code_points().contains_any_of(INVALID_DOCTYPE_CHARACTERS); +} + } diff --git a/Libraries/LibWeb/DOM/DocumentType.h b/Libraries/LibWeb/DOM/DocumentType.h index 08067ce72b2..52f7197c7f4 100644 --- a/Libraries/LibWeb/DOM/DocumentType.h +++ b/Libraries/LibWeb/DOM/DocumentType.h @@ -44,6 +44,8 @@ private: String m_system_id; }; +bool is_valid_doctype_name(String const&); + template<> inline bool Node::fast_is() const { return is_document_type(); } diff --git a/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/DOMImplementation-createDocumentType.txt b/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/DOMImplementation-createDocumentType.txt new file mode 100644 index 00000000000..ae216d1c34b --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/DOMImplementation-createDocumentType.txt @@ -0,0 +1,87 @@ +Harness status: OK + +Found 82 tests + +82 Pass +Pass DOMImplementation.createDocumentType(qualifiedName, publicId, systemId) +Pass createDocumentType("", "", "") should work +Pass createDocumentType("test:root", "1234", "") should work +Pass createDocumentType("test:root", "1234", "test") should work +Pass createDocumentType("test:root", "test", "") should work +Pass createDocumentType("test:root", "test", "test") should work +Pass createDocumentType("_:_", "", "") should work +Pass createDocumentType("_:h0", "", "") should work +Pass createDocumentType("_:test", "", "") should work +Pass createDocumentType("_:_.", "", "") should work +Pass createDocumentType("_:a-", "", "") should work +Pass createDocumentType("l_:_", "", "") should work +Pass createDocumentType("ns:_0", "", "") should work +Pass createDocumentType("ns:a0", "", "") should work +Pass createDocumentType("ns0:test", "", "") should work +Pass createDocumentType("ns:EEE.", "", "") should work +Pass createDocumentType("ns:_-", "", "") should work +Pass createDocumentType("a.b:c", "", "") should work +Pass createDocumentType("a-b:c.j", "", "") should work +Pass createDocumentType("a-b:c", "", "") should work +Pass createDocumentType("foo", "", "") should work +Pass createDocumentType("1foo", "", "") should work +Pass createDocumentType("foo1", "", "") should work +Pass createDocumentType("f1oo", "", "") should work +Pass createDocumentType("@foo", "", "") should work +Pass createDocumentType("foo@", "", "") should work +Pass createDocumentType("f@oo", "", "") should work +Pass createDocumentType("edi:{", "", "") should work +Pass createDocumentType("edi:}", "", "") should work +Pass createDocumentType("edi:~", "", "") should work +Pass createDocumentType("edi:'", "", "") should work +Pass createDocumentType("edi:!", "", "") should work +Pass createDocumentType("edi:@", "", "") should work +Pass createDocumentType("edi:#", "", "") should work +Pass createDocumentType("edi:$", "", "") should work +Pass createDocumentType("edi:%", "", "") should work +Pass createDocumentType("edi:^", "", "") should work +Pass createDocumentType("edi:&", "", "") should work +Pass createDocumentType("edi:*", "", "") should work +Pass createDocumentType("edi:(", "", "") should work +Pass createDocumentType("edi:)", "", "") should work +Pass createDocumentType("edi:+", "", "") should work +Pass createDocumentType("edi:=", "", "") should work +Pass createDocumentType("edi:[", "", "") should work +Pass createDocumentType("edi:]", "", "") should work +Pass createDocumentType("edi:\\", "", "") should work +Pass createDocumentType("edi:/", "", "") should work +Pass createDocumentType("edi:;", "", "") should work +Pass createDocumentType("edi:`", "", "") should work +Pass createDocumentType("edi:<", "", "") should work +Pass createDocumentType("edi:>", "", "") should throw INVALID_CHARACTER_ERR +Pass createDocumentType("edi:,", "", "") should work +Pass createDocumentType("edi:a ", "", "") should throw INVALID_CHARACTER_ERR +Pass createDocumentType("edi:\"", "", "") should work +Pass createDocumentType("{", "", "") should work +Pass createDocumentType("}", "", "") should work +Pass createDocumentType("'", "", "") should work +Pass createDocumentType("~", "", "") should work +Pass createDocumentType("`", "", "") should work +Pass createDocumentType("@", "", "") should work +Pass createDocumentType("#", "", "") should work +Pass createDocumentType("$", "", "") should work +Pass createDocumentType("%", "", "") should work +Pass createDocumentType("^", "", "") should work +Pass createDocumentType("&", "", "") should work +Pass createDocumentType("*", "", "") should work +Pass createDocumentType("(", "", "") should work +Pass createDocumentType(")", "", "") should work +Pass createDocumentType("f:oo", "", "") should work +Pass createDocumentType(":foo", "", "") should work +Pass createDocumentType("foo:", "", "") should work +Pass createDocumentType("prefix::local", "", "") should work +Pass createDocumentType("foo", "foo", "") should work +Pass createDocumentType("foo", "", "foo") should work +Pass createDocumentType("foo", "f'oo", "") should work +Pass createDocumentType("foo", "", "f'oo") should work +Pass createDocumentType("foo", "f\"oo", "") should work +Pass createDocumentType("foo", "", "f\"oo") should work +Pass createDocumentType("foo", "f'o\"o", "") should work +Pass createDocumentType("foo", "", "f'o\"o") should work +Pass createDocumentType("foo", "foo>", "") should work +Pass createDocumentType("foo", "", "foo>") should work \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/dom/nodes/DOMImplementation-createDocumentType.html b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/DOMImplementation-createDocumentType.html new file mode 100644 index 00000000000..505ec5dc0fc --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/DOMImplementation-createDocumentType.html @@ -0,0 +1,123 @@ + + +DOMImplementation.createDocumentType(qualifiedName, publicId, systemId) + + + + + + + +
+