LibWeb: Ensure parser cannot change the mode is handled

This fixes at least 1 wpt bug where text/plain documents are rendered in
quirks mode. The test in question: https://wpt.live/html/browsers/browsing-the-web/read-text/load-text-plain.html
This commit is contained in:
euro20179 2025-09-05 15:17:55 -07:00 committed by Tim Ledbetter
commit e442aa6e10
Notes: github-actions[bot] 2025-09-07 10:12:43 +00:00
6 changed files with 71 additions and 3 deletions

View file

@ -414,6 +414,9 @@ public:
bool in_limited_quirks_mode() const { return m_quirks_mode == QuirksMode::Limited; }
void set_quirks_mode(QuirksMode mode) { m_quirks_mode = mode; }
bool parser_cannot_change_the_mode() const { return m_parser_cannot_change_the_mode; }
void set_parser_cannot_change_the_mode(bool parser_cannot_change_the_mode) { m_parser_cannot_change_the_mode = parser_cannot_change_the_mode; }
Type document_type() const { return m_type; }
void set_document_type(Type type) { m_type = type; }
@ -1013,6 +1016,8 @@ private:
QuirksMode m_quirks_mode { QuirksMode::No };
bool m_parser_cannot_change_the_mode { false };
// https://dom.spec.whatwg.org/#concept-document-type
Type m_type { Type::XML };

View file

@ -208,7 +208,8 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_text_document(HTML::Navi
// 1. Let document be the result of creating and initializing a Document object given "html", type, and navigationParams.
auto document = TRY(DOM::Document::create_and_initialize(DOM::Document::Type::HTML, type.essence(), navigation_params));
// FIXME: 2. Set document's parser cannot change the mode flag to true.
// 2. Set document's parser cannot change the mode flag to true.
document->set_parser_cannot_change_the_mode(true);
// 3. Set document's mode to "no-quirks".
document->set_quirks_mode(DOM::QuirksMode::No);

View file

@ -606,16 +606,26 @@ void HTMLParser::handle_initial(HTMLToken& token)
// Otherwise, if the document is not an iframe srcdoc document, and the parser cannot change the mode flag is false,
// and the DOCTYPE token matches one of the conditions in the following list, then set the Document to limited-quirks mode:
// [...]
document().set_quirks_mode(which_quirks_mode(token));
if (!document().parser_cannot_change_the_mode())
document().set_quirks_mode(which_quirks_mode(token));
// Then, switch the insertion mode to "before html".
m_insertion_mode = InsertionMode::BeforeHTML;
return;
}
// -> Anything else
// FIXME: If the document is not an iframe srcdoc document, then this is a parse error
log_parse_error();
document().set_quirks_mode(DOM::QuirksMode::Yes);
// if the parser cannot change the mode flag is false, set the Document to quirks mode.
if (!document().parser_cannot_change_the_mode())
document().set_quirks_mode(DOM::QuirksMode::Yes);
// In any case, switch the insertion mode to "before html"
m_insertion_mode = InsertionMode::BeforeHTML;
// then reprocess the token.
process_using_the_rules_for(InsertionMode::BeforeHTML, token);
}

View file

@ -0,0 +1,8 @@
Harness status: OK
Found 3 tests
3 Pass
Pass Checking document metadata for text file
Pass Checking DOM for text file
Pass Checking contents for text file

View file

@ -0,0 +1,4 @@
This is a sample text/plain document.
This is not an HTML document.

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<title>Page load processing model for text files</title>
<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#read-text">
<script src="../../../../resources/testharness.js"></script>
<script src="../../../../resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
var t = async_test("Checking document metadata for text file");
var tD = async_test("Checking DOM for text file");
var tC = async_test("Checking contents for text file");
var iframe = document.body.appendChild(document.createElement("iframe"));
iframe.onload = function(e) {
var doc = iframe.contentDocument;
t.step(function() {
assert_equals(doc.compatMode, "CSS1Compat");
assert_equals(doc.contentType, "text/plain");
assert_equals(doc.doctype, null);
t.done();
})
tD.step(function() {
assert_equals(doc.childNodes.length, 1, "Document should have 1 child")
assert_equals(doc.documentElement.tagName, "HTML");
assert_equals(doc.documentElement.childNodes.length, 2,
"Root element should have 2 children")
assert_equals(doc.documentElement.firstChild.tagName, "HEAD");
assert_equals(doc.documentElement.lastChild.tagName, "BODY");
assert_equals(doc.documentElement.lastChild.childNodes.length, 1,
"Body element should have 1 child")
assert_equals(doc.documentElement.lastChild.firstChild.tagName, "PRE");
tD.done();
})
tC.step(function() {
assert_equals(doc.documentElement.lastChild.firstChild.firstChild.data,
"This is a sample text/plain document.\n\nThis is not an HTML document.\n\n");
tC.done();
})
};
iframe.src = "../../../../common/text-plain.txt";
</script>