LibWeb: Properly propagate errors for Node set_text_content

This function was supposed to throw errors even before the TrustedTypes
spec thanks to the CharacterData replaceData call but had a MUST.

This changes this to ensure this function can throw an error
This commit is contained in:
Tete17 2025-08-08 02:25:57 +02:00 committed by Luke Wilde
parent 887537b061
commit 2fa84f1683
7 changed files with 19 additions and 19 deletions

View File

@ -296,7 +296,7 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_media_document(HTML::Nav
};
auto style_element = TRY(DOM::create_element(document, HTML::TagNames::style, Namespace::HTML));
style_element->set_text_content(R"~~~(
MUST(style_element->set_text_content(R"~~~(
:root {
background-color: #222;
}
@ -310,7 +310,7 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_media_document(HTML::Nav
img {
background-color: #fff;
}
)~~~"_utf16);
)~~~"_utf16));
TRY(document->head()->append_child(style_element));
auto url_string = document->url_string();

View File

@ -199,7 +199,7 @@ Optional<Utf16String> Node::text_content() const
}
// https://dom.spec.whatwg.org/#ref-for-dom-node-textcontent%E2%91%A0
void Node::set_text_content(Optional<Utf16String> const& maybe_content)
WebIDL::ExceptionOr<void> Node::set_text_content(Optional<Utf16String> const& maybe_content)
{
// The textContent setter steps are to, if the given value is null, act as if it was the empty string instead,
// and then do as described below, switching on the interface this implements:
@ -209,20 +209,19 @@ void Node::set_text_content(Optional<Utf16String> const& maybe_content)
if (is<DocumentFragment>(this) || is<Element>(this)) {
// OPTIMIZATION: Replacing nothing with nothing is a no-op. Avoid all invalidation in this case.
if (!first_child() && content.is_empty()) {
return;
return {};
}
string_replace_all(content);
}
// If CharacterData, replace data with node this, offset 0, count thiss length, and data the given value.
else if (auto* character_data = as_if<CharacterData>(*this)) {
MUST(character_data->replace_data(0, character_data->length_in_utf16_code_units(), content));
TRY(character_data->replace_data(0, character_data->length_in_utf16_code_units(), content));
}
// If Attr, set an existing attribute value with this and the given value.
else if (auto* attribute = as_if<Attr>(*this)) {
// FIXME: This should propagate
MUST(attribute->set_value(content.to_utf8_but_should_be_ported_to_utf16()));
TRY(attribute->set_value(content.to_utf8_but_should_be_ported_to_utf16()));
}
// Otherwise, do nothing.
@ -233,6 +232,7 @@ void Node::set_text_content(Optional<Utf16String> const& maybe_content)
}
document().bump_dom_tree_version();
return {};
}
// https://dom.spec.whatwg.org/#dom-node-normalize

View File

@ -280,7 +280,7 @@ public:
Utf16String descendant_text_content() const;
Optional<Utf16String> text_content() const;
void set_text_content(Optional<Utf16String> const&);
WebIDL::ExceptionOr<void> set_text_content(Optional<Utf16String> const&);
WebIDL::ExceptionOr<void> normalize();

View File

@ -243,7 +243,7 @@ WebIDL::ExceptionOr<void> HTMLDetailsElement::create_shadow_tree_if_needed()
// The third child element is either a link or style element with the following styles for the default summary:
auto style = TRY(DOM::create_element(document(), HTML::TagNames::style, Namespace::HTML));
style->set_text_content(R"~~~(
MUST(style->set_text_content(R"~~~(
:host summary {
display: list-item;
counter-increment: list-item 0;
@ -252,7 +252,7 @@ WebIDL::ExceptionOr<void> HTMLDetailsElement::create_shadow_tree_if_needed()
:host([open]) summary {
list-style-type: disclosure-open;
}
)~~~"_utf16);
)~~~"_utf16));
MUST(shadow_root->append_child(style));
m_summary_slot = static_cast<HTML::HTMLSlotElement&>(*summary_slot);

View File

@ -1082,7 +1082,7 @@ void HTMLInputElement::create_text_input_shadow_tree()
m_text_node = realm().create<DOM::Text>(document(), Utf16String {});
if (type_state() == TypeAttributeState::Password)
m_text_node->set_is_password_input({}, true);
m_text_node->set_text_content(m_value);
MUST(m_text_node->set_text_content(m_value));
handle_maxlength_attribute();
MUST(m_inner_text_element->append_child(*m_text_node));
@ -1225,15 +1225,15 @@ void HTMLInputElement::update_file_input_shadow_tree()
return;
auto files_label = has_attribute(HTML::AttributeNames::multiple) ? "files"sv : "file"sv;
m_file_button->set_text_content(Utf16String::formatted("Select {}...", files_label));
MUST(m_file_button->set_text_content(Utf16String::formatted("Select {}...", files_label)));
if (m_selected_files && m_selected_files->length() > 0) {
if (m_selected_files->length() == 1)
m_file_label->set_text_content(Utf16String::from_utf8(m_selected_files->item(0)->name()));
MUST(m_file_label->set_text_content(Utf16String::from_utf8(m_selected_files->item(0)->name())));
else
m_file_label->set_text_content(Utf16String::formatted("{} files selected.", m_selected_files->length()));
MUST(m_file_label->set_text_content(Utf16String::formatted("{} files selected.", m_selected_files->length())));
} else {
m_file_label->set_text_content(Utf16String::formatted("No {} selected.", files_label));
MUST(m_file_label->set_text_content(Utf16String::formatted("No {} selected.", files_label)));
}
}

View File

@ -633,7 +633,7 @@ void HTMLSelectElement::update_inner_text_element()
// Update inner text element to the label of the selected option
for (auto const& option_element : m_cached_list_of_options) {
if (option_element->selected()) {
m_inner_text_element->set_text_content(Infra::strip_and_collapse_whitespace(Utf16String::from_utf8(option_element->label())));
MUST(m_inner_text_element->set_text_content(Infra::strip_and_collapse_whitespace(Utf16String::from_utf8(option_element->label()))));
return;
}
}

View File

@ -117,7 +117,7 @@ void HTMLTextAreaElement::reset_algorithm()
set_raw_value(child_text_content());
if (m_text_node) {
m_text_node->set_text_content(m_raw_value);
MUST(m_text_node->set_text_content(m_raw_value));
update_placeholder_visibility();
}
}
@ -350,7 +350,7 @@ void HTMLTextAreaElement::create_shadow_tree_if_needed()
m_text_node = realm().create<DOM::Text>(document(), Utf16String {});
// NOTE: If `children_changed()` was called before now, `m_raw_value` will hold the text content.
// Otherwise, it will get filled in whenever that does get called.
m_text_node->set_text_content(m_raw_value);
MUST(m_text_node->set_text_content(m_raw_value));
handle_maxlength_attribute();
MUST(m_inner_text_element->append_child(*m_text_node));
@ -403,7 +403,7 @@ void HTMLTextAreaElement::children_changed(ChildrenChangedMetadata const* metada
if (!m_dirty_value) {
set_raw_value(child_text_content());
if (m_text_node)
m_text_node->set_text_content(m_raw_value);
MUST(m_text_node->set_text_content(m_raw_value));
update_placeholder_visibility();
}
}