1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:17:45 +00:00

LibWeb: Port Element::local_name and TagNames from Deprecated String

Which pretty much needs to be done together due to the amount of places
where they are compared together.

This also involves porting over StackOfOpenElements over to FlyString
from DeprecatedFly string to prevent a gazillion calls to
`.to_deprecated_fly_string` calls in HTMLParser.
This commit is contained in:
Shannon Booth 2023-10-01 20:07:44 +13:00 committed by Sam Atkins
parent bbfe0d3a82
commit 9303e9e76f
30 changed files with 163 additions and 158 deletions

View file

@ -662,7 +662,7 @@ JS::NonnullGCPtr<DOM::Element> HTMLParser::create_element_for(HTMLToken const& t
is_value = String::from_utf8(is_value_deprecated_string).release_value_but_fixme_should_propagate_errors();
// 6. Let definition be the result of looking up a custom element definition given document, given namespace, local name, and is.
auto definition = document->lookup_custom_element_definition(namespace_, local_name, is_value);
auto definition = document->lookup_custom_element_definition(namespace_, local_name.to_deprecated_fly_string(), is_value);
// 7. If definition is non-null and the parser was not created as part of the HTML fragment parsing algorithm, then let will execute script be true. Otherwise, let it be false.
bool will_execute_script = definition && !m_parsing_fragment;
@ -813,7 +813,7 @@ void HTMLParser::handle_before_head(HTMLToken& token)
}
AnythingElse:
m_head_element = JS::make_handle(verify_cast<HTMLHeadElement>(*insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head))));
m_head_element = JS::make_handle(verify_cast<HTMLHeadElement>(*insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head.to_deprecated_fly_string()))));
m_insertion_mode = InsertionMode::InHead;
process_using_the_rules_for(InsertionMode::InHead, token);
return;
@ -1107,12 +1107,12 @@ void HTMLParser::handle_after_head(HTMLToken& token)
}
AnythingElse:
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::body));
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::body.to_deprecated_fly_string()));
m_insertion_mode = InsertionMode::InBody;
process_using_the_rules_for(m_insertion_mode, token);
}
void HTMLParser::generate_implied_end_tags(DeprecatedFlyString const& exception)
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))
(void)m_stack_of_open_elements.pop();
@ -1242,7 +1242,7 @@ Create:
VERIFY(!entry->is_marker());
// FIXME: Hold on to the real token!
auto new_element = insert_html_element(HTMLToken::make_start_tag(entry->element->local_name()));
auto new_element = insert_html_element(HTMLToken::make_start_tag(entry->element->local_name().to_deprecated_fly_string()));
// 9. Replace the entry for entry in the list with an entry for new element.
m_list_of_active_formatting_elements.entries().at(index).element = JS::make_handle(new_element);
@ -1256,7 +1256,7 @@ Create:
HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_algorithm(HTMLToken& token)
{
// 1. Let subject be token's tag name.
auto& subject = token.tag_name();
auto const& subject = token.tag_name();
// 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,
@ -1383,7 +1383,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a
// 6. Create an element for the token for which the element node was created,
// in the HTML namespace, with common ancestor as the intended parent;
// FIXME: hold onto the real token
auto element = create_element_for(HTMLToken::make_start_tag(node->local_name()), Namespace::HTML, *common_ancestor);
auto element = create_element_for(HTMLToken::make_start_tag(node->local_name().to_deprecated_fly_string()), Namespace::HTML, *common_ancestor);
// replace the entry for node in the list of active formatting elements with an entry for the new element,
m_list_of_active_formatting_elements.replace(*node, *element);
// replace the entry for node in the stack of open elements with an entry for the new element,
@ -1412,7 +1412,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a
// 15. Create an element for the token for which formatting element was created,
// in the HTML namespace, with furthest block as the intended parent.
// FIXME: hold onto the real token
auto element = create_element_for(HTMLToken::make_start_tag(formatting_element->local_name()), Namespace::HTML, *furthest_block);
auto element = create_element_for(HTMLToken::make_start_tag(formatting_element->local_name().to_deprecated_fly_string()), Namespace::HTML, *furthest_block);
// 16. Take all of the child nodes of furthest block and append them to the element created in the last step.
for (auto& child : furthest_block->children_as_vector())
@ -1437,7 +1437,7 @@ HTMLParser::AdoptionAgencyAlgorithmOutcome HTMLParser::run_the_adoption_agency_a
}
// https://html.spec.whatwg.org/multipage/parsing.html#special
bool HTMLParser::is_special_tag(DeprecatedFlyString const& tag_name, DeprecatedFlyString const& namespace_)
bool HTMLParser::is_special_tag(FlyString const& tag_name, DeprecatedFlyString const& namespace_)
{
if (namespace_ == Namespace::HTML) {
return tag_name.is_one_of(
@ -1846,7 +1846,7 @@ void HTMLParser::handle_in_body(HTMLToken& token)
if (token.is_end_tag() && token.tag_name() == HTML::TagNames::p) {
if (!m_stack_of_open_elements.has_in_button_scope(HTML::TagNames::p)) {
log_parse_error();
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::p));
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::p.to_deprecated_fly_string()));
}
close_a_p_element();
return;
@ -2708,7 +2708,7 @@ void HTMLParser::handle_in_table_body(HTMLToken& token)
if (token.is_start_tag() && token.tag_name().is_one_of(HTML::TagNames::th, HTML::TagNames::td)) {
log_parse_error();
clear_the_stack_back_to_a_table_body_context();
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::tr));
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::tr.to_deprecated_fly_string()));
m_insertion_mode = InsertionMode::InRow;
process_using_the_rules_for(m_insertion_mode, token);
return;
@ -2811,7 +2811,7 @@ void HTMLParser::handle_in_table(HTMLToken& token)
clear_the_stack_back_to_a_table_context();
// Insert an HTML element for a "colgroup" start tag token with no attributes, then switch the insertion mode to "in column group".
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::colgroup));
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::colgroup.to_deprecated_fly_string()));
m_insertion_mode = InsertionMode::InColumnGroup;
// Reprocess the current token.
@ -2836,7 +2836,7 @@ void HTMLParser::handle_in_table(HTMLToken& token)
clear_the_stack_back_to_a_table_context();
// Insert an HTML element for a "tbody" start tag token with no attributes, then switch the insertion mode to "in table body".
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::tbody));
(void)insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::tbody.to_deprecated_fly_string()));
m_insertion_mode = InsertionMode::InTableBody;
// Reprocess the current token.
@ -3514,7 +3514,7 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token)
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_() == Namespace::SVG) {
if (token.tag_name().to_deprecated_fly_string() == SVG::TagNames::script && current_node().namespace_() == Namespace::SVG) {
// Acknowledge the token's self-closing flag, and then act as described in the steps for a "script" end tag below.
token.acknowledge_self_closing_flag_if_set();
goto ScriptEndTag;
@ -3564,7 +3564,7 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token)
JS::GCPtr<DOM::Element> node = current_node();
// FIXME: Not sure if this is the correct to_lowercase, as the specification says "to ASCII lowercase"
// 2. If node's tag name, converted to ASCII lowercase, is not the same as the tag name of the token, then this is a parse error.
if (node->tag_name().to_lowercase() != token.tag_name())
if (node->tag_name().to_lowercase() != token.tag_name().to_deprecated_fly_string())
log_parse_error();
// 3. Loop: If node is the topmost element in the stack of open elements, then return. (fragment case)
@ -3576,7 +3576,7 @@ void HTMLParser::process_using_the_rules_for_foreign_content(HTMLToken& token)
// FIXME: See the above FIXME
// 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().to_lowercase() == token.tag_name()) {
if (node->tag_name().to_lowercase() == token.tag_name().to_deprecated_fly_string()) {
while (&current_node() != node.ptr())
(void)m_stack_of_open_elements.pop();
(void)m_stack_of_open_elements.pop();
@ -3898,7 +3898,7 @@ DeprecatedString HTMLParser::serialize_html_fragment(DOM::Node const& node)
DeprecatedString tag_name;
if (element.namespace_().is_one_of(Namespace::HTML, Namespace::MathML, Namespace::SVG))
tag_name = element.local_name();
tag_name = element.local_name().to_deprecated_fly_string();
else
tag_name = element.qualified_name();

View file

@ -68,7 +68,7 @@ public:
InsertionMode insertion_mode() const { return m_insertion_mode; }
static bool is_special_tag(DeprecatedFlyString const& tag_name, DeprecatedFlyString const& namespace_);
static bool is_special_tag(FlyString const& tag_name, DeprecatedFlyString const& namespace_);
HTMLTokenizer& tokenizer() { return m_tokenizer; }
@ -118,7 +118,7 @@ private:
void stop_parsing() { m_stop_parsing = true; }
void generate_implied_end_tags(DeprecatedFlyString const& exception = {});
void generate_implied_end_tags(FlyString const& exception = {});
void generate_all_implied_end_tags_thoroughly();
JS::NonnullGCPtr<DOM::Element> create_element_for(HTMLToken const&, DeprecatedFlyString const& namespace_, DOM::Node& intended_parent);

View file

@ -9,6 +9,7 @@
#include <AK/DeprecatedFlyString.h>
#include <AK/DeprecatedString.h>
#include <AK/FlyString.h>
#include <AK/Function.h>
#include <AK/OwnPtr.h>
#include <AK/Types.h>
@ -145,10 +146,10 @@ public:
m_string_data = move(comment);
}
DeprecatedFlyString const& tag_name() const
FlyString tag_name() const
{
VERIFY(is_start_tag() || is_end_tag());
return m_string_data;
return MUST(FlyString::from_deprecated_fly_string(m_string_data));
}
void set_tag_name(DeprecatedString name)
@ -275,7 +276,7 @@ public:
void adjust_tag_name(DeprecatedFlyString const& old_name, DeprecatedFlyString const& new_name)
{
VERIFY(is_start_tag() || is_end_tag());
if (old_name == tag_name())
if (old_name == tag_name().to_deprecated_fly_string())
set_tag_name(new_name);
}

View file

@ -2845,7 +2845,7 @@ void HTMLTokenizer::switch_to(Badge<HTMLParser>, State new_state)
void HTMLTokenizer::will_emit(HTMLToken& token)
{
if (token.is_start_tag())
m_last_emitted_start_tag_name = token.tag_name();
m_last_emitted_start_tag_name = token.tag_name().to_deprecated_fly_string();
auto is_start_or_end_tag = token.type() == HTMLToken::Type::StartTag || token.type() == HTMLToken::Type::EndTag;
token.set_end_position({}, nth_last_position(is_start_or_end_tag ? 1 : 0));
@ -2856,7 +2856,7 @@ bool HTMLTokenizer::current_end_tag_token_is_appropriate() const
VERIFY(m_current_token.is_end_tag());
if (!m_last_emitted_start_tag_name.has_value())
return false;
return m_current_token.tag_name() == m_last_emitted_start_tag_name.value();
return m_current_token.tag_name().to_deprecated_fly_string() == m_last_emitted_start_tag_name.value();
}
bool HTMLTokenizer::consumed_as_part_of_an_attribute() const

View file

@ -37,7 +37,7 @@ bool ListOfActiveFormattingElements::contains(const DOM::Element& element) const
return false;
}
DOM::Element* ListOfActiveFormattingElements::last_element_with_tag_name_before_marker(DeprecatedFlyString const& tag_name)
DOM::Element* ListOfActiveFormattingElements::last_element_with_tag_name_before_marker(FlyString const& tag_name)
{
for (ssize_t i = m_entries.size() - 1; i >= 0; --i) {
auto& entry = m_entries[i];

View file

@ -36,7 +36,7 @@ public:
Vector<Entry> const& entries() const { return m_entries; }
Vector<Entry>& entries() { return m_entries; }
DOM::Element* last_element_with_tag_name_before_marker(DeprecatedFlyString const& tag_name);
DOM::Element* last_element_with_tag_name_before_marker(FlyString const& tag_name);
void clear_up_to_the_last_marker();

View file

@ -10,7 +10,7 @@
namespace Web::HTML {
static Vector<DeprecatedFlyString> s_base_list { "applet", "caption", "html", "table", "td", "th", "marquee", "object", "template" };
static Vector<FlyString> s_base_list { "applet"_fly_string, "caption"_fly_string, "html"_fly_string, "table"_fly_string, "td"_fly_string, "th"_fly_string, "marquee"_fly_string, "object"_fly_string, "template"_fly_string };
StackOfOpenElements::~StackOfOpenElements() = default;
@ -20,7 +20,7 @@ void StackOfOpenElements::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(element);
}
bool StackOfOpenElements::has_in_scope_impl(DeprecatedFlyString const& tag_name, Vector<DeprecatedFlyString> const& list) const
bool StackOfOpenElements::has_in_scope_impl(FlyString const& tag_name, Vector<FlyString> const& list) const
{
for (auto const& element : m_elements.in_reverse()) {
if (element->local_name() == tag_name)
@ -31,12 +31,12 @@ bool StackOfOpenElements::has_in_scope_impl(DeprecatedFlyString const& tag_name,
VERIFY_NOT_REACHED();
}
bool StackOfOpenElements::has_in_scope(DeprecatedFlyString const& tag_name) const
bool StackOfOpenElements::has_in_scope(FlyString const& tag_name) const
{
return has_in_scope_impl(tag_name, s_base_list);
}
bool StackOfOpenElements::has_in_scope_impl(const DOM::Element& target_node, Vector<DeprecatedFlyString> const& list) const
bool StackOfOpenElements::has_in_scope_impl(const DOM::Element& target_node, Vector<FlyString> const& list) const
{
for (auto& element : m_elements.in_reverse()) {
if (element.ptr() == &target_node)
@ -52,23 +52,23 @@ bool StackOfOpenElements::has_in_scope(const DOM::Element& target_node) const
return has_in_scope_impl(target_node, s_base_list);
}
bool StackOfOpenElements::has_in_button_scope(DeprecatedFlyString const& tag_name) const
bool StackOfOpenElements::has_in_button_scope(FlyString const& tag_name) const
{
auto list = s_base_list;
list.append("button");
list.append("button"_fly_string);
return has_in_scope_impl(tag_name, list);
}
bool StackOfOpenElements::has_in_table_scope(DeprecatedFlyString const& tag_name) const
bool StackOfOpenElements::has_in_table_scope(FlyString const& tag_name) const
{
return has_in_scope_impl(tag_name, { "html", "table", "template" });
return has_in_scope_impl(tag_name, { "html"_fly_string, "table"_fly_string, "template"_fly_string });
}
bool StackOfOpenElements::has_in_list_item_scope(DeprecatedFlyString const& tag_name) const
bool StackOfOpenElements::has_in_list_item_scope(FlyString const& tag_name) const
{
auto list = s_base_list;
list.append("ol");
list.append("ul");
list.append("ol"_fly_string);
list.append("ul"_fly_string);
return has_in_scope_impl(tag_name, list);
}
@ -78,7 +78,7 @@ bool StackOfOpenElements::has_in_list_item_scope(DeprecatedFlyString const& tag_
// - optgroup in the HTML namespace
// - option in the HTML namespace
// NOTE: In this case it's "all element types _except_"
bool StackOfOpenElements::has_in_select_scope(DeprecatedFlyString const& tag_name) const
bool StackOfOpenElements::has_in_select_scope(FlyString const& tag_name) const
{
// https://html.spec.whatwg.org/multipage/parsing.html#has-an-element-in-the-specific-scope
// 1. Initialize node to be the current node (the bottommost node of the stack).
@ -106,7 +106,7 @@ bool StackOfOpenElements::contains(const DOM::Element& element) const
return false;
}
bool StackOfOpenElements::contains(DeprecatedFlyString const& tag_name) const
bool StackOfOpenElements::contains(FlyString const& tag_name) const
{
for (auto& element_on_stack : m_elements) {
if (element_on_stack->local_name() == tag_name)
@ -115,7 +115,7 @@ bool StackOfOpenElements::contains(DeprecatedFlyString const& tag_name) const
return false;
}
void StackOfOpenElements::pop_until_an_element_with_tag_name_has_been_popped(DeprecatedFlyString const& tag_name)
void StackOfOpenElements::pop_until_an_element_with_tag_name_has_been_popped(FlyString const& tag_name)
{
while (m_elements.last()->local_name() != tag_name)
(void)pop();
@ -134,7 +134,7 @@ JS::GCPtr<DOM::Element> StackOfOpenElements::topmost_special_node_below(DOM::Ele
return found_element.ptr();
}
StackOfOpenElements::LastElementResult StackOfOpenElements::last_element_with_tag_name(DeprecatedFlyString const& tag_name)
StackOfOpenElements::LastElementResult StackOfOpenElements::last_element_with_tag_name(FlyString const& tag_name)
{
for (ssize_t i = m_elements.size() - 1; i >= 0; --i) {
auto& element = m_elements[i];

View file

@ -35,21 +35,21 @@ public:
const DOM::Element& current_node() const { return *m_elements.last(); }
DOM::Element& current_node() { return *m_elements.last(); }
bool has_in_scope(DeprecatedFlyString const& tag_name) const;
bool has_in_button_scope(DeprecatedFlyString const& tag_name) const;
bool has_in_table_scope(DeprecatedFlyString const& tag_name) const;
bool has_in_list_item_scope(DeprecatedFlyString const& tag_name) const;
bool has_in_select_scope(DeprecatedFlyString const& tag_name) const;
bool has_in_scope(FlyString const& tag_name) const;
bool has_in_button_scope(FlyString const& tag_name) const;
bool has_in_table_scope(FlyString const& tag_name) const;
bool has_in_list_item_scope(FlyString const& tag_name) const;
bool has_in_select_scope(FlyString const& tag_name) const;
bool has_in_scope(const DOM::Element&) const;
bool contains(const DOM::Element&) const;
bool contains(DeprecatedFlyString const& tag_name) const;
bool contains(FlyString const& tag_name) const;
auto const& elements() const { return m_elements; }
auto& elements() { return m_elements; }
void pop_until_an_element_with_tag_name_has_been_popped(DeprecatedFlyString const&);
void pop_until_an_element_with_tag_name_has_been_popped(FlyString const&);
JS::GCPtr<DOM::Element> topmost_special_node_below(DOM::Element const&);
@ -57,14 +57,14 @@ public:
JS::GCPtr<DOM::Element> element;
ssize_t index;
};
LastElementResult last_element_with_tag_name(DeprecatedFlyString const&);
LastElementResult last_element_with_tag_name(FlyString const&);
JS::GCPtr<DOM::Element> element_immediately_above(DOM::Element const&);
void visit_edges(JS::Cell::Visitor&);
private:
bool has_in_scope_impl(DeprecatedFlyString const& tag_name, Vector<DeprecatedFlyString> const&) const;
bool has_in_scope_impl(const DOM::Element& target_node, Vector<DeprecatedFlyString> const&) const;
bool has_in_scope_impl(FlyString const& tag_name, Vector<FlyString> const&) const;
bool has_in_scope_impl(const DOM::Element& target_node, Vector<FlyString> const&) const;
Vector<JS::NonnullGCPtr<DOM::Element>> m_elements;
};