diff --git a/Tests/LibWeb/TestConfig.ini b/Tests/LibWeb/TestConfig.ini index b1676ffa91e..051969bd91b 100644 --- a/Tests/LibWeb/TestConfig.ini +++ b/Tests/LibWeb/TestConfig.ini @@ -19,7 +19,6 @@ Text/input/Worker/Worker-performance.html Text/input/Worker/Worker-postMessage-transfer.html Text/input/wpt-import/css/css-flexbox/abspos/position-absolute-001.html Text/input/wpt-import/html/syntax/parsing/html5lib_entities01.html -Text/input/wpt-import/html/syntax/parsing/html5lib_html5test-com.html Text/input/wpt-import/html/syntax/parsing/html5lib_innerHTML_tests_innerHTML_1.html Text/input/wpt-import/html/syntax/parsing/html5lib_plain-text-unsafe.html Text/input/wpt-import/html/syntax/parsing/html5lib_template.html diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/syntax/parsing/html5lib_html5test-com.txt b/Tests/LibWeb/Text/expected/wpt-import/html/syntax/parsing/html5lib_html5test-com.txt new file mode 100644 index 00000000000..860f303cd87 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/html/syntax/parsing/html5lib_html5test-com.txt @@ -0,0 +1,34 @@ +Summary + +Harness status: OK + +Rerun + +Found 24 tests + +24 Pass +Details +Result Test Name MessagePass html5lib_html5test-com.html 71bd5e6b9e907e65295b6d670627e0da4a8a65ed +Pass html5lib_html5test-com.html 32cd504d36a6db3584b716b3681ab4b0741423b3 +Pass html5lib_html5test-com.html f0bf0506a2d3e5ca4aa5f14a1f260e405882827e +Pass html5lib_html5test-com.html 666a215d91c4e83d99f4be4caebb67fd65569480 +Pass html5lib_html5test-com.html fd2cd459bdc79db754b24bc537758990d392b1fc +Pass html5lib_html5test-com.html 86be28614bf72e24c162d865c04d687447098867 +Pass html5lib_html5test-com.html be72b058e5be0f6aef2c442d83c92c0d251fcb7f +Pass html5lib_html5test-com.html ab6e31cf52c8d57d6dfdcaf7165f1abf7bd5e73d +Pass html5lib_html5test-com.html 11240d9b03b14eb515d6a1d1595c5a409830ea38 +Pass html5lib_html5test-com.html 809c1bebcded8f43981af902442ff8a2db5d2578 +Pass html5lib_html5test-com.html bcbeb84f40e56a642b794d514e97e3ec303d4a79 +Pass html5lib_html5test-com.html 1cbb987dd0a35af3a5b2e4fc11eba36a60eba03d +Pass html5lib_html5test-com.html 5b5e75eca2f5c80e1c4d5676254b9891090e288e +Pass html5lib_html5test-com.html 93e966e2edad3297ecb159f3983bdd2dc84f829e +Pass html5lib_html5test-com.html 7a02a2d7ab875dbeedc9a34c6c27b6119bd6d1f0 +Pass html5lib_html5test-com.html 46615acdb9dd6231e2a65fed5bcce7e19f086d03 +Pass html5lib_html5test-com.html 381de12234a699cbfb775b3ca7c679f357e7403e +Pass html5lib_html5test-com.html 72736fc894b2077928559cc4284a102635cac898 +Pass html5lib_html5test-com.html 290d5e7fa9684038411e78c4b0e0ade83150eeea +Pass html5lib_html5test-com.html a5fb9cf46ed215a61d073ae4b7e7477ba49fa5d8 +Pass html5lib_html5test-com.html 88dea19243733a9bda26c6f5290d2c4f5bbac157 +Pass html5lib_html5test-com.html 9906bb30ae08654f4c67bf6d97040abbca91082d +Pass html5lib_html5test-com.html c6cd25ce02329e4a42b9be9ba35453532fec7599 +Pass html5lib_html5test-com.html 81af3f9d6ccc2a1a1a58ace18dd530c544675610 \ No newline at end of file diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index 4365e0d4a13..6f6f9ac1995 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -201,11 +201,11 @@ void HTMLParser::run(HTMLTokenizer::StopAtInsertionPoint stop_at_insertion_point // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher // As each token is emitted from the tokenizer, the user agent must follow the appropriate steps from the following list, known as the tree construction dispatcher: if (m_stack_of_open_elements.is_empty() - || adjusted_current_node().namespace_uri() == Namespace::HTML - || (is_mathml_text_integration_point(adjusted_current_node()) && token.is_start_tag() && token.tag_name() != MathML::TagNames::mglyph && token.tag_name() != MathML::TagNames::malignmark) - || (is_mathml_text_integration_point(adjusted_current_node()) && token.is_character()) - || (adjusted_current_node().namespace_uri() == Namespace::MathML && adjusted_current_node().tag_name() == MathML::TagNames::annotation_xml && token.is_start_tag() && token.tag_name() == SVG::TagNames::svg) - || (is_html_integration_point(adjusted_current_node()) && (token.is_start_tag() || token.is_character())) + || adjusted_current_node()->namespace_uri() == Namespace::HTML + || (is_mathml_text_integration_point(*adjusted_current_node()) && token.is_start_tag() && token.tag_name() != MathML::TagNames::mglyph && token.tag_name() != MathML::TagNames::malignmark) + || (is_mathml_text_integration_point(*adjusted_current_node()) && token.is_character()) + || (adjusted_current_node()->namespace_uri() == Namespace::MathML && adjusted_current_node()->tag_name() == MathML::TagNames::annotation_xml && token.is_start_tag() && token.tag_name() == SVG::TagNames::svg) + || (is_html_integration_point(*adjusted_current_node()) && (token.is_start_tag() || token.is_character())) || token.is_end_of_file()) { // -> If the stack of open elements is empty // -> If the adjusted current node is an element in the HTML namespace @@ -608,13 +608,15 @@ AnythingElse: return; } -DOM::Element& HTMLParser::current_node() +JS::GCPtr HTMLParser::current_node() { + if (m_stack_of_open_elements.is_empty()) + return nullptr; return m_stack_of_open_elements.current_node(); } // https://html.spec.whatwg.org/multipage/parsing.html#adjusted-current-node -DOM::Element& HTMLParser::adjusted_current_node() +JS::GCPtr HTMLParser::adjusted_current_node() { // The adjusted current node is the context element if the parser was created as part of the // HTML fragment parsing algorithm and the stack of open elements has only one element in it @@ -626,8 +628,10 @@ DOM::Element& HTMLParser::adjusted_current_node() return current_node(); } -DOM::Element& HTMLParser::node_before_current_node() +JS::GCPtr HTMLParser::node_before_current_node() { + if (m_stack_of_open_elements.elements().size() < 2) + return nullptr; return *m_stack_of_open_elements.elements().at(m_stack_of_open_elements.elements().size() - 2); } @@ -635,7 +639,7 @@ DOM::Element& HTMLParser::node_before_current_node() HTMLParser::AdjustedInsertionLocation HTMLParser::find_appropriate_place_for_inserting_node(JS::GCPtr override_target) { // 1. If there was an override target specified, then let target be the override target. - auto& target = override_target ? *override_target.ptr() : current_node(); + auto& target = override_target ? *override_target.ptr() : *current_node(); HTMLParser::AdjustedInsertionLocation adjusted_insertion_location; // 2. Determine the adjusted insertion location using the first matching steps from the following list: @@ -986,7 +990,7 @@ void HTMLParser::handle_in_head(HTMLToken& token) // - the adjusted current node is not the topmost element in the stack of open elements, if (!shadowrootmode.has_value() || !document.allow_declarative_shadow_roots() - || &adjusted_current_node() == &m_stack_of_open_elements.first()) { + || adjusted_current_node() == &m_stack_of_open_elements.first()) { // then insert an HTML element for the token. (void)insert_html_element(token); } @@ -994,7 +998,7 @@ void HTMLParser::handle_in_head(HTMLToken& token) // Otherwise: else { // 1. Let declarative shadow host element be adjusted current node. - auto& declarative_shadow_host_element = adjusted_current_node(); + auto& declarative_shadow_host_element = *adjusted_current_node(); // 2. Let template be the result of insert a foreign element for template start tag, with HTML namespace and true. auto template_ = insert_foreign_element(template_start_tag, Namespace::HTML, OnlyAddToElementStack::Yes); @@ -1061,7 +1065,7 @@ void HTMLParser::handle_in_head(HTMLToken& token) generate_all_implied_end_tags_thoroughly(); // 2. If the current node is not a template element, then this is a parse error. - if (current_node().local_name() != HTML::TagNames::template_) + if (current_node()->local_name() != HTML::TagNames::template_) log_parse_error(); // 3. Pop elements from the stack of open elements until a template element has been popped from the stack. @@ -1282,20 +1286,20 @@ AnythingElse: void HTMLParser::generate_implied_end_tags(FlyString const& exception) { - while (current_node().local_name() != exception && current_node().local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc)) + while (current_node()->local_name() != exception && current_node()->local_name().is_one_of(HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc)) (void)m_stack_of_open_elements.pop(); } void HTMLParser::generate_all_implied_end_tags_thoroughly() { - while (current_node().local_name().is_one_of(HTML::TagNames::caption, HTML::TagNames::colgroup, HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr)) + while (current_node()->local_name().is_one_of(HTML::TagNames::caption, HTML::TagNames::colgroup, HTML::TagNames::dd, HTML::TagNames::dt, HTML::TagNames::li, HTML::TagNames::optgroup, HTML::TagNames::option, HTML::TagNames::p, HTML::TagNames::rb, HTML::TagNames::rp, HTML::TagNames::rt, HTML::TagNames::rtc, HTML::TagNames::tbody, HTML::TagNames::td, HTML::TagNames::tfoot, HTML::TagNames::th, HTML::TagNames::thead, HTML::TagNames::tr)) (void)m_stack_of_open_elements.pop(); } void HTMLParser::close_a_p_element() { generate_implied_end_tags(HTML::TagNames::p); - if (current_node().local_name() != HTML::TagNames::p) { + if (current_node()->local_name() != HTML::TagNames::p) { log_parse_error(); } m_stack_of_open_elements.pop_until_an_element_with_tag_name_has_been_popped(HTML::TagNames::p); @@ -1429,7 +1433,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a // 2. If the current node is an HTML element whose tag name is subject, // and the current node is not in the list of active formatting elements, // then pop the current node off the stack of open elements, and return. - if (current_node().local_name() == subject && !m_list_of_active_formatting_elements.contains(current_node())) { + if (current_node()->local_name() == subject && !m_list_of_active_formatting_elements.contains(*current_node())) { (void)m_stack_of_open_elements.pop(); return AdoptionAgencyAlgorithmOutcome::DoNothing; } @@ -1474,7 +1478,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a } // 6. If formatting element is not the current node, - if (formatting_element != ¤t_node()) { + if (formatting_element != current_node()) { // this is a parse error. (But do not return.) log_parse_error(); } @@ -1487,7 +1491,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a if (!furthest_block) { // then the UA must first pop all the nodes from the bottom of the stack of open elements, // from the current node up to and including formatting element, - while (¤t_node() != formatting_element) + while (current_node() != formatting_element) (void)m_stack_of_open_elements.pop(); (void)m_stack_of_open_elements.pop(); @@ -1943,7 +1947,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) close_a_p_element(); // If the current node is an HTML element whose tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then this is a parse error; pop the current node off the stack of open elements. - if (current_node().local_name().is_one_of(HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6)) { + if (current_node()->local_name().is_one_of(HTML::TagNames::h1, HTML::TagNames::h2, HTML::TagNames::h3, HTML::TagNames::h4, HTML::TagNames::h5, HTML::TagNames::h6)) { log_parse_error(); (void)m_stack_of_open_elements.pop(); } @@ -2011,7 +2015,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(HTML::TagNames::li); // 2. If the current node is not an li element, then this is a parse error. - if (current_node().local_name() != HTML::TagNames::li) { + if (current_node()->local_name() != HTML::TagNames::li) { log_parse_error(); } @@ -2052,7 +2056,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) if (node->local_name() == HTML::TagNames::dd) { generate_implied_end_tags(HTML::TagNames::dd); // 2. If the current node is not a dd element, then this is a parse error. - if (current_node().local_name() != HTML::TagNames::dd) { + if (current_node()->local_name() != HTML::TagNames::dd) { log_parse_error(); } @@ -2067,7 +2071,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) if (node->local_name() == HTML::TagNames::dt) { // 2. If the current node is not a dt element, then this is a parse error. generate_implied_end_tags(HTML::TagNames::dt); - if (current_node().local_name() != HTML::TagNames::dt) { + if (current_node()->local_name() != HTML::TagNames::dt) { log_parse_error(); } // 3. Pop elements from the stack of open elements until a dt element has been popped from the stack. @@ -2145,7 +2149,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(); // 2. If the current node is not an HTML element with the same tag name as that of the token, then this is a parse error. - if (current_node().local_name() != token.tag_name()) { + if (current_node()->local_name() != token.tag_name()) { log_parse_error(); } @@ -2174,7 +2178,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(); // 5. If the current node is not node, then this is a parse error. - if (¤t_node() != node.ptr()) { + if (current_node() != node) { log_parse_error(); } @@ -2193,7 +2197,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(); // 3. If the current node is not a form element, then this is a parse error. - if (current_node().local_name() != HTML::TagNames::form) { + if (current_node()->local_name() != HTML::TagNames::form) { log_parse_error(); } @@ -2229,9 +2233,9 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(HTML::TagNames::li); // 2. If the current node is not an li element, then this is a parse error. - if (current_node().local_name() != HTML::TagNames::li) { + if (current_node()->local_name() != HTML::TagNames::li) { log_parse_error(); - dbgln("Expected
  • current node, but had <{}>", current_node().local_name()); + dbgln("Expected
  • current node, but had <{}>", current_node()->local_name()); } // 3. Pop elements from the stack of open elements until an li element has been popped from the stack. @@ -2252,7 +2256,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(token.tag_name()); // 2. If the current node is not an HTML element with the same tag name as that of the token, then this is a parse error. - if (current_node().local_name() != token.tag_name()) { + if (current_node()->local_name() != token.tag_name()) { log_parse_error(); } @@ -2279,7 +2283,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(); // 2. If the current node is not an HTML element with the same tag name as that of the token, then this is a parse error. - if (current_node().local_name() != token.tag_name()) { + if (current_node()->local_name() != token.tag_name()) { log_parse_error(); } @@ -2382,7 +2386,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(); // 2. If the current node is not an HTML element with the same tag name as that of the token, then this is a parse error. - if (current_node().local_name() != token.tag_name()) { + if (current_node()->local_name() != token.tag_name()) { log_parse_error(); } @@ -2599,7 +2603,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) // -> A start tag whose tag name is one of: "optgroup", "option" if (token.is_start_tag() && token.tag_name().is_one_of(HTML::TagNames::optgroup, HTML::TagNames::option)) { // If the current node is an option element, then pop the current node off the stack of open elements. - if (current_node().local_name() == HTML::TagNames::option) + if (current_node()->local_name() == HTML::TagNames::option) (void)m_stack_of_open_elements.pop(); // Reconstruct the active formatting elements, if any. @@ -2615,7 +2619,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) // If the stack of open elements has a ruby element in scope, then generate implied end tags. If the current node is not now a ruby element, this is a parse error. if (m_stack_of_open_elements.has_in_scope(HTML::TagNames::ruby)) generate_implied_end_tags(); - if (current_node().local_name() != HTML::TagNames::ruby) + if (current_node()->local_name() != HTML::TagNames::ruby) log_parse_error(); // Insert an HTML element for the token. @@ -2628,7 +2632,7 @@ void HTMLParser::handle_in_body(HTMLToken& token) // If the stack of open elements has a ruby element in scope, then generate implied end tags, except for rtc elements. If the current node is not now a rtc element or a ruby element, this is a parse error. if (m_stack_of_open_elements.has_in_scope(HTML::TagNames::ruby)) generate_implied_end_tags(HTML::TagNames::rtc); - if (current_node().local_name() != HTML::TagNames::rtc || current_node().local_name() != HTML::TagNames::ruby) + if (current_node()->local_name() != HTML::TagNames::rtc || current_node()->local_name() != HTML::TagNames::ruby) log_parse_error(); // Insert an HTML element for the token. @@ -2712,12 +2716,12 @@ void HTMLParser::handle_in_body(HTMLToken& token) generate_implied_end_tags(token.tag_name()); // 2. If node is not the current node, then this is a parse error. - if (node.ptr() != ¤t_node()) { + if (node != current_node()) { log_parse_error(); } // 3. Pop all the nodes from the current node up to node, including node, then stop these steps. - while (¤t_node() != node.ptr()) { + while (current_node() != node) { (void)m_stack_of_open_elements.pop(); } (void)m_stack_of_open_elements.pop(); @@ -2916,8 +2920,8 @@ void HTMLParser::handle_text(HTMLToken& token) } if (token.is_end_of_file()) { log_parse_error(); - if (current_node().local_name() == HTML::TagNames::script) - verify_cast(current_node()).set_already_started(Badge {}, true); + if (current_node()->local_name() == HTML::TagNames::script) + verify_cast(*current_node()).set_already_started(Badge {}, true); (void)m_stack_of_open_elements.pop(); m_insertion_mode = m_original_insertion_mode; process_using_the_rules_for(m_insertion_mode, token); @@ -2938,7 +2942,7 @@ void HTMLParser::handle_text(HTMLToken& token) perform_a_microtask_checkpoint(); // Let script be the current node (which will be a script element). - JS::NonnullGCPtr script = verify_cast(current_node()); + JS::NonnullGCPtr script = verify_cast(*current_node()); // Pop the current node off the stack of open elements. (void)m_stack_of_open_elements.pop(); @@ -3050,28 +3054,28 @@ void HTMLParser::handle_text(HTMLToken& token) void HTMLParser::clear_the_stack_back_to_a_table_context() { - while (!current_node().local_name().is_one_of(HTML::TagNames::table, HTML::TagNames::template_, HTML::TagNames::html)) + while (!current_node()->local_name().is_one_of(HTML::TagNames::table, HTML::TagNames::template_, HTML::TagNames::html)) (void)m_stack_of_open_elements.pop(); - if (current_node().local_name() == HTML::TagNames::html) + if (current_node()->local_name() == HTML::TagNames::html) VERIFY(m_parsing_fragment); } void HTMLParser::clear_the_stack_back_to_a_table_row_context() { - while (!current_node().local_name().is_one_of(HTML::TagNames::tr, HTML::TagNames::template_, HTML::TagNames::html)) + while (!current_node()->local_name().is_one_of(HTML::TagNames::tr, HTML::TagNames::template_, HTML::TagNames::html)) (void)m_stack_of_open_elements.pop(); - if (current_node().local_name() == HTML::TagNames::html) + if (current_node()->local_name() == HTML::TagNames::html) VERIFY(m_parsing_fragment); } void HTMLParser::clear_the_stack_back_to_a_table_body_context() { - while (!current_node().local_name().is_one_of(HTML::TagNames::tbody, HTML::TagNames::tfoot, HTML::TagNames::thead, HTML::TagNames::template_, HTML::TagNames::html)) + while (!current_node()->local_name().is_one_of(HTML::TagNames::tbody, HTML::TagNames::tfoot, HTML::TagNames::thead, HTML::TagNames::template_, HTML::TagNames::html)) (void)m_stack_of_open_elements.pop(); - if (current_node().local_name() == HTML::TagNames::html) + if (current_node()->local_name() == HTML::TagNames::html) VERIFY(m_parsing_fragment); } @@ -3181,10 +3185,10 @@ void HTMLParser::handle_in_row(HTMLToken& token) void HTMLParser::close_the_cell() { generate_implied_end_tags(); - if (!current_node().local_name().is_one_of(HTML::TagNames::td, HTML::TagNames::th)) { + if (!current_node()->local_name().is_one_of(HTML::TagNames::td, HTML::TagNames::th)) { log_parse_error(); } - while (!current_node().local_name().is_one_of(HTML::TagNames::td, HTML::TagNames::th)) + while (!current_node()->local_name().is_one_of(HTML::TagNames::td, HTML::TagNames::th)) (void)m_stack_of_open_elements.pop(); (void)m_stack_of_open_elements.pop(); m_list_of_active_formatting_elements.clear_up_to_the_last_marker(); @@ -3200,7 +3204,7 @@ void HTMLParser::handle_in_cell(HTMLToken& token) } generate_implied_end_tags(); - if (current_node().local_name() != token.tag_name()) { + if (current_node()->local_name() != token.tag_name()) { log_parse_error(); } @@ -3340,7 +3344,7 @@ void HTMLParser::handle_in_table_body(HTMLToken& token) void HTMLParser::handle_in_table(HTMLToken& token) { // A character token, if the current node is table, tbody, template, tfoot, thead, or tr element - if (token.is_character() && current_node().local_name().is_one_of(HTML::TagNames::table, HTML::TagNames::tbody, HTML::TagNames::tfoot, HTML::TagNames::thead, HTML::TagNames::tr)) { + if (token.is_character() && current_node()->local_name().is_one_of(HTML::TagNames::table, HTML::TagNames::tbody, HTML::TagNames::tfoot, HTML::TagNames::thead, HTML::TagNames::tr)) { // Let the pending table character tokens be an empty list of tokens. m_pending_table_character_tokens.clear(); @@ -3600,7 +3604,7 @@ void HTMLParser::handle_in_select(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == HTML::TagNames::option) { - if (current_node().local_name() == HTML::TagNames::option) { + if (current_node()->local_name() == HTML::TagNames::option) { (void)m_stack_of_open_elements.pop(); } (void)insert_html_element(token); @@ -3608,10 +3612,10 @@ void HTMLParser::handle_in_select(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == HTML::TagNames::optgroup) { - if (current_node().local_name() == HTML::TagNames::option) { + if (current_node()->local_name() == HTML::TagNames::option) { (void)m_stack_of_open_elements.pop(); } - if (current_node().local_name() == HTML::TagNames::optgroup) { + if (current_node()->local_name() == HTML::TagNames::optgroup) { (void)m_stack_of_open_elements.pop(); } (void)insert_html_element(token); @@ -3621,11 +3625,11 @@ void HTMLParser::handle_in_select(HTMLToken& token) // -> A start tag whose tag name is "hr" if (token.is_start_tag() && token.tag_name() == HTML::TagNames::hr) { // If the current node is an option element, pop that node from the stack of open elements. - if (current_node().local_name() == HTML::TagNames::option) { + if (current_node()->local_name() == HTML::TagNames::option) { (void)m_stack_of_open_elements.pop(); } // If the current node is an optgroup element, pop that node from the stack of open elements. - if (current_node().local_name() == HTML::TagNames::optgroup) { + if (current_node()->local_name() == HTML::TagNames::optgroup) { (void)m_stack_of_open_elements.pop(); } // Insert an HTML element for the token. Immediately pop the current node off the stack of open elements. @@ -3637,10 +3641,10 @@ void HTMLParser::handle_in_select(HTMLToken& token) } if (token.is_end_tag() && token.tag_name() == HTML::TagNames::optgroup) { - if (current_node().local_name() == HTML::TagNames::option && node_before_current_node().local_name() == HTML::TagNames::optgroup) + if (current_node()->local_name() == HTML::TagNames::option && node_before_current_node()->local_name() == HTML::TagNames::optgroup) (void)m_stack_of_open_elements.pop(); - if (current_node().local_name() == HTML::TagNames::optgroup) { + if (current_node()->local_name() == HTML::TagNames::optgroup) { (void)m_stack_of_open_elements.pop(); } else { log_parse_error(); @@ -3650,7 +3654,7 @@ void HTMLParser::handle_in_select(HTMLToken& token) } if (token.is_end_tag() && token.tag_name() == HTML::TagNames::option) { - if (current_node().local_name() == HTML::TagNames::option) { + if (current_node()->local_name() == HTML::TagNames::option) { (void)m_stack_of_open_elements.pop(); } else { log_parse_error(); @@ -3726,7 +3730,7 @@ void HTMLParser::handle_in_caption(HTMLToken& token) generate_implied_end_tags(); - if (current_node().local_name() != HTML::TagNames::caption) + if (current_node()->local_name() != HTML::TagNames::caption) log_parse_error(); m_stack_of_open_elements.pop_until_an_element_with_tag_name_has_been_popped(HTML::TagNames::caption); @@ -3746,7 +3750,7 @@ void HTMLParser::handle_in_caption(HTMLToken& token) generate_implied_end_tags(); - if (current_node().local_name() != HTML::TagNames::caption) + if (current_node()->local_name() != HTML::TagNames::caption) log_parse_error(); m_stack_of_open_elements.pop_until_an_element_with_tag_name_has_been_popped(HTML::TagNames::caption); @@ -3795,7 +3799,7 @@ void HTMLParser::handle_in_column_group(HTMLToken& token) } if (token.is_end_tag() && token.tag_name() == HTML::TagNames::colgroup) { - if (current_node().local_name() != HTML::TagNames::colgroup) { + if (current_node()->local_name() != HTML::TagNames::colgroup) { log_parse_error(); return; } @@ -3820,7 +3824,7 @@ void HTMLParser::handle_in_column_group(HTMLToken& token) return; } - if (current_node().local_name() != HTML::TagNames::colgroup) { + if (current_node()->local_name() != HTML::TagNames::colgroup) { log_parse_error(); return; } @@ -3950,7 +3954,7 @@ void HTMLParser::handle_in_frameset(HTMLToken& token) // -> An end tag whose tag name is "frameset" if (token.is_end_tag() && token.tag_name() == HTML::TagNames::frameset) { // If the current node is the root html element, then this is a parse error; ignore the token. (fragment case) - if (current_node().is_document_element()) { + if (current_node()->is_document_element()) { log_parse_error(); return; } @@ -3960,7 +3964,7 @@ void HTMLParser::handle_in_frameset(HTMLToken& token) // If the parser was not created as part of the HTML fragment parsing algorithm (fragment case), // and the current node is no longer a frameset element, then switch the insertion mode to "after frameset". - if (!m_parsing_fragment && current_node().local_name() != HTML::TagNames::frameset) { + if (!m_parsing_fragment && current_node()->local_name() != HTML::TagNames::frameset) { m_insertion_mode = InsertionMode::AfterFrameset; } return; @@ -3989,7 +3993,7 @@ void HTMLParser::handle_in_frameset(HTMLToken& token) // -> An end-of-file token if (token.is_end_of_file()) { // If the current node is not the root html element, then this is a parse error. - if (!current_node().is_document_element()) { + if (!current_node()->is_document_element()) { log_parse_error(); } @@ -4118,9 +4122,9 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token) log_parse_error(); // While the current node is not a MathML text integration point, an HTML integration point, or an element in the HTML namespace, pop elements from the stack of open elements. - while (!is_mathml_text_integration_point(current_node()) - && !is_html_integration_point(current_node()) - && current_node().namespace_uri() != Namespace::HTML) { + while (!is_mathml_text_integration_point(*current_node()) + && !is_html_integration_point(*current_node()) + && current_node()->namespace_uri() != Namespace::HTML) { (void)m_stack_of_open_elements.pop(); } @@ -4132,13 +4136,13 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token) // Any other start tag if (token.is_start_tag()) { // If the adjusted current node is an element in the MathML namespace, adjust MathML attributes for the token. (This fixes the case of MathML attributes that are not all lowercase.) - if (adjusted_current_node().namespace_uri() == Namespace::MathML) { + if (adjusted_current_node()->namespace_uri() == Namespace::MathML) { adjust_mathml_attributes(token); } // If the adjusted current node is an element in the SVG namespace, and the token's tag name is one of the ones in the first column of the // following table, change the tag name to the name given in the corresponding cell in the second column. (This fixes the case of SVG // elements that are not all lowercase.) - else if (adjusted_current_node().namespace_uri() == Namespace::SVG) { + else if (adjusted_current_node()->namespace_uri() == Namespace::SVG) { adjust_svg_tag_names(token); // If the adjusted current node is an element in the SVG namespace, adjust SVG attributes for the token. (This fixes the case of SVG attributes that are not all lowercase.) adjust_svg_attributes(token); @@ -4148,14 +4152,14 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token) adjust_foreign_attributes(token); // Insert a foreign element for the token, with adjusted current node's namespace and false. - (void)insert_foreign_element(token, adjusted_current_node().namespace_uri(), OnlyAddToElementStack::No); + (void)insert_foreign_element(token, adjusted_current_node()->namespace_uri(), OnlyAddToElementStack::No); // If the token has its self-closing flag set, then run the appropriate steps from the following list: if (token.is_self_closing()) { // -> If the token's tag name is "script", and the new current node is in the SVG namespace - if (token.tag_name() == SVG::TagNames::script && current_node().namespace_uri() == Namespace::SVG) { - auto& script_element = verify_cast(current_node()); + if (token.tag_name() == SVG::TagNames::script && current_node()->namespace_uri() == Namespace::SVG) { + auto& script_element = verify_cast(*current_node()); script_element.set_source_line_number({}, token.start_position().line + 1); // FIXME: This +1 is incorrect for script tags whose script does not start on a new line // Acknowledge the token's self-closing flag, and then act as described in the steps for a "script" end tag below. @@ -4174,7 +4178,7 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token) } // -> An end tag whose tag name is "script", if the current node is an SVG script element - if (token.is_end_tag() && current_node().namespace_uri() == Namespace::SVG && current_node().tag_name() == SVG::TagNames::script) { + if (token.is_end_tag() && current_node()->namespace_uri() == Namespace::SVG && current_node()->tag_name() == SVG::TagNames::script) { ScriptEndTag: // Pop the current node off the stack of open elements. auto& script_element = verify_cast(*m_stack_of_open_elements.pop()); @@ -4224,7 +4228,7 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token) // 4. If node's tag name, converted to ASCII lowercase, is the same as the tag name of the token, pop elements from the stack // of open elements until node has been popped from the stack, and then return. if (node->tag_name().equals_ignoring_ascii_case(token.tag_name())) { - while (¤t_node() != node.ptr()) + while (current_node() != node) (void)m_stack_of_open_elements.pop(); (void)m_stack_of_open_elements.pop(); return; diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h index e240153ca76..270aae63e3f 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h @@ -148,9 +148,9 @@ private: }; JS::NonnullGCPtr insert_foreign_element(HTMLToken const&, Optional const& namespace_, OnlyAddToElementStack); JS::NonnullGCPtr insert_html_element(HTMLToken const&); - DOM::Element& current_node(); - DOM::Element& adjusted_current_node(); - DOM::Element& node_before_current_node(); + [[nodiscard]] JS::GCPtr current_node(); + [[nodiscard]] JS::GCPtr adjusted_current_node(); + [[nodiscard]] JS::GCPtr node_before_current_node(); void insert_character(u32 data); void insert_comment(HTMLToken&); void reconstruct_the_active_formatting_elements(); diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp index c7293c67c18..fca8292ec29 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLTokenizer.cpp @@ -433,7 +433,9 @@ _StartOfFunction: if (consume_next_if_match("[CDATA["sv)) { // We keep the parser optional so that syntax highlighting can be lexer-only. // The parser registers itself with the lexer it creates. - if (m_parser != nullptr && m_parser->adjusted_current_node().namespace_uri() != Namespace::HTML) { + if (m_parser != nullptr + && m_parser->adjusted_current_node() + && m_parser->adjusted_current_node()->namespace_uri() != Namespace::HTML) { SWITCH_TO(CDATASection); } else { create_new_token(HTMLToken::Type::Comment);