LibWeb: Set doctype node immediately while parsing XML document

Instead of deferring it to the end of parsing, where scripts that
were expecting to look at the doctype may have already run.
This commit is contained in:
Andreas Kling 2024-11-20 11:43:20 +01:00 committed by Andreas Kling
parent ab0dc83d28
commit cd446e5e9c
Notes: github-actions[bot] 2024-11-20 15:11:55 +00:00
6 changed files with 66 additions and 9 deletions

View file

@ -62,7 +62,7 @@ void XMLDocumentBuilder::set_source(ByteString source)
m_document->set_source(MUST(String::from_byte_string(source)));
}
void XMLDocumentBuilder::set_doctype(XML::Doctype doctype)
void XMLDocumentBuilder::doctype(XML::Doctype const& doctype)
{
if (m_document->doctype()) {
return;
@ -73,13 +73,13 @@ void XMLDocumentBuilder::set_doctype(XML::Doctype doctype)
document_type->set_name(name);
if (doctype.external_id.has_value()) {
auto external_id = doctype.external_id.release_value();
auto const& external_id = *doctype.external_id;
auto system_id = MUST(AK::String::from_byte_string(external_id.system_id.system_literal));
document_type->set_system_id(system_id);
if (external_id.public_id.has_value()) {
auto public_id = MUST(AK::String::from_byte_string(external_id.public_id.release_value().public_literal));
auto public_id = MUST(AK::String::from_byte_string(external_id.public_id->public_literal));
document_type->set_public_id(public_id);
}
}

View file

@ -31,7 +31,7 @@ public:
private:
virtual void set_source(ByteString) override;
virtual void set_doctype(XML::Doctype) override;
virtual void doctype(XML::Doctype const&) override;
virtual void element_start(XML::Name const& name, HashMap<XML::Name, ByteString> const& attributes) override;
virtual void element_end(XML::Name const& name) override;
virtual void text(StringView data) override;

View file

@ -182,9 +182,6 @@ ErrorOr<void, ParseError> Parser::parse_with_listener(Listener& listener)
if (result.is_error())
m_listener->error(result.error());
m_listener->document_end();
if (m_doctype.has_value()) {
m_listener->set_doctype(m_doctype.release_value());
}
m_root_node.clear();
return result;
}
@ -621,7 +618,8 @@ ErrorOr<void, ParseError> Parser::parse_doctype_decl()
TRY(expect(">"sv));
rollback.disarm();
m_doctype = move(doctype);
if (m_listener)
m_listener->doctype(doctype);
return {};
}

View file

@ -34,9 +34,9 @@ struct Listener {
virtual ~Listener() { }
virtual void set_source(ByteString) { }
virtual void set_doctype(XML::Doctype) { }
virtual void document_start() { }
virtual void document_end() { }
virtual void doctype(Doctype const&) { }
virtual void element_start(Name const&, HashMap<Name, ByteString> const&) { }
virtual void element_end(Name const&) { }
virtual void text(StringView) { }

View file

@ -0,0 +1,17 @@
Summary
Harness status: OK
Rerun
Found 7 tests
7 Pass
Details
Result Test Name MessagePass For Element nodes, nodeName should return the same as tagName.
Pass For Text nodes, nodeName should return "#text".
Pass For ProcessingInstruction nodes, nodeName should return the target.
Pass For Comment nodes, nodeName should return "#comment".
Pass For Document nodes, nodeName should return "#document".
Pass For DocumentType nodes, nodeName should return the name.
Pass For DocumentFragment nodes, nodeName should return "#document-fragment".

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Node.nodeName</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
</head>
<body>
<div id="log"/>
<script>
test(function() {
var HTMLNS = "http://www.w3.org/1999/xhtml",
SVGNS = "http://www.w3.org/2000/svg"
assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I")
assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "i")
assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg")
assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG")
assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "x:b")
}, "For Element nodes, nodeName should return the same as tagName.")
test(function() {
assert_equals(document.createTextNode("foo").nodeName, "#text")
}, "For Text nodes, nodeName should return \"#text\".")
test(function() {
assert_equals(document.createProcessingInstruction("foo", "bar").nodeName,
"foo")
}, "For ProcessingInstruction nodes, nodeName should return the target.")
test(function() {
assert_equals(document.createComment("foo").nodeName, "#comment")
}, "For Comment nodes, nodeName should return \"#comment\".")
test(function() {
assert_equals(document.nodeName, "#document")
}, "For Document nodes, nodeName should return \"#document\".")
test(function() {
assert_equals(document.doctype.nodeName, "html")
}, "For DocumentType nodes, nodeName should return the name.")
test(function() {
assert_equals(document.createDocumentFragment().nodeName,
"#document-fragment")
}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".")
</script>
</body>
</html>