From bc54c0cdfbfa6f71ddc4ed16450a8a83e5958cf3 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 17 Feb 2025 13:21:07 -0500 Subject: [PATCH] AK+Everywhere: Store JSON strings as String --- AK/JsonObject.cpp | 12 +++- AK/JsonObject.h | 3 +- AK/JsonObjectSerializer.h | 2 +- AK/JsonValue.cpp | 12 ++-- AK/JsonValue.h | 16 ++--- Libraries/LibCore/ArgsParser.cpp | 2 +- Libraries/LibDevTools/Actor.cpp | 9 +-- Libraries/LibDevTools/Actor.h | 5 +- .../LibDevTools/Actors/CSSPropertiesActor.cpp | 2 +- Libraries/LibDevTools/Actors/DeviceActor.cpp | 12 ++-- Libraries/LibDevTools/Actors/FrameActor.cpp | 8 +-- Libraries/LibDevTools/Actors/RootActor.cpp | 4 +- Libraries/LibDevTools/Actors/TabActor.cpp | 4 +- Libraries/LibDevTools/Actors/WalkerActor.cpp | 22 +++---- Libraries/LibGC/Heap.cpp | 4 +- Libraries/LibWeb/Crypto/CryptoBindings.cpp | 2 +- Libraries/LibWeb/WebDriver/Capabilities.cpp | 8 +-- Libraries/LibWeb/WebDriver/Client.cpp | 4 +- Libraries/LibWeb/WebDriver/Contexts.cpp | 2 +- .../LibWeb/WebDriver/ElementReference.cpp | 4 +- Libraries/LibWeb/WebDriver/Properties.h | 2 +- Libraries/LibWebView/InspectorClient.cpp | 2 +- .../LibWeb/GenerateCSSEnums.cpp | 2 +- .../LibWeb/GenerateCSSMediaFeatureID.cpp | 6 +- .../LibWeb/GenerateCSSPropertyID.cpp | 14 ++--- .../LibWeb/GenerateCSSTransformFunctions.cpp | 2 +- Services/WebContent/WebDriverConnection.cpp | 28 ++++----- Services/WebDriver/Client.cpp | 2 +- Services/WebDriver/Session.cpp | 2 +- Tests/AK/TestJSON.cpp | 12 ++-- Tests/LibJS/test-test262.cpp | 4 +- Tests/LibJS/test262-runner.cpp | 58 +++++++++---------- UI/Qt/AutoComplete.cpp | 44 +++++++------- 33 files changed, 163 insertions(+), 152 deletions(-) diff --git a/AK/JsonObject.cpp b/AK/JsonObject.cpp index 93303e2ce66..d5d7596b4a4 100644 --- a/AK/JsonObject.cpp +++ b/AK/JsonObject.cpp @@ -116,11 +116,17 @@ Optional JsonObject::get_bool(StringView key) const return {}; } +Optional JsonObject::get_string(StringView key) const +{ + if (auto value = get(key); value.has_value() && value->is_string()) + return value->as_string(); + return {}; +} + Optional JsonObject::get_byte_string(StringView key) const { - auto maybe_value = get(key); - if (maybe_value.has_value() && maybe_value->is_string()) - return maybe_value->as_string(); + if (auto value = get_string(key); value.has_value()) + return value->to_byte_string(); return {}; } diff --git a/AK/JsonObject.h b/AK/JsonObject.h index ea4d8172890..0cafc9bb0f3 100644 --- a/AK/JsonObject.h +++ b/AK/JsonObject.h @@ -76,6 +76,7 @@ public: Optional get_addr(StringView key) const; Optional get_bool(StringView key) const; + Optional get_string(StringView key) const; Optional get_byte_string(StringView key) const; Optional get_object(StringView key); @@ -144,7 +145,7 @@ inline void JsonValue::serialize(Builder& builder) const [&](Empty const&) { builder.append("null"sv); }, [&](bool const& value) { builder.append(value ? "true"sv : "false"sv); }, [&](Arithmetic auto const& value) { builder.appendff("{}", value); }, - [&](ByteString const& value) { + [&](String const& value) { builder.append('\"'); builder.append_escaped_for_json(value.bytes()); builder.append('\"'); diff --git a/AK/JsonObjectSerializer.h b/AK/JsonObjectSerializer.h index 7162ff6d80a..f888812577c 100644 --- a/AK/JsonObjectSerializer.h +++ b/AK/JsonObjectSerializer.h @@ -57,7 +57,7 @@ public: return {}; } - ErrorOr add(StringView key, ByteString const& value) + ErrorOr add(StringView key, String const& value) { TRY(begin_item(key)); if constexpr (IsLegacyBuilder) { diff --git a/AK/JsonValue.cpp b/AK/JsonValue.cpp index 0430b9d3960..7f576ca7fa3 100644 --- a/AK/JsonValue.cpp +++ b/AK/JsonValue.cpp @@ -153,17 +153,17 @@ JsonValue::JsonValue(long long unsigned value) } JsonValue::JsonValue(double value) - : m_value(double { value }) -{ -} - -JsonValue::JsonValue(ByteString const& value) : m_value(value) { } +JsonValue::JsonValue(String value) + : m_value(move(value)) +{ +} + JsonValue::JsonValue(StringView value) - : m_value(ByteString { value }) + : m_value(MUST(String::from_utf8(value))) { } diff --git a/AK/JsonValue.h b/AK/JsonValue.h index 7979261bf41..d0fee56f229 100644 --- a/AK/JsonValue.h +++ b/AK/JsonValue.h @@ -7,10 +7,10 @@ #pragma once -#include #include #include #include +#include #include namespace AK { @@ -32,7 +32,7 @@ public: i64, u64, double, - ByteString, + String, NonnullOwnPtr, NonnullOwnPtr>; @@ -53,9 +53,9 @@ public: JsonValue(long unsigned); JsonValue(long long); JsonValue(long long unsigned); - JsonValue(double); - JsonValue(ByteString const&); + + JsonValue(String); JsonValue(StringView); template @@ -119,9 +119,9 @@ public: return m_value.get(); } - ByteString const& as_string() const + String const& as_string() const { - return m_value.get(); + return m_value.get(); } JsonObject& as_object() @@ -155,14 +155,14 @@ public: [](Empty const&) { return Type::Null; }, [](bool const&) { return Type::Bool; }, [](Arithmetic auto const&) { return Type::Number; }, - [](ByteString const&) { return Type::String; }, + [](String const&) { return Type::String; }, [](NonnullOwnPtr const&) { return Type::Array; }, [](NonnullOwnPtr const&) { return Type::Object; }); } bool is_null() const { return m_value.has(); } bool is_bool() const { return m_value.has(); } - bool is_string() const { return m_value.has(); } + bool is_string() const { return m_value.has(); } bool is_array() const { return m_value.has>(); } bool is_object() const { return m_value.has>(); } bool is_number() const diff --git a/Libraries/LibCore/ArgsParser.cpp b/Libraries/LibCore/ArgsParser.cpp index 97c77787a6f..32f301a4642 100644 --- a/Libraries/LibCore/ArgsParser.cpp +++ b/Libraries/LibCore/ArgsParser.cpp @@ -749,7 +749,7 @@ void ArgsParser::autocomplete(FILE* file, StringView program_name, ReadonlySpan< auto write_completion = [&](auto format, auto& option, auto has_invariant, auto... args) { JsonObject object; - object.set("completion"sv, ByteString::formatted(StringView { format, strlen(format) }, args...)); + object.set("completion"sv, MUST(String::formatted(StringView { format, strlen(format) }, args...))); object.set("static_offset"sv, 0); object.set("invariant_offset"sv, has_invariant ? option_to_complete.length() : 0u); object.set("display_trivia"sv, StringView { option.help_string, strlen(option.help_string) }); diff --git a/Libraries/LibDevTools/Actor.cpp b/Libraries/LibDevTools/Actor.cpp index 57af75e9330..0089d5954b2 100644 --- a/Libraries/LibDevTools/Actor.cpp +++ b/Libraries/LibDevTools/Actor.cpp @@ -11,9 +11,10 @@ namespace DevTools { +// FIXME: Convert `name` to a String. Actor::Actor(DevToolsServer& devtools, ByteString name) : m_devtools(devtools) - , m_name(move(name)) + , m_name(MUST(String::from_byte_string(name))) { } @@ -36,7 +37,7 @@ void Actor::send_missing_parameter_error(StringView parameter) JsonObject error; error.set("from"sv, name()); error.set("error"sv, "missingParameter"sv); - error.set("message"sv, ByteString::formatted("Missing parameter: '{}'", parameter)); + error.set("message"sv, MUST(String::formatted("Missing parameter: '{}'", parameter))); send_message(move(error)); } @@ -46,7 +47,7 @@ void Actor::send_unrecognized_packet_type_error(StringView type) JsonObject error; error.set("from"sv, name()); error.set("error"sv, "unrecognizedPacketType"sv); - error.set("message"sv, ByteString::formatted("Unrecognized packet type: '{}'", type)); + error.set("message"sv, MUST(String::formatted("Unrecognized packet type: '{}'", type))); send_message(move(error)); } @@ -57,7 +58,7 @@ void Actor::send_unknown_actor_error(StringView actor) JsonObject error; error.set("from"sv, name()); error.set("error"sv, "unknownActor"sv); - error.set("message"sv, ByteString::formatted("Unknown actor: '{}'", actor)); + error.set("message"sv, MUST(String::formatted("Unknown actor: '{}'", actor))); send_message(move(error)); } diff --git a/Libraries/LibDevTools/Actor.h b/Libraries/LibDevTools/Actor.h index 0b8728ad8d6..21ef242bb87 100644 --- a/Libraries/LibDevTools/Actor.h +++ b/Libraries/LibDevTools/Actor.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,7 @@ class Actor public: virtual ~Actor(); - ByteString const& name() const { return m_name; } + String const& name() const { return m_name; } virtual void handle_message(StringView type, JsonObject const&) = 0; class [[nodiscard]] BlockToken { @@ -57,7 +58,7 @@ protected: private: DevToolsServer& m_devtools; - ByteString m_name; + String m_name; Vector m_blocked_responses; bool m_block_responses { false }; diff --git a/Libraries/LibDevTools/Actors/CSSPropertiesActor.cpp b/Libraries/LibDevTools/Actors/CSSPropertiesActor.cpp index 2b3ad4016de..bb55662d4af 100644 --- a/Libraries/LibDevTools/Actors/CSSPropertiesActor.cpp +++ b/Libraries/LibDevTools/Actors/CSSPropertiesActor.cpp @@ -36,7 +36,7 @@ void CSSPropertiesActor::handle_message(StringView type, JsonObject const&) for (auto const& css_property : css_property_list) { JsonArray subproperties; - subproperties.must_append(css_property.name); + subproperties.must_append(MUST(String::from_byte_string(css_property.name))); JsonObject property; property.set("isInherited"sv, css_property.is_inherited); diff --git a/Libraries/LibDevTools/Actors/DeviceActor.cpp b/Libraries/LibDevTools/Actors/DeviceActor.cpp index b0fb4b83414..0fdedb3b924 100644 --- a/Libraries/LibDevTools/Actors/DeviceActor.cpp +++ b/Libraries/LibDevTools/Actors/DeviceActor.cpp @@ -27,16 +27,16 @@ DeviceActor::~DeviceActor() = default; void DeviceActor::handle_message(StringView type, JsonObject const&) { if (type == "getDescription"sv) { - auto build_id = Core::Version::read_long_version_string().to_byte_string(); + auto build_id = Core::Version::read_long_version_string(); - static constexpr auto browser_name = StringView { BROWSER_NAME, __builtin_strlen(BROWSER_NAME) }; - static constexpr auto browser_version = StringView { BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) }; - static constexpr auto platform_name = StringView { OS_STRING, __builtin_strlen(OS_STRING) }; - static constexpr auto arch = StringView { CPU_STRING, __builtin_strlen(CPU_STRING) }; + static auto browser_name = String::from_utf8_without_validation({ BROWSER_NAME, __builtin_strlen(BROWSER_NAME) }); + static auto browser_version = String::from_utf8_without_validation({ BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) }); + static auto platform_name = String::from_utf8_without_validation({ OS_STRING, __builtin_strlen(OS_STRING) }); + static auto arch = String::from_utf8_without_validation({ CPU_STRING, __builtin_strlen(CPU_STRING) }); // https://github.com/mozilla/gecko-dev/blob/master/devtools/shared/system.js JsonObject value; - value.set("apptype"sv, browser_name.to_lowercase_string()); + value.set("apptype"sv, browser_name.to_ascii_lowercase()); value.set("name"sv, browser_name); value.set("brandName"sv, browser_name); value.set("version"sv, browser_version); diff --git a/Libraries/LibDevTools/Actors/FrameActor.cpp b/Libraries/LibDevTools/Actors/FrameActor.cpp index 898a2d0b6d0..15619df5acc 100644 --- a/Libraries/LibDevTools/Actors/FrameActor.cpp +++ b/Libraries/LibDevTools/Actors/FrameActor.cpp @@ -50,8 +50,8 @@ void FrameActor::send_frame_update_message() if (auto tab_actor = m_tab.strong_ref()) { JsonObject frame; frame.set("id"sv, tab_actor->description().id); - frame.set("title"sv, tab_actor->description().title); - frame.set("url"sv, tab_actor->description().url); + frame.set("title"sv, MUST(String::from_byte_string(tab_actor->description().title))); + frame.set("url"sv, MUST(String::from_byte_string(tab_actor->description().url))); frames.must_append(move(frame)); } @@ -76,8 +76,8 @@ JsonObject FrameActor::serialize_target() const target.set("actor"sv, name()); if (auto tab_actor = m_tab.strong_ref()) { - target.set("title"sv, tab_actor->description().title); - target.set("url"sv, tab_actor->description().url); + target.set("title"sv, MUST(String::from_byte_string(tab_actor->description().title))); + target.set("url"sv, MUST(String::from_byte_string(tab_actor->description().url))); target.set("browsingContextID"sv, tab_actor->description().id); target.set("outerWindowID"sv, tab_actor->description().id); target.set("isTopLevelTarget"sv, true); diff --git a/Libraries/LibDevTools/Actors/RootActor.cpp b/Libraries/LibDevTools/Actors/RootActor.cpp index f71927e2d71..76871b28932 100644 --- a/Libraries/LibDevTools/Actors/RootActor.cpp +++ b/Libraries/LibDevTools/Actors/RootActor.cpp @@ -57,9 +57,9 @@ void RootActor::handle_message(StringView type, JsonObject const& message) for (auto const& actor : devtools().actor_registry()) { if (is(*actor.value)) - response.set("deviceActor"sv, actor.key); + response.set("deviceActor"sv, MUST(String::from_byte_string(actor.key))); else if (is(*actor.value)) - response.set("preferenceActor"sv, actor.key); + response.set("preferenceActor"sv, MUST(String::from_byte_string(actor.key))); } send_message(move(response)); diff --git a/Libraries/LibDevTools/Actors/TabActor.cpp b/Libraries/LibDevTools/Actors/TabActor.cpp index b7a25fef02d..cfc0c2a16b9 100644 --- a/Libraries/LibDevTools/Actors/TabActor.cpp +++ b/Libraries/LibDevTools/Actors/TabActor.cpp @@ -60,8 +60,8 @@ JsonObject TabActor::serialize_description() const // provide different IDs for browserId, browsingContextID, and outerWindowID. JsonObject description; description.set("actor"sv, name()); - description.set("title"sv, m_description.title); - description.set("url"sv, m_description.url); + description.set("title"sv, MUST(String::from_byte_string(m_description.title))); + description.set("url"sv, MUST(String::from_byte_string(m_description.url))); description.set("browserId"sv, m_description.id); description.set("browsingContextID"sv, m_description.id); description.set("outerWindowID"sv, m_description.id); diff --git a/Libraries/LibDevTools/Actors/WalkerActor.cpp b/Libraries/LibDevTools/Actors/WalkerActor.cpp index 7f62433a26a..a833dd42bd1 100644 --- a/Libraries/LibDevTools/Actors/WalkerActor.cpp +++ b/Libraries/LibDevTools/Actors/WalkerActor.cpp @@ -135,12 +135,12 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const if (!tab) return {}; - auto actor = node.get_byte_string("actor"sv); + auto actor = node.get_string("actor"sv); if (!actor.has_value()) return {}; - auto name = node.get_byte_string("name"sv).release_value(); - auto type = node.get_byte_string("type"sv).release_value(); + auto name = node.get_string("name"sv).release_value(); + auto type = node.get_string("type"sv).release_value(); auto dom_type = Web::DOM::NodeType::INVALID; JsonValue node_value; @@ -157,12 +157,12 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const } else if (type == "text"sv) { dom_type = Web::DOM::NodeType::TEXT_NODE; - if (auto text = node.get_byte_string("text"sv); text.has_value()) + if (auto text = node.get_string("text"sv); text.has_value()) node_value = text.release_value(); } else if (type == "comment"sv) { dom_type = Web::DOM::NodeType::COMMENT_NODE; - if (auto data = node.get_byte_string("data"sv); data.has_value()) + if (auto data = node.get_string("data"sv); data.has_value()) node_value = data.release_value(); } else if (type == "shadow-root"sv) { is_shadow_root = true; @@ -180,7 +180,7 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const return; JsonObject attr; - attr.set("name"sv, name.to_byte_string()); + attr.set("name"sv, name); attr.set("value"sv, value.as_string()); attrs.must_append(move(attr)); }); @@ -189,10 +189,10 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const JsonObject serialized; serialized.set("actor"sv, actor.release_value()); serialized.set("attrs"sv, move(attrs)); - serialized.set("baseURI"sv, tab->description().url); + serialized.set("baseURI"sv, MUST(String::from_byte_string(tab->description().url))); serialized.set("causesOverflow"sv, false); serialized.set("containerType"sv, JsonValue {}); - serialized.set("displayName"sv, name.to_lowercase()); + serialized.set("displayName"sv, name.to_ascii_lowercase()); serialized.set("displayType"sv, "block"sv); serialized.set("host"sv, JsonValue {}); serialized.set("isAfterPseudoElement"sv, false); @@ -216,7 +216,7 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const if (!is_top_level_document) { if (auto parent = m_dom_node_to_parent_map.get(&node); parent.has_value() && parent.value()) { - actor = parent.value()->get_byte_string("actor"sv); + actor = parent.value()->get_string("actor"sv); if (!actor.has_value()) return {}; @@ -255,8 +255,8 @@ void WalkerActor::populate_dom_tree_cache(JsonObject& node, JsonObject const* pa { m_dom_node_to_parent_map.set(&node, parent); - auto actor = ByteString::formatted("{}-node{}", name(), m_dom_node_count++); - m_actor_to_dom_node_map.set(actor, &node); + auto actor = MUST(String::formatted("{}-node{}", name(), m_dom_node_count++)); + m_actor_to_dom_node_map.set(actor.to_byte_string(), &node); node.set("actor"sv, actor); auto children = node.get_array("children"sv); diff --git a/Libraries/LibGC/Heap.cpp b/Libraries/LibGC/Heap.cpp index 27aa0e4cd35..f470c42f4c7 100644 --- a/Libraries/LibGC/Heap.cpp +++ b/Libraries/LibGC/Heap.cpp @@ -176,7 +176,7 @@ public: for (auto& it : m_graph) { AK::JsonArray edges; for (auto const& value : it.value.edges) { - edges.must_append(ByteString::formatted("{}", value)); + edges.must_append(MUST(String::formatted("{}", value))); } auto node = AK::JsonObject(); @@ -185,7 +185,7 @@ public: auto location = it.value.root_origin->location; switch (type) { case HeapRoot::Type::Root: - node.set("root"sv, ByteString::formatted("Root {} {}:{}", location->function_name(), location->filename(), location->line_number())); + node.set("root"sv, MUST(String::formatted("Root {} {}:{}", location->function_name(), location->filename(), location->line_number()))); break; case HeapRoot::Type::RootVector: node.set("root"sv, "RootVector"sv); diff --git a/Libraries/LibWeb/Crypto/CryptoBindings.cpp b/Libraries/LibWeb/Crypto/CryptoBindings.cpp index 5509132c6b3..ec7812b585e 100644 --- a/Libraries/LibWeb/Crypto/CryptoBindings.cpp +++ b/Libraries/LibWeb/Crypto/CryptoBindings.cpp @@ -68,7 +68,7 @@ JS::ThrowCompletionOr JsonWebKey::parse(JS::Realm& realm, ReadonlyBy key.key_ops->ensure_capacity(key_ops->size()); key_ops->for_each([&](auto const& value) { - key.key_ops->append(MUST(String::from_byte_string(value.as_string()))); + key.key_ops->append(value.as_string()); }); } diff --git a/Libraries/LibWeb/WebDriver/Capabilities.cpp b/Libraries/LibWeb/WebDriver/Capabilities.cpp index f222050a9c1..73a675fb97e 100644 --- a/Libraries/LibWeb/WebDriver/Capabilities.cpp +++ b/Libraries/LibWeb/WebDriver/Capabilities.cpp @@ -235,9 +235,9 @@ static bool matches_platform_name(StringView requested_platform_name, StringView // https://w3c.github.io/webdriver/#dfn-matching-capabilities static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags flags) { - static auto browser_name = StringView { BROWSER_NAME, strlen(BROWSER_NAME) }.to_lowercase_string(); - static constexpr auto browser_version = StringView { BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) }; - static auto platform_name = StringView { OS_STRING, strlen(OS_STRING) }.to_lowercase_string(); + static auto browser_name = String::from_utf8_without_validation({ BROWSER_NAME, __builtin_strlen(BROWSER_NAME) }).to_ascii_lowercase(); + static auto browser_version = String::from_utf8_without_validation({ BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) }); + static auto platform_name = String::from_utf8_without_validation({ OS_STRING, __builtin_strlen(OS_STRING) }).to_ascii_lowercase(); // 1. Let matched capabilities be a JSON Object with the following entries: JsonObject matched_capabilities; @@ -283,7 +283,7 @@ static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags // -> "browserName" if (name == "browserName"sv) { // If value is not a string equal to the "browserName" entry in matched capabilities, return success with data null. - if (value.as_string() != matched_capabilities.get_byte_string(name).value()) + if (value.as_string() != matched_capabilities.get_string(name).value()) return AK::Error::from_string_literal("browserName"); } // -> "browserVersion" diff --git a/Libraries/LibWeb/WebDriver/Client.cpp b/Libraries/LibWeb/WebDriver/Client.cpp index 51324a7d457..514d38a6e14 100644 --- a/Libraries/LibWeb/WebDriver/Client.cpp +++ b/Libraries/LibWeb/WebDriver/Client.cpp @@ -329,8 +329,8 @@ ErrorOr Client::send_error_response(HTTP::HttpReques auto reason = HTTP::HttpResponse::reason_phrase_for_code(error.http_status); JsonObject error_response; - error_response.set("error"sv, error.error); - error_response.set("message"sv, error.message); + error_response.set("error"sv, MUST(String::from_byte_string(error.error))); + error_response.set("message"sv, MUST(String::from_byte_string(error.message))); error_response.set("stacktrace"sv, ""sv); if (error.data.has_value()) error_response.set("data"sv, *error.data); diff --git a/Libraries/LibWeb/WebDriver/Contexts.cpp b/Libraries/LibWeb/WebDriver/Contexts.cpp index dcb72c3e2a2..12cdb82d233 100644 --- a/Libraries/LibWeb/WebDriver/Contexts.cpp +++ b/Libraries/LibWeb/WebDriver/Contexts.cpp @@ -39,7 +39,7 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window) // identifier // Associated window handle of the window’s browsing context. - object.set(identifier, navigable->traversable_navigable()->window_handle().to_byte_string()); + object.set(identifier, navigable->traversable_navigable()->window_handle()); return object; } diff --git a/Libraries/LibWeb/WebDriver/ElementReference.cpp b/Libraries/LibWeb/WebDriver/ElementReference.cpp index 597b7acdc91..bbf667e5e3d 100644 --- a/Libraries/LibWeb/WebDriver/ElementReference.cpp +++ b/Libraries/LibWeb/WebDriver/ElementReference.cpp @@ -132,7 +132,7 @@ JsonObject web_element_reference_object(HTML::BrowsingContext const& browsing_co // 3. Return a JSON Object initialized with a property with name identifier and value reference. JsonObject object; - object.set(identifier, reference); + object.set(identifier, MUST(String::from_byte_string(reference))); return object; } @@ -422,7 +422,7 @@ JsonObject shadow_root_reference_object(HTML::BrowsingContext const& browsing_co // 3. Return a JSON Object initialized with a property with name identifier and value reference. JsonObject object; - object.set(identifier, reference); + object.set(identifier, MUST(String::from_byte_string(reference))); return object; } diff --git a/Libraries/LibWeb/WebDriver/Properties.h b/Libraries/LibWeb/WebDriver/Properties.h index a36ef382bf2..80a1a2806a1 100644 --- a/Libraries/LibWeb/WebDriver/Properties.h +++ b/Libraries/LibWeb/WebDriver/Properties.h @@ -40,7 +40,7 @@ static ErrorOr get_property(JsonObject const& pa if constexpr (IsSame) { if (!property->is_string()) return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a String", key)); - return property->as_string(); + return property->as_string().to_byte_string(); } else if constexpr (IsSame) { if (!property->is_bool()) return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Boolean", key)); diff --git a/Libraries/LibWebView/InspectorClient.cpp b/Libraries/LibWebView/InspectorClient.cpp index 5f78db6edcb..a6962ce7658 100644 --- a/Libraries/LibWebView/InspectorClient.cpp +++ b/Libraries/LibWebView/InspectorClient.cpp @@ -655,7 +655,7 @@ String InspectorClient::generate_dom_tree(JsonObject const& dom_tree) builder.appendff("\"{}\"", escape_html_entities(value_string)); builder.append(""sv); - dom_node_attributes.empend(name, MUST(String::from_byte_string(value_string))); + dom_node_attributes.empend(name, value_string); }); } diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSEnums.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSEnums.cpp index a4a5da0c4be..ae8797552d0 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSEnums.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSEnums.cpp @@ -128,7 +128,7 @@ Optional<@name:titlecase@> keyword_to_@name:snakecase@(Keyword keyword) auto member_generator = enum_generator.fork(); auto member_name = member.as_string(); if (member_name.contains('=')) { - auto parts = member_name.split_view('='); + auto parts = MUST(member_name.split('=')); member_generator.set("valueid:titlecase", title_casify(parts[0])); member_generator.set("member:titlecase", title_casify(parts[1])); } else { diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMediaFeatureID.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMediaFeatureID.cpp index f191b1d4fd1..da15ee29151 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMediaFeatureID.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMediaFeatureID.cpp @@ -182,7 +182,7 @@ bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureVal VERIFY(type.is_string()); auto type_name = type.as_string(); // Skip keywords. - if (type_name[0] != '<') + if (!type_name.starts_with('<')) continue; if (type_name == "") { append_value_type_switch_if_needed(); @@ -258,9 +258,9 @@ bool media_feature_accepts_keyword(MediaFeatureID media_feature_id, Keyword keyw auto& values_array = values.value(); for (auto& keyword : values_array.values()) { VERIFY(keyword.is_string()); - auto keyword_name = keyword.as_string(); + auto const& keyword_name = keyword.as_string(); // Skip types. - if (keyword_name[0] == '<') + if (keyword_name.starts_with('<')) continue; append_keyword_switch_if_needed(); diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp index 832c2b11c9e..6035208e243 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp @@ -91,7 +91,7 @@ ErrorOr serenity_main(Main::Arguments arguments) void replace_logical_aliases(JsonObject& properties) { - AK::HashMap logical_aliases; + AK::HashMap logical_aliases; properties.for_each_member([&](auto& name, auto& value) { VERIFY(value.is_object()); auto const& value_as_object = value.as_object(); @@ -319,7 +319,7 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @ return; if (auto maybe_valid_types = value.as_object().get_array("valid-types"sv); maybe_valid_types.has_value() && !maybe_valid_types->is_empty()) { for (auto valid_type : maybe_valid_types->values()) { - auto type_and_range = valid_type.as_string().split_view(' '); + auto type_and_range = MUST(valid_type.as_string().split(' ')); if (type_and_range.first() != css_type_name) continue; @@ -333,9 +333,9 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @ if (type_and_range.size() > 1) { auto range = type_and_range[1]; VERIFY(range.starts_with('[') && range.ends_with(']') && range.contains(',')); - auto comma_index = range.find(',').value(); - StringView min_value_string = range.substring_view(1, comma_index - 1); - StringView max_value_string = range.substring_view(comma_index + 1, range.length() - comma_index - 2); + auto comma_index = range.find_byte_offset(',').value(); + StringView min_value_string = range.bytes_as_string_view().substring_view(1, comma_index - 1); + StringView max_value_string = range.bytes_as_string_view().substring_view(comma_index + 1, range.byte_count() - comma_index - 2); // If the min/max value is infinite, we can just skip that side of the check. if (min_value_string == "-∞") @@ -782,7 +782,7 @@ bool property_accepts_type(PropertyID property_id, ValueType value_type) bool did_output_accepted_type = false; for (auto& type : valid_types.values()) { VERIFY(type.is_string()); - auto type_name = type.as_string().split_view(' ').first(); + auto type_name = MUST(type.as_string().split(' ')).first(); if (type_name_is_enum(type_name)) continue; @@ -888,7 +888,7 @@ bool property_accepts_keyword(PropertyID property_id, Keyword keyword) if (auto maybe_valid_types = object.get_array("valid-types"sv); maybe_valid_types.has_value() && !maybe_valid_types->is_empty()) { auto& valid_types = maybe_valid_types.value(); for (auto& valid_type : valid_types.values()) { - auto type_name = valid_type.as_string().split_view(' ').first(); + auto type_name = MUST(valid_type.as_string().split(' ')).first(); if (!type_name_is_enum(type_name)) continue; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSTransformFunctions.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSTransformFunctions.cpp index 475a47e15ca..9ca747cbc7d 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSTransformFunctions.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSTransformFunctions.cpp @@ -171,7 +171,7 @@ TransformFunctionMetadata transform_function_metadata(TransformFunction transfor JsonArray const& parameters = value.as_object().get_array("parameters"sv).value(); bool first = true; parameters.for_each([&](JsonValue const& value) { - GenericLexer lexer { value.as_object().get_byte_string("type"sv).value() }; + GenericLexer lexer { value.as_object().get_string("type"sv).value() }; VERIFY(lexer.consume_specific('<')); auto parameter_type_name = lexer.consume_until('>'); VERIFY(lexer.consume_specific('>')); diff --git a/Services/WebContent/WebDriverConnection.cpp b/Services/WebContent/WebDriverConnection.cpp index c7bbb2bdb17..69c9f151d14 100644 --- a/Services/WebContent/WebDriverConnection.cpp +++ b/Services/WebContent/WebDriverConnection.cpp @@ -83,10 +83,10 @@ namespace WebContent { static JsonValue serialize_cookie(Web::Cookie::Cookie const& cookie) { JsonObject serialized_cookie; - serialized_cookie.set("name"sv, cookie.name.to_byte_string()); - serialized_cookie.set("value"sv, cookie.value.to_byte_string()); - serialized_cookie.set("path"sv, cookie.path.to_byte_string()); - serialized_cookie.set("domain"sv, cookie.domain.to_byte_string()); + serialized_cookie.set("name"sv, cookie.name); + serialized_cookie.set("value"sv, cookie.value); + serialized_cookie.set("path"sv, cookie.path); + serialized_cookie.set("domain"sv, cookie.domain); serialized_cookie.set("secure"sv, cookie.secure); serialized_cookie.set("httpOnly"sv, cookie.http_only); serialized_cookie.set("expiry"sv, cookie.expiry_time.seconds_since_epoch()); @@ -346,7 +346,7 @@ Messages::WebDriverClient::GetCurrentUrlResponse WebDriverConnection::get_curren auto url = current_top_level_browsing_context()->active_document()->url(); // 4. Return success with data url. - async_driver_execution_complete({ url.to_byte_string() }); + async_driver_execution_complete({ url.to_string() }); }); return JsonValue {}; @@ -529,7 +529,7 @@ Messages::WebDriverClient::GetTitleResponse WebDriverConnection::get_title() auto title = current_top_level_browsing_context()->active_document()->title(); // 4. Return success with data title. - async_driver_execution_complete({ title.to_byte_string() }); + async_driver_execution_complete({ move(title) }); }); return JsonValue {}; @@ -1323,7 +1323,7 @@ Messages::WebDriverClient::GetElementAttributeResponse WebDriverConnection::get_ } // 5. Return success with data result. - async_driver_execution_complete({ result.to_byte_string() }); + async_driver_execution_complete({ move(result) }); }); return JsonValue {}; @@ -1389,7 +1389,7 @@ Messages::WebDriverClient::GetElementCssValueResponse WebDriverConnection::get_e // "" (empty string) // 5. Return success with data computed value. - async_driver_execution_complete({ computed_value.to_byte_string() }); + async_driver_execution_complete({ move(computed_value) }); }); return JsonValue {}; @@ -1411,7 +1411,7 @@ Messages::WebDriverClient::GetElementTextResponse WebDriverConnection::get_eleme auto rendered_text = Web::WebDriver::element_rendered_text(element); // 5. Return success with data rendered text. - async_driver_execution_complete({ rendered_text.to_byte_string() }); + async_driver_execution_complete({ move(rendered_text) }); }); return JsonValue {}; @@ -1434,7 +1434,7 @@ Messages::WebDriverClient::GetElementTagNameResponse WebDriverConnection::get_el auto qualified_name = element->local_name(); // 5. Return success with data qualified name. - async_driver_execution_complete({ qualified_name.to_string().to_byte_string() }); + async_driver_execution_complete({ qualified_name.to_string() }); }); return JsonValue {}; @@ -1541,7 +1541,7 @@ Messages::WebDriverClient::GetComputedLabelResponse WebDriverConnection::get_com auto label = element->accessible_name(element->document()).release_value_but_fixme_should_propagate_errors(); // 5. Return success with data label. - async_driver_execution_complete({ label.to_byte_string() }); + async_driver_execution_complete({ move(label) }); }); return JsonValue {}; @@ -2047,7 +2047,7 @@ Messages::WebDriverClient::GetSourceResponse WebDriverConnection::get_source() source = MUST(document->serialize_fragment(Web::DOMParsing::RequireWellFormed::No)); // 5. Return success with data source. - async_driver_execution_complete({ source->to_byte_string() }); + async_driver_execution_complete({ source.release_value() }); }); return JsonValue {}; @@ -2465,7 +2465,7 @@ Messages::WebDriverClient::GetAlertTextResponse WebDriverConnection::get_alert_t // 4. Return success with data message. if (message.has_value()) - return message->to_byte_string(); + return message.value(); return JsonValue {}; } @@ -2679,7 +2679,7 @@ static Web::WebDriver::Error create_annotated_unexpected_alert_open_error(Option // The current user prompt's message. auto data = text.map([&](auto const& text) -> JsonValue { JsonObject data; - data.set("text"sv, text.to_byte_string()); + data.set("text"sv, text); return data; }); diff --git a/Services/WebDriver/Client.cpp b/Services/WebDriver/Client.cpp index 9dffefebb91..7bfa075011d 100644 --- a/Services/WebDriver/Client.cpp +++ b/Services/WebDriver/Client.cpp @@ -131,7 +131,7 @@ Web::WebDriver::Response Client::get_status(Web::WebDriver::Parameters, JsonValu // An implementation-defined string explaining the remote end's readiness state. JsonObject body; body.set("ready"sv, readiness_state); - body.set("message"sv, ByteString::formatted("{} to accept a new session", readiness_state ? "Ready"sv : "Not ready"sv)); + body.set("message"sv, MUST(String::formatted("{} to accept a new session", readiness_state ? "Ready"sv : "Not ready"sv))); // 2. Return success with data body. return JsonValue { body }; diff --git a/Services/WebDriver/Session.cpp b/Services/WebDriver/Session.cpp index 1cffccdf6ff..66b25f8a208 100644 --- a/Services/WebDriver/Session.cpp +++ b/Services/WebDriver/Session.cpp @@ -221,7 +221,7 @@ ErrorOr> Session::create_server(NonnullRefPtron_close = [this, window_handle]() { dbgln_if(WEBDRIVER_DEBUG, "Window {} was closed remotely.", window_handle); diff --git a/Tests/AK/TestJSON.cpp b/Tests/AK/TestJSON.cpp index 31b357ebf04..a1483f9addd 100644 --- a/Tests/AK/TestJSON.cpp +++ b/Tests/AK/TestJSON.cpp @@ -66,7 +66,7 @@ TEST_CASE(json_string) { auto json = JsonValue::from_string("\"A\""sv).value(); EXPECT_EQ(json.type(), JsonValue::Type::String); - EXPECT_EQ(json.as_string().length(), size_t { 1 }); + EXPECT_EQ(json.as_string().byte_count(), size_t { 1 }); EXPECT_EQ(json.as_string() == "A", true); } @@ -74,7 +74,7 @@ TEST_CASE(json_utf8_character) { auto json = JsonValue::from_string("\"\\u0041\""sv).value(); EXPECT_EQ(json.type(), JsonValue::Type::String); - EXPECT_EQ(json.as_string().length(), size_t { 1 }); + EXPECT_EQ(json.as_string().byte_count(), size_t { 1 }); EXPECT_EQ(json.as_string() == "A", true); } @@ -83,19 +83,19 @@ TEST_CASE(json_encoded_surrogates) { auto json = JsonValue::from_string("\"\\uD83E\\uDD13\""sv).value(); EXPECT_EQ(json.type(), JsonValue::Type::String); - EXPECT_EQ(json.as_string().length(), 4u); + EXPECT_EQ(json.as_string().byte_count(), 4u); EXPECT_EQ(json.as_string(), "🤓"sv); } { auto json = JsonValue::from_string("\"\\uD83E\""sv).value(); EXPECT_EQ(json.type(), JsonValue::Type::String); - EXPECT_EQ(json.as_string().length(), 3u); + EXPECT_EQ(json.as_string().byte_count(), 3u); EXPECT_EQ(json.as_string(), "\xED\xA0\xBE"sv); } { auto json = JsonValue::from_string("\"\\uDD13\""sv).value(); EXPECT_EQ(json.type(), JsonValue::Type::String); - EXPECT_EQ(json.as_string().length(), 3u); + EXPECT_EQ(json.as_string().byte_count(), 3u); EXPECT_EQ(json.as_string(), "\xED\xB4\x93"sv); } } @@ -110,7 +110,7 @@ TEST_CASE(json_utf8_multibyte) auto& json = json_or_error.value(); EXPECT_EQ(json.type(), JsonValue::Type::String); - EXPECT_EQ(json.as_string().length(), size_t { 2 }); + EXPECT_EQ(json.as_string().byte_count(), size_t { 2 }); EXPECT_EQ(json.as_string() == "š", true); EXPECT_EQ(json.as_string() == "\xc5\xa1", true); } diff --git a/Tests/LibJS/test-test262.cpp b/Tests/LibJS/test-test262.cpp index 788f01d64b3..a5d6e9eab82 100644 --- a/Tests/LibJS/test-test262.cpp +++ b/Tests/LibJS/test-test262.cpp @@ -317,8 +317,8 @@ void write_per_file(HashMap const& result_map, Vectorwrite_until_depleted(complete_results.to_byte_string()).is_error()) warnln("Failed to write per-file"); diff --git a/Tests/LibJS/test262-runner.cpp b/Tests/LibJS/test262-runner.cpp index 6413c353230..c90e5eed2a8 100644 --- a/Tests/LibJS/test262-runner.cpp +++ b/Tests/LibJS/test262-runner.cpp @@ -46,8 +46,8 @@ enum class NegativePhase { struct TestError { NegativePhase phase { NegativePhase::ParseOrEarly }; - ByteString type; - ByteString details; + String type; + String details; ByteString harness_file; }; @@ -60,8 +60,8 @@ static ErrorOr parse_program(JS::Realm& realm, if (script_or_error.is_error()) { return TestError { NegativePhase::ParseOrEarly, - "SyntaxError", - script_or_error.error()[0].to_byte_string(), + "SyntaxError"_string, + script_or_error.error()[0].to_string(), "" }; } @@ -92,22 +92,22 @@ static ErrorOr run_program(InterpreterT& interpreter, ScriptOrM auto name = object.get_without_side_effects("name"); if (!name.is_empty() && !name.is_accessor()) { - error.type = name.to_string_without_side_effects().to_byte_string(); + error.type = name.to_string_without_side_effects(); } else { auto constructor = object.get_without_side_effects("constructor"); if (constructor.is_object()) { name = constructor.as_object().get_without_side_effects("name"); if (!name.is_undefined()) - error.type = name.to_string_without_side_effects().to_byte_string(); + error.type = name.to_string_without_side_effects(); } } auto message = object.get_without_side_effects("message"); if (!message.is_empty() && !message.is_accessor()) - error.details = message.to_string_without_side_effects().to_byte_string(); + error.details = message.to_string_without_side_effects(); } if (error.type.is_empty()) - error.type = error_value.to_string_without_side_effects().to_byte_string(); + error.type = error_value.to_string_without_side_effects(); return error; } return {}; @@ -136,8 +136,8 @@ static ErrorOr read_harness_file(StringView harness_file) if (cache.is_error()) { return TestError { NegativePhase::Harness, - "filesystem", - ByteString::formatted("Could not read file: {}", harness_file), + "filesystem"_string, + MUST(String::formatted("Could not read file: {}", harness_file)), harness_file }; } @@ -202,8 +202,8 @@ static ErrorOr run_test(StringView source, StringView filepath, if (parser.has_errors()) { return TestError { NegativePhase::ParseOrEarly, - "SyntaxError", - parser.errors()[0].to_byte_string(), + "SyntaxError"_string, + parser.errors()[0].to_string(), "" }; } @@ -250,14 +250,14 @@ static ErrorOr run_test(StringView source, StringView filepath, return run_program(vm->bytecode_interpreter(), program); } -static ErrorOr extract_metadata(StringView source) +static ErrorOr extract_metadata(StringView source) { auto lines = source.lines(); TestMetadata metadata; bool parsing_negative = false; - ByteString failed_message; + String failed_message; auto parse_list = [&](StringView line) { auto start = line.find('['); @@ -268,7 +268,7 @@ static ErrorOr extract_metadata(StringView source) auto end = line.find_last(']'); if (!end.has_value() || end.value() <= start.value()) { - failed_message = ByteString::formatted("Can't parse list in '{}'", line); + failed_message = MUST(String::formatted("Can't parse list in '{}'", line)); return items; } @@ -281,7 +281,7 @@ static ErrorOr extract_metadata(StringView source) auto second_word = [&](StringView line) { auto separator = line.find(' '); if (!separator.has_value() || separator.value() >= (line.length() - 1u)) { - failed_message = ByteString::formatted("Can't parse value after space in '{}'", line); + failed_message = MUST(String::formatted("Can't parse value after space in '{}'", line)); return ""sv; } return line.substring_view(separator.value() + 1); @@ -311,7 +311,7 @@ static ErrorOr extract_metadata(StringView source) continue; } else { if (include_list.is_empty()) { - failed_message = "Supposed to parse a list but found no entries"; + failed_message = "Supposed to parse a list but found no entries"_string; break; } @@ -335,18 +335,18 @@ static ErrorOr extract_metadata(StringView source) metadata.phase = NegativePhase::Runtime; } else { has_phase = false; - failed_message = ByteString::formatted("Unknown negative phase: {}", phase); + failed_message = MUST(String::formatted("Unknown negative phase: {}", phase)); break; } } else if (line.starts_with("type:"sv)) { metadata.type = second_word(line); } else { if (!has_phase) { - failed_message = "Failed to find phase in negative attributes"; + failed_message = "Failed to find phase in negative attributes"_string; break; } if (metadata.type.is_empty()) { - failed_message = "Failed to find type in negative attributes"; + failed_message = "Failed to find type in negative attributes"_string; break; } @@ -392,7 +392,7 @@ static ErrorOr extract_metadata(StringView source) } if (failed_message.is_empty()) - failed_message = ByteString::formatted("Never reached end of comment '---*/'"); + failed_message = MUST(String::formatted("Never reached end of comment '---*/'")); return failed_message; } @@ -402,13 +402,13 @@ static bool verify_test(ErrorOr& result, TestMetadata const& me if (result.is_error()) { if (result.error().phase == NegativePhase::Harness) { output.set("harness_error"sv, true); - output.set("harness_file"sv, result.error().harness_file); + output.set("harness_file"sv, String::from_utf8_with_replacement_character(result.error().harness_file)); output.set("result"sv, "harness_error"sv); } else if (result.error().phase == NegativePhase::Runtime) { auto& error_type = result.error().type; auto& error_details = result.error().details; - if ((error_type == "InternalError"sv && error_details.starts_with("TODO("sv)) - || (error_type == "Test262Error"sv && error_details.ends_with(" but got a InternalError"sv))) { + if ((error_type == "InternalError"sv && error_details.starts_with_bytes("TODO("sv)) + || (error_type == "Test262Error"sv && error_details.ends_with_bytes(" but got a InternalError"sv))) { output.set("todo_error"sv, true); output.set("result"sv, "todo_error"sv); } @@ -467,7 +467,7 @@ static bool verify_test(ErrorOr& result, TestMetadata const& me JsonObject expected_error_object; expected_error_object.set("phase"sv, phase_to_string(metadata.phase)); - expected_error_object.set("type"sv, metadata.type.to_byte_string()); + expected_error_object.set("type"sv, metadata.type); expected_error = expected_error_object; @@ -528,7 +528,7 @@ static bool g_in_assert = false; // immediately stop if we are already in a failed assert. g_in_assert = true; JsonObject assert_fail_result; - assert_fail_result.set("test"sv, s_current_test); + assert_fail_result.set("test"sv, String::from_utf8_with_replacement_character(s_current_test)); assert_fail_result.set("assert_fail"sv, true); assert_fail_result.set("result"sv, "assert_fail"sv); assert_fail_result.set("output"sv, StringView { assert_failed_message, strlen(assert_failed_message) }); @@ -741,7 +741,7 @@ int main(int argc, char** argv) if (metadata_or_error.is_error()) { result_object.set("result"sv, "metadata_error"sv); result_object.set("metadata_error"sv, true); - result_object.set("metadata_output"sv, metadata_or_error.error()); + result_object.set("metadata_output"sv, metadata_or_error.release_error()); continue; } @@ -762,7 +762,7 @@ int main(int argc, char** argv) auto first_output = collect_output(); if (first_output.has_value()) - result_object.set("output"sv, *first_output); + result_object.set("output"sv, String::from_utf8_with_replacement_character(*first_output)); passed = verify_test(result, metadata, result_object); auto output = first_output.value_or(""); @@ -786,7 +786,7 @@ int main(int argc, char** argv) auto first_output = collect_output(); if (first_output.has_value()) - result_object.set("strict_output"sv, *first_output); + result_object.set("strict_output"sv, String::from_utf8_with_replacement_character(*first_output)); passed = verify_test(result, metadata, result_object); auto output = first_output.value_or(""); diff --git a/UI/Qt/AutoComplete.cpp b/UI/Qt/AutoComplete.cpp index 7c88271d768..abfd7c19975 100644 --- a/UI/Qt/AutoComplete.cpp +++ b/UI/Qt/AutoComplete.cpp @@ -45,7 +45,7 @@ ErrorOr> AutoComplete::parse_google_autocomplete(Vector> AutoComplete::parse_google_autocomplete(Vector results; results.ensure_capacity(suggestions_array.size()); for (auto& suggestion : suggestions_array) - results.unchecked_append(MUST(String::from_byte_string(suggestion.as_string()))); + results.unchecked_append(suggestion.as_string()); return results; } @@ -65,11 +65,13 @@ ErrorOr> AutoComplete::parse_google_autocomplete(Vector> AutoComplete::parse_duckduckgo_autocomplete(Vector const& json) { Vector results; + for (auto const& suggestion : json) { - auto maybe_value = suggestion.as_object().get("phrase"sv); - if (!maybe_value.has_value()) - continue; - results.append(MUST(String::from_byte_string(maybe_value->as_string()))); + if (!suggestion.is_object()) + return Error::from_string_literal("Invalid JSON, expected value to be an object"); + + if (auto value = suggestion.as_object().get_string("phrase"sv); !value.has_value()) + results.append(*value); } return results; @@ -77,28 +79,28 @@ ErrorOr> AutoComplete::parse_duckduckgo_autocomplete(Vector> AutoComplete::parse_yahoo_autocomplete(JsonObject const& json) { - if (!json.get("q"sv).has_value() || !json.get("q"sv)->is_string()) + auto query = json.get_string("q"sv); + if (!query.has_value()) return Error::from_string_view("Invalid JSON, expected \"q\" to be a string"sv); - auto query = TRY(String::from_byte_string(json.get("q"sv)->as_string())); - - if (!json.get("r"sv).has_value() || !json.get("r"sv)->is_array()) - return Error::from_string_view("Invalid JSON, expected \"r\" to be an object"sv); - auto suggestions_object = json.get("r"sv)->as_array().values(); - if (query != m_query) return Error::from_string_literal("Invalid JSON, query does not match"); - Vector results; - results.ensure_capacity(suggestions_object.size()); - for (auto& suggestion_object : suggestions_object) { - if (!suggestion_object.is_object()) - return Error::from_string_literal("Invalid JSON, expected value to be an object"); - auto suggestion = suggestion_object.as_object(); + auto suggestions = json.get_array("r"sv); + if (!suggestions.has_value()) + return Error::from_string_view("Invalid JSON, expected \"r\" to be an object"sv); - if (!suggestion.get("k"sv).has_value() || !suggestion.get("k"sv)->is_string()) + Vector results; + results.ensure_capacity(suggestions->size()); + + for (auto const& suggestion : suggestions->values()) { + if (!suggestion.is_object()) + return Error::from_string_literal("Invalid JSON, expected value to be an object"); + + auto result = suggestion.as_object().get_string("k"sv); + if (!result.has_value()) return Error::from_string_view("Invalid JSON, expected \"k\" to be a string"sv); - results.unchecked_append(MUST(String::from_byte_string(suggestion.get("k"sv)->as_string()))); + results.unchecked_append(*result); } return results;