diff --git a/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp b/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp index 9327c6aa6f..39db209b33 100644 --- a/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp +++ b/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -34,8 +34,8 @@ JS_DEFINE_NATIVE_FUNCTION(CSSNamespace::escape) if (!vm.argument_count()) return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "CSS.escape"); - auto identifier = TRY(vm.argument(0).to_deprecated_string(vm)); - return JS::PrimitiveString::create(vm, Web::CSS::serialize_an_identifier(identifier)); + auto identifier = TRY(vm.argument(0).to_string(vm)); + return JS::PrimitiveString::create(vm, TRY_OR_THROW_OOM(vm, Web::CSS::serialize_an_identifier(identifier))); } // https://www.w3.org/TR/css-conditional-3/#dom-css-supports diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp index 9eb018a51e..7890656ccb 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022-2023, Sam Atkins * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause @@ -50,7 +50,7 @@ DeprecatedString CSSFontFaceRule::serialized() const builder.append("font-family: "sv); // 3. The result of performing serialize a string on the rule’s font family name. - serialize_a_string(builder, m_font_face.font_family()); + serialize_a_string(builder, m_font_face.font_family()).release_value_but_fixme_should_propagate_errors(); // 4. The string ";", i.e., SEMICOLON (U+003B). builder.append(';'); @@ -61,20 +61,21 @@ DeprecatedString CSSFontFaceRule::serialized() const builder.append(" src: "sv); // 2. The result of invoking serialize a comma-separated list on performing serialize a URL or serialize a LOCAL for each source on the source list. - serialize_a_comma_separated_list(builder, m_font_face.sources(), [&](FontFace::Source source) { + serialize_a_comma_separated_list(builder, m_font_face.sources(), [&](StringBuilder& builder, FontFace::Source source) -> ErrorOr { if (source.url.cannot_be_a_base_url()) { - serialize_a_url(builder, source.url.to_deprecated_string()); + TRY(serialize_a_url(builder, source.url.to_deprecated_string())); } else { - serialize_a_local(builder, source.url.to_deprecated_string()); + TRY(serialize_a_local(builder, source.url.to_deprecated_string())); } // NOTE: No spec currently exists for format() if (source.format.has_value()) { - builder.append("format(\""sv); - serialize_a_string(builder, source.format.value()); - builder.append("\")"sv); + TRY(builder.try_append("format(\""sv)); + TRY(serialize_a_string(builder, source.format.value())); + TRY(builder.try_append("\")"sv)); } - }); + return {}; + }).release_value_but_fixme_should_propagate_errors(); // 3. The string ";", i.e., SEMICOLON (U+003B). builder.append(';'); @@ -82,7 +83,7 @@ DeprecatedString CSSFontFaceRule::serialized() const // 6. If rule’s associated unicode-range descriptor is present, a single SPACE (U+0020), followed by the string "unicode-range:", followed by a single SPACE (U+0020), followed by the result of performing serialize a <'unicode-range'>, followed by the string ";", i.e., SEMICOLON (U+003B). builder.append(" unicode-range: "sv); - serialize_unicode_ranges(builder, m_font_face.unicode_ranges()); + serialize_unicode_ranges(builder, m_font_face.unicode_ranges()).release_value_but_fixme_should_propagate_errors(); builder.append(';'); // FIXME: 7. If rule’s associated font-variant descriptor is present, a single SPACE (U+0020), diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Declaration.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Declaration.cpp index 1ae3732321..3978a6abdd 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Declaration.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Declaration.cpp @@ -23,7 +23,7 @@ ErrorOr Declaration::to_string() const { StringBuilder builder; - serialize_an_identifier(builder, m_name); + TRY(serialize_an_identifier(builder, m_name)); TRY(builder.try_append(": "sv)); TRY(builder.try_join(' ', m_values)); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Function.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Function.cpp index e5e8a935ab..481c9ba769 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Function.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Function.cpp @@ -22,7 +22,7 @@ ErrorOr Function::to_string() const { StringBuilder builder; - serialize_an_identifier(builder, m_name); + TRY(serialize_an_identifier(builder, m_name)); TRY(builder.try_append('(')); TRY(builder.try_join(' ', m_values)); TRY(builder.try_append(')')); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Token.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Token.cpp index 2fc5e340fc..db07758519 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Token.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Token.cpp @@ -18,26 +18,26 @@ ErrorOr Token::to_string() const case Type::EndOfFile: return String {}; case Type::Ident: - return String::from_utf8(serialize_an_identifier(ident())); + return serialize_an_identifier(ident()); case Type::Function: - return String::formatted("{}(", serialize_an_identifier(function())); + return String::formatted("{}(", TRY(serialize_an_identifier(function()))); case Type::AtKeyword: - return String::formatted("@{}", serialize_an_identifier(at_keyword())); + return String::formatted("@{}", TRY(serialize_an_identifier(at_keyword()))); case Type::Hash: { switch (m_hash_type) { case HashType::Id: - return String::formatted("#{}", serialize_an_identifier(hash_value())); + return String::formatted("#{}", TRY(serialize_an_identifier(hash_value()))); case HashType::Unrestricted: return String::formatted("#{}", hash_value()); } VERIFY_NOT_REACHED(); } case Type::String: - return String::from_utf8(serialize_a_string(string())); + return serialize_a_string(string()); case Type::BadString: return String {}; case Type::Url: - return String::from_utf8(serialize_a_url(url())); + return serialize_a_url(url()); case Type::BadUrl: return String::from_utf8("url()"sv); case Type::Delim: diff --git a/Userland/Libraries/LibWeb/CSS/Selector.cpp b/Userland/Libraries/LibWeb/CSS/Selector.cpp index 59f6fcce02..788525196a 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.cpp +++ b/Userland/Libraries/LibWeb/CSS/Selector.cpp @@ -129,7 +129,7 @@ DeprecatedString Selector::SimpleSelector::serialize() const // FIXME: 2. If the namespace prefix maps to a namespace that is the null namespace (not in a namespace) append "|" (U+007C) to s. // 3. If this is a type selector append the serialization of the element name as an identifier to s. if (type == Selector::SimpleSelector::Type::TagName) { - serialize_an_identifier(s, name()); + serialize_an_identifier(s, name()).release_value_but_fixme_should_propagate_errors(); } // 4. If this is a universal selector append "*" (U+002A) to s. if (type == Selector::SimpleSelector::Type::Universal) @@ -144,7 +144,7 @@ DeprecatedString Selector::SimpleSelector::serialize() const // FIXME: 2. If the namespace prefix maps to a namespace that is not the null namespace (not in a namespace) append the serialization of the namespace prefix as an identifier, followed by a "|" (U+007C) to s. // 3. Append the serialization of the attribute name as an identifier to s. - serialize_an_identifier(s, attribute.name); + serialize_an_identifier(s, attribute.name).release_value_but_fixme_should_propagate_errors(); // 4. If there is an attribute value specified, append "=", "~=", "|=", "^=", "$=", or "*=" as appropriate (depending on the type of attribute selector), // followed by the serialization of the attribute value as a string, to s. @@ -172,7 +172,7 @@ DeprecatedString Selector::SimpleSelector::serialize() const break; } - serialize_a_string(s, attribute.value); + serialize_a_string(s, attribute.value).release_value_but_fixme_should_propagate_errors(); } // 5. If the attribute selector has the case-insensitivity flag present, append " i" (U+0020 U+0069) to s. @@ -197,13 +197,13 @@ DeprecatedString Selector::SimpleSelector::serialize() const case Selector::SimpleSelector::Type::Class: // Append a "." (U+002E), followed by the serialization of the class name as an identifier to s. s.append('.'); - serialize_an_identifier(s, name()); + serialize_an_identifier(s, name()).release_value_but_fixme_should_propagate_errors(); break; case Selector::SimpleSelector::Type::Id: // Append a "#" (U+0023), followed by the serialization of the ID as an identifier to s. s.append('#'); - serialize_an_identifier(s, name()); + serialize_an_identifier(s, name()).release_value_but_fixme_should_propagate_errors(); break; case Selector::SimpleSelector::Type::PseudoClass: { diff --git a/Userland/Libraries/LibWeb/CSS/Selector.h b/Userland/Libraries/LibWeb/CSS/Selector.h index ac180e5061..837cdb11b8 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.h +++ b/Userland/Libraries/LibWeb/CSS/Selector.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling - * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ diff --git a/Userland/Libraries/LibWeb/CSS/Serialize.cpp b/Userland/Libraries/LibWeb/CSS/Serialize.cpp index 22d6d9e512..70a2e185bf 100644 --- a/Userland/Libraries/LibWeb/CSS/Serialize.cpp +++ b/Userland/Libraries/LibWeb/CSS/Serialize.cpp @@ -11,20 +11,22 @@ namespace Web::CSS { // https://www.w3.org/TR/cssom-1/#escape-a-character -void escape_a_character(StringBuilder& builder, u32 character) +ErrorOr escape_a_character(StringBuilder& builder, u32 character) { - builder.append('\\'); - builder.append_code_point(character); + TRY(builder.try_append('\\')); + TRY(builder.try_append_code_point(character)); + return {}; } // https://www.w3.org/TR/cssom-1/#escape-a-character-as-code-point -void escape_a_character_as_code_point(StringBuilder& builder, u32 character) +ErrorOr escape_a_character_as_code_point(StringBuilder& builder, u32 character) { - builder.appendff("\\{:x} ", character); + TRY(builder.try_appendff("\\{:x} ", character)); + return {}; } // https://www.w3.org/TR/cssom-1/#serialize-an-identifier -void serialize_an_identifier(StringBuilder& builder, StringView ident) +ErrorOr serialize_an_identifier(StringBuilder& builder, StringView ident) { Utf8View characters { ident }; auto first_character = characters.is_empty() ? 0 : *characters.begin(); @@ -34,31 +36,31 @@ void serialize_an_identifier(StringBuilder& builder, StringView ident) for (auto character : characters) { // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD). if (character == 0) { - builder.append_code_point(0xFFFD); + TRY(builder.try_append_code_point(0xFFFD)); continue; } // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F, // then the character escaped as code point. if ((character >= 0x0001 && character <= 0x001F) || (character == 0x007F)) { - escape_a_character_as_code_point(builder, character); + TRY(escape_a_character_as_code_point(builder, character)); continue; } // If the character is the first character and is in the range [0-9] (U+0030 to U+0039), // then the character escaped as code point. if (builder.is_empty() && character >= '0' && character <= '9') { - escape_a_character_as_code_point(builder, character); + TRY(escape_a_character_as_code_point(builder, character)); continue; } // If the character is the second character and is in the range [0-9] (U+0030 to U+0039) // and the first character is a "-" (U+002D), then the character escaped as code point. if (builder.length() == 1 && first_character == '-' && character >= '0' && character <= '9') { - escape_a_character_as_code_point(builder, character); + TRY(escape_a_character_as_code_point(builder, character)); continue; } // If the character is the first character and is a "-" (U+002D), and there is no second // character, then the escaped character. if (builder.is_empty() && character == '-' && characters.length() == 1) { - escape_a_character(builder, character); + TRY(escape_a_character(builder, character)); continue; } // If the character is not handled by one of the above rules and is greater than or equal to U+0080, is "-" (U+002D) or "_" (U+005F), or is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A), or \[a-z] (U+0061 to U+007A), then the character itself. @@ -67,125 +69,131 @@ void serialize_an_identifier(StringBuilder& builder, StringView ident) || (character >= '0' && character <= '9') || (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z')) { - builder.append_code_point(character); + TRY(builder.try_append_code_point(character)); continue; } // Otherwise, the escaped character. - escape_a_character(builder, character); + TRY(escape_a_character(builder, character)); } + return {}; } // https://www.w3.org/TR/cssom-1/#serialize-a-string -void serialize_a_string(StringBuilder& builder, StringView string) +ErrorOr serialize_a_string(StringBuilder& builder, StringView string) { Utf8View characters { string }; // To serialize a string means to create a string represented by '"' (U+0022), followed by the result // of applying the rules below to each character of the given string, followed by '"' (U+0022): - builder.append('"'); + TRY(builder.try_append('"')); for (auto character : characters) { // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD). if (character == 0) { - builder.append_code_point(0xFFFD); + TRY(builder.try_append_code_point(0xFFFD)); continue; } // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F, the character escaped as code point. if ((character >= 0x0001 && character <= 0x001F) || (character == 0x007F)) { - escape_a_character_as_code_point(builder, character); + TRY(escape_a_character_as_code_point(builder, character)); continue; } // If the character is '"' (U+0022) or "\" (U+005C), the escaped character. if (character == 0x0022 || character == 0x005C) { - escape_a_character(builder, character); + TRY(escape_a_character(builder, character)); continue; } // Otherwise, the character itself. - builder.append_code_point(character); + TRY(builder.try_append_code_point(character)); } - builder.append('"'); + TRY(builder.try_append('"')); + return {}; } // https://www.w3.org/TR/cssom-1/#serialize-a-url -void serialize_a_url(StringBuilder& builder, StringView url) +ErrorOr serialize_a_url(StringBuilder& builder, StringView url) { // To serialize a URL means to create a string represented by "url(", // followed by the serialization of the URL as a string, followed by ")". - builder.append("url("sv); - serialize_a_string(builder, url.to_deprecated_string()); - builder.append(')'); + TRY(builder.try_append("url("sv)); + TRY(serialize_a_string(builder, url.to_deprecated_string())); + TRY(builder.try_append(')')); + return {}; } // https://www.w3.org/TR/cssom-1/#serialize-a-local -void serialize_a_local(StringBuilder& builder, StringView path) +ErrorOr serialize_a_local(StringBuilder& builder, StringView path) { // To serialize a LOCAL means to create a string represented by "local(", // followed by the serialization of the LOCAL as a string, followed by ")". - builder.append("local("sv); - serialize_a_string(builder, path.to_deprecated_string()); - builder.append(')'); + TRY(builder.try_append("local("sv)); + TRY(serialize_a_string(builder, path.to_deprecated_string())); + TRY(builder.try_append(')')); + return {}; } // NOTE: No spec currently exists for serializing a <'unicode-range'>. -void serialize_unicode_ranges(StringBuilder& builder, Vector const& unicode_ranges) +ErrorOr serialize_unicode_ranges(StringBuilder& builder, Vector const& unicode_ranges) { - serialize_a_comma_separated_list(builder, unicode_ranges, [&](UnicodeRange unicode_range) { - serialize_a_string(builder, unicode_range.to_string().release_value_but_fixme_should_propagate_errors()); - }); + TRY(serialize_a_comma_separated_list(builder, unicode_ranges, [](auto& builder, UnicodeRange unicode_range) -> ErrorOr { + return serialize_a_string(builder, TRY(unicode_range.to_string())); + })); + return {}; } // https://www.w3.org/TR/css-color-4/#serializing-sRGB-values -void serialize_a_srgb_value(StringBuilder& builder, Color color) +ErrorOr serialize_a_srgb_value(StringBuilder& builder, Color color) { // The serialized form is derived from the computed value and thus, uses either the rgb() or rgba() form // (depending on whether the alpha is exactly 1, or not), with lowercase letters for the function name. // NOTE: Since we use Gfx::Color, having an "alpha of 1" means its value is 255. if (color.alpha() == 255) - builder.appendff("rgb({}, {}, {})"sv, color.red(), color.green(), color.blue()); + TRY(builder.try_appendff("rgb({}, {}, {})"sv, color.red(), color.green(), color.blue())); else - builder.appendff("rgba({}, {}, {}, {})"sv, color.red(), color.green(), color.blue(), (float)(color.alpha()) / 255.0f); + TRY(builder.try_appendff("rgba({}, {}, {}, {})"sv, color.red(), color.green(), color.blue(), (float)(color.alpha()) / 255.0f)); + return {}; } -DeprecatedString escape_a_character(u32 character) +ErrorOr escape_a_character(u32 character) { StringBuilder builder; - escape_a_character(builder, character); - return builder.to_deprecated_string(); + TRY(escape_a_character(builder, character)); + return builder.to_string(); } -DeprecatedString escape_a_character_as_code_point(u32 character) +ErrorOr escape_a_character_as_code_point(u32 character) { StringBuilder builder; - escape_a_character_as_code_point(builder, character); - return builder.to_deprecated_string(); + TRY(escape_a_character_as_code_point(builder, character)); + return builder.to_string(); } -DeprecatedString serialize_an_identifier(StringView ident) +ErrorOr serialize_an_identifier(StringView ident) { StringBuilder builder; - serialize_an_identifier(builder, ident); - return builder.to_deprecated_string(); + TRY(serialize_an_identifier(builder, ident)); + return builder.to_string(); } -DeprecatedString serialize_a_string(StringView string) +ErrorOr serialize_a_string(StringView string) { StringBuilder builder; - serialize_a_string(builder, string); - return builder.to_deprecated_string(); + TRY(serialize_a_string(builder, string)); + return builder.to_string(); } -DeprecatedString serialize_a_url(StringView url) +ErrorOr serialize_a_url(StringView url) { StringBuilder builder; - serialize_a_url(builder, url); - return builder.to_deprecated_string(); + TRY(serialize_a_url(builder, url)); + return builder.to_string(); } ErrorOr serialize_a_srgb_value(Color color) { StringBuilder builder; - serialize_a_srgb_value(builder, color); + TRY(serialize_a_srgb_value(builder, color)); return builder.to_string(); } diff --git a/Userland/Libraries/LibWeb/CSS/Serialize.h b/Userland/Libraries/LibWeb/CSS/Serialize.h index 7d729a911d..3eb680c6df 100644 --- a/Userland/Libraries/LibWeb/CSS/Serialize.h +++ b/Userland/Libraries/LibWeb/CSS/Serialize.h @@ -1,12 +1,11 @@ /* - * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include #include #include #include @@ -16,32 +15,33 @@ namespace Web::CSS { -void escape_a_character(StringBuilder&, u32 character); -void escape_a_character_as_code_point(StringBuilder&, u32 character); -void serialize_an_identifier(StringBuilder&, StringView ident); -void serialize_a_string(StringBuilder&, StringView string); -void serialize_a_url(StringBuilder&, StringView url); -void serialize_a_local(StringBuilder&, StringView path); -void serialize_unicode_ranges(StringBuilder&, Vector const& unicode_ranges); -void serialize_a_srgb_value(StringBuilder&, Color color); +ErrorOr escape_a_character(StringBuilder&, u32 character); +ErrorOr escape_a_character_as_code_point(StringBuilder&, u32 character); +ErrorOr serialize_an_identifier(StringBuilder&, StringView ident); +ErrorOr serialize_a_string(StringBuilder&, StringView string); +ErrorOr serialize_a_url(StringBuilder&, StringView url); +ErrorOr serialize_a_local(StringBuilder&, StringView path); +ErrorOr serialize_unicode_ranges(StringBuilder&, Vector const& unicode_ranges); +ErrorOr serialize_a_srgb_value(StringBuilder&, Color color); -DeprecatedString escape_a_character(u32 character); -DeprecatedString escape_a_character_as_code_point(u32 character); -DeprecatedString serialize_an_identifier(StringView ident); -DeprecatedString serialize_a_string(StringView string); -DeprecatedString serialize_a_url(StringView url); +ErrorOr escape_a_character(u32 character); +ErrorOr escape_a_character_as_code_point(u32 character); +ErrorOr serialize_an_identifier(StringView ident); +ErrorOr serialize_a_string(StringView string); +ErrorOr serialize_a_url(StringView url); ErrorOr serialize_a_srgb_value(Color color); template -void serialize_a_comma_separated_list(StringBuilder& builder, Vector const& items, SerializeItem serialize_item) +ErrorOr serialize_a_comma_separated_list(StringBuilder& builder, Vector const& items, SerializeItem serialize_item) { for (size_t i = 0; i < items.size(); i++) { auto& item = items.at(i); - serialize_item(item); + TRY(serialize_item(builder, item)); if ((i + 1) < items.size()) { - builder.append(",\n"sv); + TRY(builder.try_append(",\n"sv)); } } + return {}; } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 290fe3b7d2..e158482b6b 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -1257,7 +1257,7 @@ ErrorOr FilterValueListStyleValue::to_string() const TRY(builder.try_appendff(" {}", TRY(drop_shadow.radius->to_string()))); if (drop_shadow.color.has_value()) { TRY(builder.try_append(' ')); - serialize_a_srgb_value(builder, *drop_shadow.color); + TRY(serialize_a_srgb_value(builder, *drop_shadow.color)); } return {}; }, @@ -1773,7 +1773,7 @@ Gfx::Bitmap const* ImageStyleValue::bitmap(size_t frame_index) const ErrorOr ImageStyleValue::to_string() const { - return String::from_deprecated_string(serialize_a_url(m_url.to_deprecated_string())); + return serialize_a_url(m_url.to_deprecated_string()); } bool ImageStyleValue::equals(StyleValue const& other) const @@ -1813,7 +1813,7 @@ static ErrorOr serialize_color_stop_list(StringBuilder& builder, auto cons if (element.transition_hint.has_value()) TRY(builder.try_appendff("{}, "sv, TRY(element.transition_hint->value.to_string()))); - serialize_a_srgb_value(builder, element.color_stop.color); + TRY(serialize_a_srgb_value(builder, element.color_stop.color)); for (auto position : Array { &element.color_stop.position, &element.color_stop.second_position }) { if (position->has_value()) TRY(builder.try_appendff(" {}"sv, TRY((*position)->to_string())));