diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 42a9749be97..40287ac8d9a 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -1004,13 +1004,13 @@ String Document::title() const // element that is a child of the document element. if (auto const* document_element = this->document_element(); is(document_element)) { if (auto const* title_element = document_element->first_child_of_type()) - value = title_element->child_text_content(); + value = title_element->child_text_content().to_utf8_but_should_be_ported_to_utf16(); } // 2. Otherwise, let value be the child text content of the title element, or the empty string if the title element // is null. else if (auto title_element = this->title_element()) { - value = title_element->text_content().value_or(String {}); + value = title_element->text_content().value_or({}).to_utf8_but_should_be_ported_to_utf16(); } // 3. Strip and collapse ASCII whitespace in value. @@ -1045,7 +1045,7 @@ WebIDL::ExceptionOr Document::set_title(String const& title) } // 3. String replace all with the given value within element. - element->string_replace_all(title); + element->string_replace_all(Utf16String::from_utf8(title)); } // -> If the document element is in the HTML namespace @@ -1074,7 +1074,7 @@ WebIDL::ExceptionOr Document::set_title(String const& title) } // 4. String replace all with the given value within element. - element->string_replace_all(title); + element->string_replace_all(Utf16String::from_utf8(title)); } // -> Otherwise diff --git a/Libraries/LibWeb/DOM/DocumentLoading.cpp b/Libraries/LibWeb/DOM/DocumentLoading.cpp index 0ca2acfd854..a82e7efb3da 100644 --- a/Libraries/LibWeb/DOM/DocumentLoading.cpp +++ b/Libraries/LibWeb/DOM/DocumentLoading.cpp @@ -309,7 +309,7 @@ static WebIDL::ExceptionOr> load_media_document(HTML::Nav img { background-color: #fff; } - )~~~"_string); + )~~~"_utf16); TRY(document->head()->append_child(style_element)); auto url_string = document->url_string(); diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index d83d277d14a..bdeead59784 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -165,18 +165,20 @@ Optional Node::alternative_text() const } // https://dom.spec.whatwg.org/#concept-descendant-text-content -String Node::descendant_text_content() const +Utf16String Node::descendant_text_content() const { - StringBuilder builder; + StringBuilder builder(StringBuilder::Mode::UTF16); + for_each_in_subtree_of_type([&](auto& text_node) { builder.append(text_node.data()); return TraversalDecision::Continue; }); - return builder.to_string_without_validation(); + + return builder.to_utf16_string_without_validation(); } // https://dom.spec.whatwg.org/#dom-node-textcontent -Optional Node::text_content() const +Optional Node::text_content() const { // The textContent getter steps are to return the following, switching on the interface this implements: @@ -185,23 +187,23 @@ Optional Node::text_content() const return descendant_text_content(); // If CharacterData, return this’s data. - if (is(this)) - return static_cast(*this).data().to_utf8_but_should_be_ported_to_utf16(); + if (auto const* character_data = as_if(*this)) + return character_data->data(); // If Attr node, return this's value. - if (is(*this)) - return static_cast(*this).value(); + if (auto const* attribute = as_if(*this)) + return Utf16String::from_utf8(attribute->value()); // Otherwise, return null return {}; } // https://dom.spec.whatwg.org/#ref-for-dom-node-textcontent%E2%91%A0 -void Node::set_text_content(Optional const& maybe_content) +void Node::set_text_content(Optional 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: - auto content = maybe_content.value_or(String {}); + auto content = maybe_content.value_or({}); // If DocumentFragment or Element, string replace all with the given value within this. if (is(this) || is(this)) { @@ -213,17 +215,13 @@ void Node::set_text_content(Optional const& maybe_content) } // If CharacterData, replace data with node this, offset 0, count this’s length, and data the given value. - else if (is(this)) { - auto* character_data_node = as(this); - character_data_node->set_data(Utf16String::from_utf8(content)); - - // FIXME: CharacterData::set_data is not spec compliant. Make this match the spec when set_data becomes spec compliant. - // Do note that this will make this function able to throw an exception. + else if (auto* character_data = as_if(*this)) { + MUST(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. - if (is(*this)) { - static_cast(*this).set_value(content); + else if (auto* attribute = as_if(*this)) { + attribute->set_value(content.to_utf8_but_should_be_ported_to_utf16()); } // Otherwise, do nothing. @@ -524,21 +522,21 @@ void Node::invalidate_style(StyleInvalidationReason reason, Vector(*this)) - return String {}; + auto const* parent_node = as_if(*this); + if (!parent_node) + return {}; - StringBuilder builder; - as(*this).for_each_child([&](auto& child) { - if (is(child)) { - auto maybe_content = as(child).text_content(); - if (maybe_content.has_value()) - builder.append(maybe_content.value()); - } + StringBuilder builder(StringBuilder::Mode::UTF16); + + parent_node->for_each_child_of_type([&](auto const& child) { + if (auto content = child.text_content(); content.has_value()) + builder.append(*content); return IterationDecision::Continue; }); - return MUST(builder.to_string()); + + return builder.to_utf16_string(); } // https://dom.spec.whatwg.org/#concept-shadow-including-root @@ -2045,14 +2043,14 @@ void Node::replace_all(GC::Ptr node) } // https://dom.spec.whatwg.org/#string-replace-all -void Node::string_replace_all(String const& string) +void Node::string_replace_all(Utf16String string) { // 1. Let node be null. GC::Ptr node; // 2. If string is not the empty string, then set node to a new Text node whose data is string and node document is parent’s node document. if (!string.is_empty()) - node = realm().create(document(), Utf16String::from_utf8(string)); + node = realm().create(document(), move(string)); // 3. Replace all with node within parent. replace_all(node); @@ -2862,7 +2860,7 @@ ErrorOr Node::name_or_description(NameOrDescription target, Document con // If the current node has at least one direct child title element, select the appropriate title based on // the language rules for the SVG specification, and return the title text alternative as a flat string. element->for_each_child_of_type([&](SVG::SVGTitleElement const& title) mutable { - title_element_text = title.text_content(); + title_element_text = title.text_content().map([](auto const& title) { return title.to_utf8_but_should_be_ported_to_utf16(); }); return IterationDecision::Break; }); if (title_element_text.has_value()) @@ -2879,7 +2877,7 @@ ErrorOr Node::name_or_description(NameOrDescription target, Document con // then use the subtree of the first such element. if (is(*element)) if (auto& table = (const_cast(static_cast(*element))); table.caption()) - return table.caption()->text_content().release_value(); + return table.caption()->text_content()->to_utf8_but_should_be_ported_to_utf16(); // https://w3c.github.io/html-aam/#fieldset-element-accessible-name-computation // 2. If the accessible name is still empty, then: if the fieldset element has a child that is a legend element, @@ -2888,7 +2886,7 @@ ErrorOr Node::name_or_description(NameOrDescription target, Document con Optional legend; auto& fieldset = (const_cast(static_cast(*element))); fieldset.for_each_child_of_type([&](HTML::HTMLLegendElement const& element) mutable { - legend = element.text_content().release_value(); + legend = element.text_content()->to_utf8_but_should_be_ported_to_utf16(); return IterationDecision::Break; }); if (legend.has_value()) @@ -3010,7 +3008,7 @@ ErrorOr Node::name_or_description(NameOrDescription target, Document con if (is_text() && (!parent_element() || (parent_element()->is_referenced() || !parent_element()->is_hidden() || !parent_element()->has_hidden_ancestor() || parent_element()->has_referenced_and_hidden_ancestor()))) { if (layout_node() && layout_node()->is_text_node()) return as(layout_node())->text_for_rendering().to_utf8_but_should_be_ported_to_utf16(); - return text_content().release_value(); + return text_content()->to_utf8_but_should_be_ported_to_utf16(); } // H. Otherwise, if the current node is a descendant of an element whose Accessible Name or Accessible Description diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index 2edeeec2dd2..8f6d81f199e 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -268,9 +268,9 @@ public: virtual Optional alternative_text() const; - String descendant_text_content() const; - Optional text_content() const; - void set_text_content(Optional const&); + Utf16String descendant_text_content() const; + Optional text_content() const; + void set_text_content(Optional const&); WebIDL::ExceptionOr normalize(); @@ -288,7 +288,7 @@ public: const HTML::HTMLElement* enclosing_html_element() const; const HTML::HTMLElement* enclosing_html_element_with_attribute(FlyString const&) const; - String child_text_content() const; + Utf16String child_text_content() const; Node& shadow_including_root(); Node const& shadow_including_root() const @@ -399,7 +399,7 @@ public: WebIDL::ExceptionOr unsafely_set_html(Element&, StringView); void replace_all(GC::Ptr); - void string_replace_all(String const&); + void string_replace_all(Utf16String); bool is_same_node(Node const*) const; bool is_equal_node(Node const*) const; diff --git a/Libraries/LibWeb/DOM/Node.idl b/Libraries/LibWeb/DOM/Node.idl index fc7a2365f57..9e86e8fe89b 100644 --- a/Libraries/LibWeb/DOM/Node.idl +++ b/Libraries/LibWeb/DOM/Node.idl @@ -38,7 +38,7 @@ interface Node : EventTarget { // FIXME: [LegacyNullToEmptyString] is not allowed on nullable types as per the Web IDL spec. // However, we only apply it to setters, so this works as a stop gap. // Replace this with something like a special cased [LegacyNullToEmptyString]. - [LegacyNullToEmptyString, CEReactions] attribute DOMString? textContent; + [LegacyNullToEmptyString, CEReactions] attribute Utf16DOMString? textContent; [CEReactions] undefined normalize(); [ImplementedAs=clone_node_binding, CEReactions] Node cloneNode(optional boolean deep = false); diff --git a/Libraries/LibWeb/DOM/StyleElementUtils.cpp b/Libraries/LibWeb/DOM/StyleElementUtils.cpp index 38b8f4818fe..0cc9899a299 100644 --- a/Libraries/LibWeb/DOM/StyleElementUtils.cpp +++ b/Libraries/LibWeb/DOM/StyleElementUtils.cpp @@ -52,7 +52,7 @@ void StyleElementUtils::update_a_style_block(DOM::Element& style_element) return; // 5. If the Should element's inline behavior be blocked by Content Security Policy? algorithm returns "Blocked" when executed upon the style element, "style", and the style element's child text content, then return. [CSP] - if (ContentSecurityPolicy::should_elements_inline_type_behavior_be_blocked_by_content_security_policy(style_element.realm(), style_element, ContentSecurityPolicy::Directives::Directive::InlineType::Style, style_element.child_text_content()) == ContentSecurityPolicy::Directives::Directive::Result::Blocked) + if (ContentSecurityPolicy::should_elements_inline_type_behavior_be_blocked_by_content_security_policy(style_element.realm(), style_element, ContentSecurityPolicy::Directives::Directive::InlineType::Style, style_element.child_text_content().to_utf8_but_should_be_ported_to_utf16()) == ContentSecurityPolicy::Directives::Directive::Result::Blocked) return; // 6. Create a CSS style sheet with the following properties: @@ -78,7 +78,7 @@ void StyleElementUtils::update_a_style_block(DOM::Element& style_element) // Left uninitialized. m_style_sheet_list = style_element.document_or_shadow_root_style_sheets(); m_associated_css_style_sheet = m_style_sheet_list->create_a_css_style_sheet( - style_element.text_content().value_or(String {}), + style_element.text_content().value_or({}).to_utf8_but_should_be_ported_to_utf16(), "text/css"_string, &style_element, style_element.attribute(HTML::AttributeNames::media).value_or({}), diff --git a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp index acd859bd92e..ef77b584702 100644 --- a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp @@ -383,11 +383,10 @@ void canonicalize_whitespace(DOM::BoundaryPoint boundary, bool fix_collapsed_spa if (is(*start_node) && start_offset != 0) { auto parent_white_space_collapse = resolved_keyword(*start_node->parent(), CSS::PropertyID::WhiteSpaceCollapse); - // FIXME: Find a way to get code points directly from the UTF-8 string - auto start_node_data = Utf16String::from_utf8(*start_node->text_content()); - auto offset_minus_one_code_point = start_node_data.code_point_at(start_offset - 1); + auto start_node_data = start_node->text_content().release_value(); + auto offset_minus_one_code_unit = start_node_data.code_unit_at(start_offset - 1); - if (parent_white_space_collapse != CSS::Keyword::Preserve && (offset_minus_one_code_point == 0x20 || offset_minus_one_code_point == 0xA0)) { + if (parent_white_space_collapse != CSS::Keyword::Preserve && (offset_minus_one_code_unit == 0x20 || offset_minus_one_code_unit == 0xA0)) { --start_offset; continue; } @@ -436,22 +435,21 @@ void canonicalize_whitespace(DOM::BoundaryPoint boundary, bool fix_collapsed_spa if (is(*end_node) && end_offset != end_node->length()) { auto parent_white_space_collapse = resolved_keyword(*end_node->parent(), CSS::PropertyID::WhiteSpaceCollapse); - // FIXME: Find a way to get code points directly from the UTF-8 string - auto end_node_data = Utf16String::from_utf8(*end_node->text_content()); - auto offset_code_point = end_node_data.code_point_at(end_offset); + auto end_node_data = end_node->text_content().release_value(); + auto offset_code_unit = end_node_data.code_unit_at(end_offset); - if (parent_white_space_collapse != CSS::Keyword::Preserve && (offset_code_point == 0x20 || offset_code_point == 0xA0)) { + if (parent_white_space_collapse != CSS::Keyword::Preserve && (offset_code_unit == 0x20 || offset_code_unit == 0xA0)) { // 1. If fix collapsed space is true, and collapse spaces is true, and the end offsetth // code unit of end node's data is a space (0x0020): call deleteData(end offset, 1) // on end node, then continue this loop from the beginning. - if (fix_collapsed_space && collapse_spaces && offset_code_point == 0x20) { + if (fix_collapsed_space && collapse_spaces && offset_code_unit == 0x20) { MUST(static_cast(*end_node).delete_data(end_offset, 1)); continue; } // 2. Set collapse spaces to true if the end offsetth code unit of end node's data is a // space (0x0020), false otherwise. - collapse_spaces = offset_code_point == 0x20; + collapse_spaces = offset_code_unit == 0x20; // 3. Add one to end offset. ++end_offset; @@ -500,7 +498,7 @@ void canonicalize_whitespace(DOM::BoundaryPoint boundary, bool fix_collapsed_spa // AD-HOC: Use the white-space-collapse longhand instead of "white-space" shorthand: https://github.com/w3c/editing/issues/486. if (is(*end_node) && end_offset == end_node->length() && precedes_a_line_break(end_node)) { auto parent_white_space_collapse = resolved_keyword(*end_node->parent(), CSS::PropertyID::WhiteSpaceCollapse); - if (parent_white_space_collapse != CSS::Keyword::Preserve && end_node->text_content().value().ends_with_bytes(" "sv)) { + if (parent_white_space_collapse != CSS::Keyword::Preserve && end_node->text_content()->ends_with(" "sv)) { // 1. Subtract one from end offset. --end_offset; @@ -560,10 +558,10 @@ void canonicalize_whitespace(DOM::BoundaryPoint boundary, bool fix_collapsed_spa replacement_whitespace_view = replacement_whitespace_view.substring_view(1); // 2. If element is not the same as the start offsetth code unit of start node's data: - auto start_node_data = Utf16String::from_utf8(*start_node->text_content()); - auto start_node_code_point = start_node_data.code_point_at(start_offset); + auto start_node_data = start_node->text_content().release_value(); + auto start_node_code_unit = start_node_data.code_unit_at(start_offset); - if (element != start_node_code_point) { + if (element != start_node_code_unit) { // 1. Call insertData(start offset, element) on start node. auto& start_node_character_data = static_cast(*start_node); MUST(start_node_character_data.insert_data(start_offset, Utf16String::from_code_point(element))); @@ -1695,7 +1693,7 @@ bool is_allowed_child_of_node(Variant, FlyString> child, Vari HTML::TagNames::tbody, HTML::TagNames::tfoot, HTML::TagNames::thead, HTML::TagNames::tr); if (parent_is_table_like && is(child_node.ptr())) { auto child_text_content = child_node->text_content().release_value(); - if (!all_of(child_text_content.bytes_as_string_view(), Infra::is_ascii_whitespace)) + if (!all_of(child_text_content, Infra::is_ascii_whitespace)) return false; } @@ -2907,7 +2905,8 @@ void normalize_sublists_in_node(GC::Ref item) // 2. If child is an ol or ul, or new item is null and child is a Text node whose data // consists of zero of more space characters: auto child_text = child->text_content(); - auto text_is_all_whitespace = child_text.has_value() && all_of(child_text.value().bytes_as_string_view(), Infra::is_ascii_whitespace); + auto text_is_all_whitespace = child_text.has_value() && all_of(*child_text, Infra::is_ascii_whitespace); + if ((is(*child) || is(*child)) || (!new_item && is(*child) && text_is_all_whitespace)) { // 1. Set new item to null. diff --git a/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp b/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp index ee1f926cfda..5afc6514b2f 100644 --- a/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp @@ -164,14 +164,14 @@ GC::Ref HTMLAnchorElement::rel_list() } // https://html.spec.whatwg.org/multipage/text-level-semantics.html#dom-a-text -String HTMLAnchorElement::text() const +Utf16String HTMLAnchorElement::text() const { // The text attribute's getter must return this element's descendant text content. return descendant_text_content(); } // https://html.spec.whatwg.org/multipage/text-level-semantics.html#dom-a-text -void HTMLAnchorElement::set_text(String const& text) +void HTMLAnchorElement::set_text(Utf16String const& text) { // The text attribute's setter must string replace all with the given value within this element. string_replace_all(text); diff --git a/Libraries/LibWeb/HTML/HTMLAnchorElement.h b/Libraries/LibWeb/HTML/HTMLAnchorElement.h index 1fa0c2fba26..8ffd4095063 100644 --- a/Libraries/LibWeb/HTML/HTMLAnchorElement.h +++ b/Libraries/LibWeb/HTML/HTMLAnchorElement.h @@ -26,8 +26,8 @@ public: GC::Ref rel_list(); - String text() const; - void set_text(String const&); + Utf16String text() const; + void set_text(Utf16String const&); // ^EventTarget // https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute:the-a-element diff --git a/Libraries/LibWeb/HTML/HTMLAnchorElement.idl b/Libraries/LibWeb/HTML/HTMLAnchorElement.idl index bac32dd50b4..a967bbc562e 100644 --- a/Libraries/LibWeb/HTML/HTMLAnchorElement.idl +++ b/Libraries/LibWeb/HTML/HTMLAnchorElement.idl @@ -16,7 +16,7 @@ interface HTMLAnchorElement : HTMLElement { [CEReactions, Reflect] attribute DOMString hreflang; [CEReactions, Reflect] attribute DOMString type; - [CEReactions] attribute DOMString text; + [CEReactions] attribute Utf16DOMString text; [CEReactions, Reflect=referrerpolicy, Enumerated=ReferrerPolicy] attribute DOMString referrerPolicy; diff --git a/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp b/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp index 7da433ef830..81e80b7d2ac 100644 --- a/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLDetailsElement.cpp @@ -252,7 +252,7 @@ WebIDL::ExceptionOr HTMLDetailsElement::create_shadow_tree_if_needed() :host([open]) summary { list-style-type: disclosure-open; } - )~~~"_string); + )~~~"_utf16); MUST(shadow_root->append_child(style)); m_summary_slot = static_cast(*summary_slot); diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index ebdb67e86b7..495dade5706 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -389,7 +389,7 @@ String HTMLElement::get_the_text_steps() // 1. If element is not being rendered or if the user agent is a non-CSS user agent, then return element's descendant text content. document().update_layout(DOM::UpdateLayoutReason::HTMLElementGetTheTextSteps); if (!layout_node()) - return descendant_text_content(); + return descendant_text_content().to_utf8_but_should_be_ported_to_utf16(); // 2. Let results be a new empty list. Vector> results; diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 3000c0c17df..9020ba2f01c 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -1203,15 +1203,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(MUST(String::formatted("Select {}...", files_label))); + 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(m_selected_files->item(0)->name()); + m_file_label->set_text_content(Utf16String::from_utf8(m_selected_files->item(0)->name())); else - m_file_label->set_text_content(MUST(String::formatted("{} files selected.", m_selected_files->length()))); + m_file_label->set_text_content(Utf16String::formatted("{} files selected.", m_selected_files->length())); } else { - m_file_label->set_text_content(MUST(String::formatted("No {} selected.", files_label))); + m_file_label->set_text_content(Utf16String::formatted("No {} selected.", files_label)); } } diff --git a/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Libraries/LibWeb/HTML/HTMLOptionElement.cpp index b0613401c65..ccf061991fe 100644 --- a/Libraries/LibWeb/HTML/HTMLOptionElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLOptionElement.cpp @@ -93,7 +93,9 @@ Utf16String HTMLOptionElement::value() const { // The value of an option element is the value of the value content attribute, if there is one. // ...or, if there is not, the value of the element's text IDL attribute. - return Utf16String::from_utf8(attribute(HTML::AttributeNames::value).value_or(text())); + if (auto value = attribute(HTML::AttributeNames::value); value.has_value()) + return Utf16String::from_utf8(*value); + return text(); } // https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value @@ -121,8 +123,7 @@ String HTMLOptionElement::label() const // must return that attribute's value; otherwise, it must return the element's label. if (auto label = attribute(HTML::AttributeNames::label); label.has_value()) return label.release_value(); - - return text(); + return text().to_utf8_but_should_be_ported_to_utf16(); } // https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-label @@ -133,9 +134,9 @@ void HTMLOptionElement::set_label(String const& label) } // https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-text -String HTMLOptionElement::text() const +Utf16String HTMLOptionElement::text() const { - StringBuilder builder; + StringBuilder builder(StringBuilder::Mode::UTF16); // Concatenation of data of all the Text node descendants of the option element, in tree order, // excluding any that are descendants of descendants of the option element that are themselves @@ -146,11 +147,11 @@ String HTMLOptionElement::text() const }); // Return the result of stripping and collapsing ASCII whitespace from the above concatenation. - return MUST(Infra::strip_and_collapse_whitespace(builder.string_view())); + return Infra::strip_and_collapse_whitespace(builder.to_utf16_string()); } // https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-text -void HTMLOptionElement::set_text(String const& text) +void HTMLOptionElement::set_text(Utf16String const& text) { string_replace_all(text); // Note: this causes children_changed() to be called, which will update the