mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb: Update DOMImplementation.createDocumentType()
name validation
This now follows the latest specification steps.
This commit is contained in:
parent
f98312d022
commit
16dbb44de2
Notes:
github-actions[bot]
2025-06-19 11:57:08 +00:00
Author: https://github.com/tcl3
Commit: 16dbb44de2
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5141
Reviewed-by: https://github.com/gmta ✅
Reviewed-by: https://github.com/trflynn89 ✅
6 changed files with 228 additions and 6 deletions
|
@ -137,14 +137,16 @@ GC::Ref<Document> DOMImplementation::create_html_document(Optional<String> const
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
|
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
|
||||||
WebIDL::ExceptionOr<GC::Ref<DocumentType>> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id)
|
WebIDL::ExceptionOr<GC::Ref<DocumentType>> 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());
|
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_public_id(public_id);
|
||||||
document_type->set_system_id(system_id);
|
document_type->set_system_id(system_id);
|
||||||
return document_type;
|
return document_type;
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
|
|
||||||
WebIDL::ExceptionOr<GC::Ref<XMLDocument>> create_document(Optional<FlyString> const&, String const&, GC::Ptr<DocumentType>) const;
|
WebIDL::ExceptionOr<GC::Ref<XMLDocument>> create_document(Optional<FlyString> const&, String const&, GC::Ptr<DocumentType>) const;
|
||||||
GC::Ref<Document> create_html_document(Optional<String> const& title) const;
|
GC::Ref<Document> create_html_document(Optional<String> const& title) const;
|
||||||
WebIDL::ExceptionOr<GC::Ref<DocumentType>> create_document_type(String const& qualified_name, String const& public_id, String const& system_id);
|
WebIDL::ExceptionOr<GC::Ref<DocumentType>> create_document_type(String const& name, String const& public_id, String const& system_id);
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
|
// https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
|
||||||
bool has_feature() const
|
bool has_feature() const
|
||||||
|
|
|
@ -28,4 +28,12 @@ void DocumentType::initialize(JS::Realm& realm)
|
||||||
Base::initialize(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<u32, 7> INVALID_DOCTYPE_CHARACTERS { '\t', '\n', '\f', '\r', ' ', '\0', '>' };
|
||||||
|
return !name.code_points().contains_any_of(INVALID_DOCTYPE_CHARACTERS);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ private:
|
||||||
String m_system_id;
|
String m_system_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool is_valid_doctype_name(String const&);
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool Node::fast_is<DocumentType>() const { return is_document_type(); }
|
inline bool Node::fast_is<DocumentType>() const { return is_document_type(); }
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,123 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>DOMImplementation.createDocumentType(qualifiedName, publicId, systemId)</title>
|
||||||
|
<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype">
|
||||||
|
<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name">
|
||||||
|
<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
|
||||||
|
<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
|
||||||
|
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var tests = [
|
||||||
|
["", "", "", null],
|
||||||
|
["test:root", "1234", "", null],
|
||||||
|
["test:root", "1234", "test", null],
|
||||||
|
["test:root", "test", "", null],
|
||||||
|
["test:root", "test", "test", null],
|
||||||
|
["_:_", "", "", null],
|
||||||
|
["_:h0", "", "", null],
|
||||||
|
["_:test", "", "", null],
|
||||||
|
["_:_.", "", "", null],
|
||||||
|
["_:a-", "", "", null],
|
||||||
|
["l_:_", "", "", null],
|
||||||
|
["ns:_0", "", "", null],
|
||||||
|
["ns:a0", "", "", null],
|
||||||
|
["ns0:test", "", "", null],
|
||||||
|
["ns:EEE.", "", "", null],
|
||||||
|
["ns:_-", "", "", null],
|
||||||
|
["a.b:c", "", "", null],
|
||||||
|
["a-b:c.j", "", "", null],
|
||||||
|
["a-b:c", "", "", null],
|
||||||
|
["foo", "", "", null],
|
||||||
|
["1foo", "", "", null],
|
||||||
|
["foo1", "", "", null],
|
||||||
|
["f1oo", "", "", null],
|
||||||
|
["@foo", "", "", null],
|
||||||
|
["foo@", "", "", null],
|
||||||
|
["f@oo", "", "", null],
|
||||||
|
["edi:{", "", "", null],
|
||||||
|
["edi:}", "", "", null],
|
||||||
|
["edi:~", "", "", null],
|
||||||
|
["edi:'", "", "", null],
|
||||||
|
["edi:!", "", "", null],
|
||||||
|
["edi:@", "", "", null],
|
||||||
|
["edi:#", "", "", null],
|
||||||
|
["edi:$", "", "", null],
|
||||||
|
["edi:%", "", "", null],
|
||||||
|
["edi:^", "", "", null],
|
||||||
|
["edi:&", "", "", null],
|
||||||
|
["edi:*", "", "", null],
|
||||||
|
["edi:(", "", "", null],
|
||||||
|
["edi:)", "", "", null],
|
||||||
|
["edi:+", "", "", null],
|
||||||
|
["edi:=", "", "", null],
|
||||||
|
["edi:[", "", "", null],
|
||||||
|
["edi:]", "", "", null],
|
||||||
|
["edi:\\", "", "", null],
|
||||||
|
["edi:/", "", "", null],
|
||||||
|
["edi:;", "", "", null],
|
||||||
|
["edi:`", "", "", null],
|
||||||
|
["edi:<", "", "", null],
|
||||||
|
["edi:>", "", "", "INVALID_CHARACTER_ERR"],
|
||||||
|
["edi:,", "", "", null],
|
||||||
|
["edi:a ", "", "", "INVALID_CHARACTER_ERR"],
|
||||||
|
["edi:\"", "", "", null],
|
||||||
|
["{", "", "", null],
|
||||||
|
["}", "", "", null],
|
||||||
|
["'", "", "", null],
|
||||||
|
["~", "", "", null],
|
||||||
|
["`", "", "", null],
|
||||||
|
["@", "", "", null],
|
||||||
|
["#", "", "", null],
|
||||||
|
["$", "", "", null],
|
||||||
|
["%", "", "", null],
|
||||||
|
["^", "", "", null],
|
||||||
|
["&", "", "", null],
|
||||||
|
["*", "", "", null],
|
||||||
|
["(", "", "", null],
|
||||||
|
[")", "", "", null],
|
||||||
|
["f:oo", "", "", null],
|
||||||
|
[":foo", "", "", null],
|
||||||
|
["foo:", "", "", null],
|
||||||
|
["prefix::local", "", "", null],
|
||||||
|
["foo", "foo", "", null],
|
||||||
|
["foo", "", "foo", null],
|
||||||
|
["foo", "f'oo", "", null],
|
||||||
|
["foo", "", "f'oo", null],
|
||||||
|
["foo", 'f"oo', "", null],
|
||||||
|
["foo", "", 'f"oo', null],
|
||||||
|
["foo", "f'o\"o", "", null],
|
||||||
|
["foo", "", "f'o\"o", null],
|
||||||
|
["foo", "foo>", "", null],
|
||||||
|
["foo", "", "foo>", null]
|
||||||
|
]
|
||||||
|
|
||||||
|
var doc = document.implementation.createHTMLDocument("title");
|
||||||
|
var doTest = function(aDocument, aQualifiedName, aPublicId, aSystemId) {
|
||||||
|
var doctype = aDocument.implementation.createDocumentType(aQualifiedName, aPublicId, aSystemId);
|
||||||
|
assert_equals(doctype.name, aQualifiedName, "name")
|
||||||
|
assert_equals(doctype.nodeName, aQualifiedName, "nodeName")
|
||||||
|
assert_equals(doctype.publicId, aPublicId, "publicId")
|
||||||
|
assert_equals(doctype.systemId, aSystemId, "systemId")
|
||||||
|
assert_equals(doctype.ownerDocument, aDocument, "ownerDocument")
|
||||||
|
assert_equals(doctype.nodeValue, null, "nodeValue")
|
||||||
|
}
|
||||||
|
tests.forEach(function(t) {
|
||||||
|
var qualifiedName = t[0], publicId = t[1], systemId = t[2], expected = t[3]
|
||||||
|
test(function() {
|
||||||
|
if (expected) {
|
||||||
|
assert_throws_dom(expected, function() {
|
||||||
|
document.implementation.createDocumentType(qualifiedName, publicId, systemId)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
doTest(document, qualifiedName, publicId, systemId);
|
||||||
|
doTest(doc, qualifiedName, publicId, systemId);
|
||||||
|
}
|
||||||
|
}, "createDocumentType(" + format_value(qualifiedName) + ", " + format_value(publicId) + ", " + format_value(systemId) + ") should " +
|
||||||
|
(expected ? "throw " + expected : "work"));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue