1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-08 05:27:14 +09:00

AK+Everywhere: Store JSON strings as String

This commit is contained in:
Timothy Flynn 2025-02-17 13:21:07 -05:00 committed by Tim Flynn
parent e591636419
commit bc54c0cdfb
Notes: github-actions[bot] 2025-02-21 00:29:21 +00:00
33 changed files with 163 additions and 152 deletions

View file

@ -116,11 +116,17 @@ Optional<bool> JsonObject::get_bool(StringView key) const
return {}; return {};
} }
Optional<String const&> JsonObject::get_string(StringView key) const
{
if (auto value = get(key); value.has_value() && value->is_string())
return value->as_string();
return {};
}
Optional<ByteString> JsonObject::get_byte_string(StringView key) const Optional<ByteString> JsonObject::get_byte_string(StringView key) const
{ {
auto maybe_value = get(key); if (auto value = get_string(key); value.has_value())
if (maybe_value.has_value() && maybe_value->is_string()) return value->to_byte_string();
return maybe_value->as_string();
return {}; return {};
} }

View file

@ -76,6 +76,7 @@ public:
Optional<FlatPtr> get_addr(StringView key) const; Optional<FlatPtr> get_addr(StringView key) const;
Optional<bool> get_bool(StringView key) const; Optional<bool> get_bool(StringView key) const;
Optional<String const&> get_string(StringView key) const;
Optional<ByteString> get_byte_string(StringView key) const; Optional<ByteString> get_byte_string(StringView key) const;
Optional<JsonObject&> get_object(StringView key); Optional<JsonObject&> get_object(StringView key);
@ -144,7 +145,7 @@ inline void JsonValue::serialize(Builder& builder) const
[&](Empty const&) { builder.append("null"sv); }, [&](Empty const&) { builder.append("null"sv); },
[&](bool const& value) { builder.append(value ? "true"sv : "false"sv); }, [&](bool const& value) { builder.append(value ? "true"sv : "false"sv); },
[&](Arithmetic auto const& value) { builder.appendff("{}", value); }, [&](Arithmetic auto const& value) { builder.appendff("{}", value); },
[&](ByteString const& value) { [&](String const& value) {
builder.append('\"'); builder.append('\"');
builder.append_escaped_for_json(value.bytes()); builder.append_escaped_for_json(value.bytes());
builder.append('\"'); builder.append('\"');

View file

@ -57,7 +57,7 @@ public:
return {}; return {};
} }
ErrorOr<void> add(StringView key, ByteString const& value) ErrorOr<void> add(StringView key, String const& value)
{ {
TRY(begin_item(key)); TRY(begin_item(key));
if constexpr (IsLegacyBuilder<Builder>) { if constexpr (IsLegacyBuilder<Builder>) {

View file

@ -153,17 +153,17 @@ JsonValue::JsonValue(long long unsigned value)
} }
JsonValue::JsonValue(double value) JsonValue::JsonValue(double value)
: m_value(double { value })
{
}
JsonValue::JsonValue(ByteString const& value)
: m_value(value) : m_value(value)
{ {
} }
JsonValue::JsonValue(String value)
: m_value(move(value))
{
}
JsonValue::JsonValue(StringView value) JsonValue::JsonValue(StringView value)
: m_value(ByteString { value }) : m_value(MUST(String::from_utf8(value)))
{ {
} }

View file

@ -7,10 +7,10 @@
#pragma once #pragma once
#include <AK/ByteString.h>
#include <AK/Forward.h> #include <AK/Forward.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <AK/String.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
namespace AK { namespace AK {
@ -32,7 +32,7 @@ public:
i64, i64,
u64, u64,
double, double,
ByteString, String,
NonnullOwnPtr<JsonArray>, NonnullOwnPtr<JsonArray>,
NonnullOwnPtr<JsonObject>>; NonnullOwnPtr<JsonObject>>;
@ -53,9 +53,9 @@ public:
JsonValue(long unsigned); JsonValue(long unsigned);
JsonValue(long long); JsonValue(long long);
JsonValue(long long unsigned); JsonValue(long long unsigned);
JsonValue(double); JsonValue(double);
JsonValue(ByteString const&);
JsonValue(String);
JsonValue(StringView); JsonValue(StringView);
template<typename T> template<typename T>
@ -119,9 +119,9 @@ public:
return m_value.get<bool>(); return m_value.get<bool>();
} }
ByteString const& as_string() const String const& as_string() const
{ {
return m_value.get<ByteString>(); return m_value.get<String>();
} }
JsonObject& as_object() JsonObject& as_object()
@ -155,14 +155,14 @@ public:
[](Empty const&) { return Type::Null; }, [](Empty const&) { return Type::Null; },
[](bool const&) { return Type::Bool; }, [](bool const&) { return Type::Bool; },
[](Arithmetic auto const&) { return Type::Number; }, [](Arithmetic auto const&) { return Type::Number; },
[](ByteString const&) { return Type::String; }, [](String const&) { return Type::String; },
[](NonnullOwnPtr<JsonArray> const&) { return Type::Array; }, [](NonnullOwnPtr<JsonArray> const&) { return Type::Array; },
[](NonnullOwnPtr<JsonObject> const&) { return Type::Object; }); [](NonnullOwnPtr<JsonObject> const&) { return Type::Object; });
} }
bool is_null() const { return m_value.has<Empty>(); } bool is_null() const { return m_value.has<Empty>(); }
bool is_bool() const { return m_value.has<bool>(); } bool is_bool() const { return m_value.has<bool>(); }
bool is_string() const { return m_value.has<ByteString>(); } bool is_string() const { return m_value.has<String>(); }
bool is_array() const { return m_value.has<NonnullOwnPtr<JsonArray>>(); } bool is_array() const { return m_value.has<NonnullOwnPtr<JsonArray>>(); }
bool is_object() const { return m_value.has<NonnullOwnPtr<JsonObject>>(); } bool is_object() const { return m_value.has<NonnullOwnPtr<JsonObject>>(); }
bool is_number() const bool is_number() const

View file

@ -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) { auto write_completion = [&](auto format, auto& option, auto has_invariant, auto... args) {
JsonObject object; 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("static_offset"sv, 0);
object.set("invariant_offset"sv, has_invariant ? option_to_complete.length() : 0u); 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) }); object.set("display_trivia"sv, StringView { option.help_string, strlen(option.help_string) });

View file

@ -11,9 +11,10 @@
namespace DevTools { namespace DevTools {
// FIXME: Convert `name` to a String.
Actor::Actor(DevToolsServer& devtools, ByteString name) Actor::Actor(DevToolsServer& devtools, ByteString name)
: m_devtools(devtools) : 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; JsonObject error;
error.set("from"sv, name()); error.set("from"sv, name());
error.set("error"sv, "missingParameter"sv); 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)); send_message(move(error));
} }
@ -46,7 +47,7 @@ void Actor::send_unrecognized_packet_type_error(StringView type)
JsonObject error; JsonObject error;
error.set("from"sv, name()); error.set("from"sv, name());
error.set("error"sv, "unrecognizedPacketType"sv); 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)); send_message(move(error));
} }
@ -57,7 +58,7 @@ void Actor::send_unknown_actor_error(StringView actor)
JsonObject error; JsonObject error;
error.set("from"sv, name()); error.set("from"sv, name());
error.set("error"sv, "unknownActor"sv); 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)); send_message(move(error));
} }

View file

@ -10,6 +10,7 @@
#include <AK/ByteString.h> #include <AK/ByteString.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <AK/String.h>
#include <AK/StringView.h> #include <AK/StringView.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <AK/WeakPtr.h> #include <AK/WeakPtr.h>
@ -24,7 +25,7 @@ class Actor
public: public:
virtual ~Actor(); 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; virtual void handle_message(StringView type, JsonObject const&) = 0;
class [[nodiscard]] BlockToken { class [[nodiscard]] BlockToken {
@ -57,7 +58,7 @@ protected:
private: private:
DevToolsServer& m_devtools; DevToolsServer& m_devtools;
ByteString m_name; String m_name;
Vector<JsonValue> m_blocked_responses; Vector<JsonValue> m_blocked_responses;
bool m_block_responses { false }; bool m_block_responses { false };

View file

@ -36,7 +36,7 @@ void CSSPropertiesActor::handle_message(StringView type, JsonObject const&)
for (auto const& css_property : css_property_list) { for (auto const& css_property : css_property_list) {
JsonArray subproperties; JsonArray subproperties;
subproperties.must_append(css_property.name); subproperties.must_append(MUST(String::from_byte_string(css_property.name)));
JsonObject property; JsonObject property;
property.set("isInherited"sv, css_property.is_inherited); property.set("isInherited"sv, css_property.is_inherited);

View file

@ -27,16 +27,16 @@ DeviceActor::~DeviceActor() = default;
void DeviceActor::handle_message(StringView type, JsonObject const&) void DeviceActor::handle_message(StringView type, JsonObject const&)
{ {
if (type == "getDescription"sv) { 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 auto browser_name = String::from_utf8_without_validation({ BROWSER_NAME, __builtin_strlen(BROWSER_NAME) });
static constexpr auto browser_version = StringView { BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) }; static auto browser_version = String::from_utf8_without_validation({ BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) });
static constexpr auto platform_name = StringView { OS_STRING, __builtin_strlen(OS_STRING) }; static auto platform_name = String::from_utf8_without_validation({ OS_STRING, __builtin_strlen(OS_STRING) });
static constexpr auto arch = StringView { CPU_STRING, __builtin_strlen(CPU_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 // https://github.com/mozilla/gecko-dev/blob/master/devtools/shared/system.js
JsonObject value; 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("name"sv, browser_name);
value.set("brandName"sv, browser_name); value.set("brandName"sv, browser_name);
value.set("version"sv, browser_version); value.set("version"sv, browser_version);

View file

@ -50,8 +50,8 @@ void FrameActor::send_frame_update_message()
if (auto tab_actor = m_tab.strong_ref()) { if (auto tab_actor = m_tab.strong_ref()) {
JsonObject frame; JsonObject frame;
frame.set("id"sv, tab_actor->description().id); frame.set("id"sv, tab_actor->description().id);
frame.set("title"sv, tab_actor->description().title); frame.set("title"sv, MUST(String::from_byte_string(tab_actor->description().title)));
frame.set("url"sv, tab_actor->description().url); frame.set("url"sv, MUST(String::from_byte_string(tab_actor->description().url)));
frames.must_append(move(frame)); frames.must_append(move(frame));
} }
@ -76,8 +76,8 @@ JsonObject FrameActor::serialize_target() const
target.set("actor"sv, name()); target.set("actor"sv, name());
if (auto tab_actor = m_tab.strong_ref()) { if (auto tab_actor = m_tab.strong_ref()) {
target.set("title"sv, tab_actor->description().title); target.set("title"sv, MUST(String::from_byte_string(tab_actor->description().title)));
target.set("url"sv, tab_actor->description().url); target.set("url"sv, MUST(String::from_byte_string(tab_actor->description().url)));
target.set("browsingContextID"sv, tab_actor->description().id); target.set("browsingContextID"sv, tab_actor->description().id);
target.set("outerWindowID"sv, tab_actor->description().id); target.set("outerWindowID"sv, tab_actor->description().id);
target.set("isTopLevelTarget"sv, true); target.set("isTopLevelTarget"sv, true);

View file

@ -57,9 +57,9 @@ void RootActor::handle_message(StringView type, JsonObject const& message)
for (auto const& actor : devtools().actor_registry()) { for (auto const& actor : devtools().actor_registry()) {
if (is<DeviceActor>(*actor.value)) if (is<DeviceActor>(*actor.value))
response.set("deviceActor"sv, actor.key); response.set("deviceActor"sv, MUST(String::from_byte_string(actor.key)));
else if (is<PreferenceActor>(*actor.value)) else if (is<PreferenceActor>(*actor.value))
response.set("preferenceActor"sv, actor.key); response.set("preferenceActor"sv, MUST(String::from_byte_string(actor.key)));
} }
send_message(move(response)); send_message(move(response));

View file

@ -60,8 +60,8 @@ JsonObject TabActor::serialize_description() const
// provide different IDs for browserId, browsingContextID, and outerWindowID. // provide different IDs for browserId, browsingContextID, and outerWindowID.
JsonObject description; JsonObject description;
description.set("actor"sv, name()); description.set("actor"sv, name());
description.set("title"sv, m_description.title); description.set("title"sv, MUST(String::from_byte_string(m_description.title)));
description.set("url"sv, m_description.url); description.set("url"sv, MUST(String::from_byte_string(m_description.url)));
description.set("browserId"sv, m_description.id); description.set("browserId"sv, m_description.id);
description.set("browsingContextID"sv, m_description.id); description.set("browsingContextID"sv, m_description.id);
description.set("outerWindowID"sv, m_description.id); description.set("outerWindowID"sv, m_description.id);

View file

@ -135,12 +135,12 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const
if (!tab) if (!tab)
return {}; return {};
auto actor = node.get_byte_string("actor"sv); auto actor = node.get_string("actor"sv);
if (!actor.has_value()) if (!actor.has_value())
return {}; return {};
auto name = node.get_byte_string("name"sv).release_value(); auto name = node.get_string("name"sv).release_value();
auto type = node.get_byte_string("type"sv).release_value(); auto type = node.get_string("type"sv).release_value();
auto dom_type = Web::DOM::NodeType::INVALID; auto dom_type = Web::DOM::NodeType::INVALID;
JsonValue node_value; JsonValue node_value;
@ -157,12 +157,12 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const
} else if (type == "text"sv) { } else if (type == "text"sv) {
dom_type = Web::DOM::NodeType::TEXT_NODE; 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(); node_value = text.release_value();
} else if (type == "comment"sv) { } else if (type == "comment"sv) {
dom_type = Web::DOM::NodeType::COMMENT_NODE; 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(); node_value = data.release_value();
} else if (type == "shadow-root"sv) { } else if (type == "shadow-root"sv) {
is_shadow_root = true; is_shadow_root = true;
@ -180,7 +180,7 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const
return; return;
JsonObject attr; JsonObject attr;
attr.set("name"sv, name.to_byte_string()); attr.set("name"sv, name);
attr.set("value"sv, value.as_string()); attr.set("value"sv, value.as_string());
attrs.must_append(move(attr)); attrs.must_append(move(attr));
}); });
@ -189,10 +189,10 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const
JsonObject serialized; JsonObject serialized;
serialized.set("actor"sv, actor.release_value()); serialized.set("actor"sv, actor.release_value());
serialized.set("attrs"sv, move(attrs)); 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("causesOverflow"sv, false);
serialized.set("containerType"sv, JsonValue {}); 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("displayType"sv, "block"sv);
serialized.set("host"sv, JsonValue {}); serialized.set("host"sv, JsonValue {});
serialized.set("isAfterPseudoElement"sv, false); serialized.set("isAfterPseudoElement"sv, false);
@ -216,7 +216,7 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const
if (!is_top_level_document) { if (!is_top_level_document) {
if (auto parent = m_dom_node_to_parent_map.get(&node); parent.has_value() && parent.value()) { 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()) if (!actor.has_value())
return {}; 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); m_dom_node_to_parent_map.set(&node, parent);
auto actor = ByteString::formatted("{}-node{}", name(), m_dom_node_count++); auto actor = MUST(String::formatted("{}-node{}", name(), m_dom_node_count++));
m_actor_to_dom_node_map.set(actor, &node); m_actor_to_dom_node_map.set(actor.to_byte_string(), &node);
node.set("actor"sv, actor); node.set("actor"sv, actor);
auto children = node.get_array("children"sv); auto children = node.get_array("children"sv);

View file

@ -176,7 +176,7 @@ public:
for (auto& it : m_graph) { for (auto& it : m_graph) {
AK::JsonArray edges; AK::JsonArray edges;
for (auto const& value : it.value.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(); auto node = AK::JsonObject();
@ -185,7 +185,7 @@ public:
auto location = it.value.root_origin->location; auto location = it.value.root_origin->location;
switch (type) { switch (type) {
case HeapRoot::Type::Root: 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; break;
case HeapRoot::Type::RootVector: case HeapRoot::Type::RootVector:
node.set("root"sv, "RootVector"sv); node.set("root"sv, "RootVector"sv);

View file

@ -68,7 +68,7 @@ JS::ThrowCompletionOr<JsonWebKey> JsonWebKey::parse(JS::Realm& realm, ReadonlyBy
key.key_ops->ensure_capacity(key_ops->size()); key.key_ops->ensure_capacity(key_ops->size());
key_ops->for_each([&](auto const& value) { 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());
}); });
} }

View file

@ -235,9 +235,9 @@ static bool matches_platform_name(StringView requested_platform_name, StringView
// https://w3c.github.io/webdriver/#dfn-matching-capabilities // https://w3c.github.io/webdriver/#dfn-matching-capabilities
static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags flags) static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags flags)
{ {
static auto browser_name = StringView { BROWSER_NAME, strlen(BROWSER_NAME) }.to_lowercase_string(); static auto browser_name = String::from_utf8_without_validation({ BROWSER_NAME, __builtin_strlen(BROWSER_NAME) }).to_ascii_lowercase();
static constexpr auto browser_version = StringView { BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) }; static auto browser_version = String::from_utf8_without_validation({ BROWSER_VERSION, __builtin_strlen(BROWSER_VERSION) });
static auto platform_name = StringView { OS_STRING, strlen(OS_STRING) }.to_lowercase_string(); 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: // 1. Let matched capabilities be a JSON Object with the following entries:
JsonObject matched_capabilities; JsonObject matched_capabilities;
@ -283,7 +283,7 @@ static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags
// -> "browserName" // -> "browserName"
if (name == "browserName"sv) { 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 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"); return AK::Error::from_string_literal("browserName");
} }
// -> "browserVersion" // -> "browserVersion"

View file

@ -329,8 +329,8 @@ ErrorOr<void, Client::WrappedError> Client::send_error_response(HTTP::HttpReques
auto reason = HTTP::HttpResponse::reason_phrase_for_code(error.http_status); auto reason = HTTP::HttpResponse::reason_phrase_for_code(error.http_status);
JsonObject error_response; JsonObject error_response;
error_response.set("error"sv, error.error); error_response.set("error"sv, MUST(String::from_byte_string(error.error)));
error_response.set("message"sv, error.message); error_response.set("message"sv, MUST(String::from_byte_string(error.message)));
error_response.set("stacktrace"sv, ""sv); error_response.set("stacktrace"sv, ""sv);
if (error.data.has_value()) if (error.data.has_value())
error_response.set("data"sv, *error.data); error_response.set("data"sv, *error.data);

View file

@ -39,7 +39,7 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
// identifier // identifier
// Associated window handle of the windows browsing context. // Associated window handle of the windows browsing context.
object.set(identifier, navigable->traversable_navigable()->window_handle().to_byte_string()); object.set(identifier, navigable->traversable_navigable()->window_handle());
return object; return object;
} }

View file

@ -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. // 3. Return a JSON Object initialized with a property with name identifier and value reference.
JsonObject object; JsonObject object;
object.set(identifier, reference); object.set(identifier, MUST(String::from_byte_string(reference)));
return object; 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. // 3. Return a JSON Object initialized with a property with name identifier and value reference.
JsonObject object; JsonObject object;
object.set(identifier, reference); object.set(identifier, MUST(String::from_byte_string(reference)));
return object; return object;
} }

View file

@ -40,7 +40,7 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& pa
if constexpr (IsSame<PropertyType, ByteString>) { if constexpr (IsSame<PropertyType, ByteString>) {
if (!property->is_string()) if (!property->is_string())
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a String", key)); 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<PropertyType, bool>) { } else if constexpr (IsSame<PropertyType, bool>) {
if (!property->is_bool()) if (!property->is_bool())
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Boolean", key)); return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Boolean", key));

View file

@ -655,7 +655,7 @@ String InspectorClient::generate_dom_tree(JsonObject const& dom_tree)
builder.appendff("<span class=\"attribute-value\">\"{}\"</span>", escape_html_entities(value_string)); builder.appendff("<span class=\"attribute-value\">\"{}\"</span>", escape_html_entities(value_string));
builder.append("</span>"sv); builder.append("</span>"sv);
dom_node_attributes.empend(name, MUST(String::from_byte_string(value_string))); dom_node_attributes.empend(name, value_string);
}); });
} }

View file

@ -128,7 +128,7 @@ Optional<@name:titlecase@> keyword_to_@name:snakecase@(Keyword keyword)
auto member_generator = enum_generator.fork(); auto member_generator = enum_generator.fork();
auto member_name = member.as_string(); auto member_name = member.as_string();
if (member_name.contains('=')) { 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("valueid:titlecase", title_casify(parts[0]));
member_generator.set("member:titlecase", title_casify(parts[1])); member_generator.set("member:titlecase", title_casify(parts[1]));
} else { } else {

View file

@ -182,7 +182,7 @@ bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureVal
VERIFY(type.is_string()); VERIFY(type.is_string());
auto type_name = type.as_string(); auto type_name = type.as_string();
// Skip keywords. // Skip keywords.
if (type_name[0] != '<') if (!type_name.starts_with('<'))
continue; continue;
if (type_name == "<mq-boolean>") { if (type_name == "<mq-boolean>") {
append_value_type_switch_if_needed(); 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(); auto& values_array = values.value();
for (auto& keyword : values_array.values()) { for (auto& keyword : values_array.values()) {
VERIFY(keyword.is_string()); VERIFY(keyword.is_string());
auto keyword_name = keyword.as_string(); auto const& keyword_name = keyword.as_string();
// Skip types. // Skip types.
if (keyword_name[0] == '<') if (keyword_name.starts_with('<'))
continue; continue;
append_keyword_switch_if_needed(); append_keyword_switch_if_needed();

View file

@ -91,7 +91,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
void replace_logical_aliases(JsonObject& properties) void replace_logical_aliases(JsonObject& properties)
{ {
AK::HashMap<String, ByteString> logical_aliases; AK::HashMap<String, String> logical_aliases;
properties.for_each_member([&](auto& name, auto& value) { properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object()); VERIFY(value.is_object());
auto const& value_as_object = value.as_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; return;
if (auto maybe_valid_types = value.as_object().get_array("valid-types"sv); maybe_valid_types.has_value() && !maybe_valid_types->is_empty()) { 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()) { 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) if (type_and_range.first() != css_type_name)
continue; continue;
@ -333,9 +333,9 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @
if (type_and_range.size() > 1) { if (type_and_range.size() > 1) {
auto range = type_and_range[1]; auto range = type_and_range[1];
VERIFY(range.starts_with('[') && range.ends_with(']') && range.contains(',')); VERIFY(range.starts_with('[') && range.ends_with(']') && range.contains(','));
auto comma_index = range.find(',').value(); auto comma_index = range.find_byte_offset(',').value();
StringView min_value_string = range.substring_view(1, comma_index - 1); StringView min_value_string = range.bytes_as_string_view().substring_view(1, comma_index - 1);
StringView max_value_string = range.substring_view(comma_index + 1, range.length() - comma_index - 2); 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 the min/max value is infinite, we can just skip that side of the check.
if (min_value_string == "-∞") if (min_value_string == "-∞")
@ -782,7 +782,7 @@ bool property_accepts_type(PropertyID property_id, ValueType value_type)
bool did_output_accepted_type = false; bool did_output_accepted_type = false;
for (auto& type : valid_types.values()) { for (auto& type : valid_types.values()) {
VERIFY(type.is_string()); 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)) if (type_name_is_enum(type_name))
continue; 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()) { 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(); auto& valid_types = maybe_valid_types.value();
for (auto& valid_type : valid_types.values()) { 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)) if (!type_name_is_enum(type_name))
continue; continue;

View file

@ -171,7 +171,7 @@ TransformFunctionMetadata transform_function_metadata(TransformFunction transfor
JsonArray const& parameters = value.as_object().get_array("parameters"sv).value(); JsonArray const& parameters = value.as_object().get_array("parameters"sv).value();
bool first = true; bool first = true;
parameters.for_each([&](JsonValue const& value) { 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('<')); VERIFY(lexer.consume_specific('<'));
auto parameter_type_name = lexer.consume_until('>'); auto parameter_type_name = lexer.consume_until('>');
VERIFY(lexer.consume_specific('>')); VERIFY(lexer.consume_specific('>'));

View file

@ -83,10 +83,10 @@ namespace WebContent {
static JsonValue serialize_cookie(Web::Cookie::Cookie const& cookie) static JsonValue serialize_cookie(Web::Cookie::Cookie const& cookie)
{ {
JsonObject serialized_cookie; JsonObject serialized_cookie;
serialized_cookie.set("name"sv, cookie.name.to_byte_string()); serialized_cookie.set("name"sv, cookie.name);
serialized_cookie.set("value"sv, cookie.value.to_byte_string()); serialized_cookie.set("value"sv, cookie.value);
serialized_cookie.set("path"sv, cookie.path.to_byte_string()); serialized_cookie.set("path"sv, cookie.path);
serialized_cookie.set("domain"sv, cookie.domain.to_byte_string()); serialized_cookie.set("domain"sv, cookie.domain);
serialized_cookie.set("secure"sv, cookie.secure); serialized_cookie.set("secure"sv, cookie.secure);
serialized_cookie.set("httpOnly"sv, cookie.http_only); serialized_cookie.set("httpOnly"sv, cookie.http_only);
serialized_cookie.set("expiry"sv, cookie.expiry_time.seconds_since_epoch()); 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(); auto url = current_top_level_browsing_context()->active_document()->url();
// 4. Return success with data url. // 4. Return success with data url.
async_driver_execution_complete({ url.to_byte_string() }); async_driver_execution_complete({ url.to_string() });
}); });
return JsonValue {}; return JsonValue {};
@ -529,7 +529,7 @@ Messages::WebDriverClient::GetTitleResponse WebDriverConnection::get_title()
auto title = current_top_level_browsing_context()->active_document()->title(); auto title = current_top_level_browsing_context()->active_document()->title();
// 4. Return success with data title. // 4. Return success with data title.
async_driver_execution_complete({ title.to_byte_string() }); async_driver_execution_complete({ move(title) });
}); });
return JsonValue {}; return JsonValue {};
@ -1323,7 +1323,7 @@ Messages::WebDriverClient::GetElementAttributeResponse WebDriverConnection::get_
} }
// 5. Return success with data result. // 5. Return success with data result.
async_driver_execution_complete({ result.to_byte_string() }); async_driver_execution_complete({ move(result) });
}); });
return JsonValue {}; return JsonValue {};
@ -1389,7 +1389,7 @@ Messages::WebDriverClient::GetElementCssValueResponse WebDriverConnection::get_e
// "" (empty string) // "" (empty string)
// 5. Return success with data computed value. // 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 {}; return JsonValue {};
@ -1411,7 +1411,7 @@ Messages::WebDriverClient::GetElementTextResponse WebDriverConnection::get_eleme
auto rendered_text = Web::WebDriver::element_rendered_text(element); auto rendered_text = Web::WebDriver::element_rendered_text(element);
// 5. Return success with data rendered text. // 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 {}; return JsonValue {};
@ -1434,7 +1434,7 @@ Messages::WebDriverClient::GetElementTagNameResponse WebDriverConnection::get_el
auto qualified_name = element->local_name(); auto qualified_name = element->local_name();
// 5. Return success with data qualified 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 {}; 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(); auto label = element->accessible_name(element->document()).release_value_but_fixme_should_propagate_errors();
// 5. Return success with data label. // 5. Return success with data label.
async_driver_execution_complete({ label.to_byte_string() }); async_driver_execution_complete({ move(label) });
}); });
return JsonValue {}; return JsonValue {};
@ -2047,7 +2047,7 @@ Messages::WebDriverClient::GetSourceResponse WebDriverConnection::get_source()
source = MUST(document->serialize_fragment(Web::DOMParsing::RequireWellFormed::No)); source = MUST(document->serialize_fragment(Web::DOMParsing::RequireWellFormed::No));
// 5. Return success with data source. // 5. Return success with data source.
async_driver_execution_complete({ source->to_byte_string() }); async_driver_execution_complete({ source.release_value() });
}); });
return JsonValue {}; return JsonValue {};
@ -2465,7 +2465,7 @@ Messages::WebDriverClient::GetAlertTextResponse WebDriverConnection::get_alert_t
// 4. Return success with data message. // 4. Return success with data message.
if (message.has_value()) if (message.has_value())
return message->to_byte_string(); return message.value();
return JsonValue {}; return JsonValue {};
} }
@ -2679,7 +2679,7 @@ static Web::WebDriver::Error create_annotated_unexpected_alert_open_error(Option
// The current user prompt's message. // The current user prompt's message.
auto data = text.map([&](auto const& text) -> JsonValue { auto data = text.map([&](auto const& text) -> JsonValue {
JsonObject data; JsonObject data;
data.set("text"sv, text.to_byte_string()); data.set("text"sv, text);
return data; return data;
}); });

View file

@ -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. // An implementation-defined string explaining the remote end's readiness state.
JsonObject body; JsonObject body;
body.set("ready"sv, readiness_state); 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. // 2. Return success with data body.
return JsonValue { body }; return JsonValue { body };

View file

@ -221,7 +221,7 @@ ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<S
return; return;
} }
auto window_handle = MUST(String::from_byte_string(maybe_window_handle.value().as_string())); auto const& window_handle = maybe_window_handle.value().as_string();
web_content_connection->on_close = [this, window_handle]() { web_content_connection->on_close = [this, window_handle]() {
dbgln_if(WEBDRIVER_DEBUG, "Window {} was closed remotely.", window_handle); dbgln_if(WEBDRIVER_DEBUG, "Window {} was closed remotely.", window_handle);

View file

@ -66,7 +66,7 @@ TEST_CASE(json_string)
{ {
auto json = JsonValue::from_string("\"A\""sv).value(); auto json = JsonValue::from_string("\"A\""sv).value();
EXPECT_EQ(json.type(), JsonValue::Type::String); 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); EXPECT_EQ(json.as_string() == "A", true);
} }
@ -74,7 +74,7 @@ TEST_CASE(json_utf8_character)
{ {
auto json = JsonValue::from_string("\"\\u0041\""sv).value(); auto json = JsonValue::from_string("\"\\u0041\""sv).value();
EXPECT_EQ(json.type(), JsonValue::Type::String); 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); 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(); auto json = JsonValue::from_string("\"\\uD83E\\uDD13\""sv).value();
EXPECT_EQ(json.type(), JsonValue::Type::String); 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); EXPECT_EQ(json.as_string(), "🤓"sv);
} }
{ {
auto json = JsonValue::from_string("\"\\uD83E\""sv).value(); auto json = JsonValue::from_string("\"\\uD83E\""sv).value();
EXPECT_EQ(json.type(), JsonValue::Type::String); 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); EXPECT_EQ(json.as_string(), "\xED\xA0\xBE"sv);
} }
{ {
auto json = JsonValue::from_string("\"\\uDD13\""sv).value(); auto json = JsonValue::from_string("\"\\uDD13\""sv).value();
EXPECT_EQ(json.type(), JsonValue::Type::String); 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); EXPECT_EQ(json.as_string(), "\xED\xB4\x93"sv);
} }
} }
@ -110,7 +110,7 @@ TEST_CASE(json_utf8_multibyte)
auto& json = json_or_error.value(); auto& json = json_or_error.value();
EXPECT_EQ(json.type(), JsonValue::Type::String); 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() == "š", true);
EXPECT_EQ(json.as_string() == "\xc5\xa1", true); EXPECT_EQ(json.as_string() == "\xc5\xa1", true);
} }

View file

@ -317,8 +317,8 @@ void write_per_file(HashMap<size_t, TestResult> const& result_map, Vector<ByteSt
result_object.set(paths[test], name_for_result(value)); result_object.set(paths[test], name_for_result(value));
JsonObject complete_results {}; JsonObject complete_results {};
complete_results.set("duration", time_taken_in_ms / 1000.); complete_results.set("duration"sv, time_taken_in_ms / 1000.);
complete_results.set("results", result_object); complete_results.set("results"sv, result_object);
if (file->write_until_depleted(complete_results.to_byte_string()).is_error()) if (file->write_until_depleted(complete_results.to_byte_string()).is_error())
warnln("Failed to write per-file"); warnln("Failed to write per-file");

View file

@ -46,8 +46,8 @@ enum class NegativePhase {
struct TestError { struct TestError {
NegativePhase phase { NegativePhase::ParseOrEarly }; NegativePhase phase { NegativePhase::ParseOrEarly };
ByteString type; String type;
ByteString details; String details;
ByteString harness_file; ByteString harness_file;
}; };
@ -60,8 +60,8 @@ static ErrorOr<ScriptOrModuleProgram, TestError> parse_program(JS::Realm& realm,
if (script_or_error.is_error()) { if (script_or_error.is_error()) {
return TestError { return TestError {
NegativePhase::ParseOrEarly, NegativePhase::ParseOrEarly,
"SyntaxError", "SyntaxError"_string,
script_or_error.error()[0].to_byte_string(), script_or_error.error()[0].to_string(),
"" ""
}; };
} }
@ -92,22 +92,22 @@ static ErrorOr<void, TestError> run_program(InterpreterT& interpreter, ScriptOrM
auto name = object.get_without_side_effects("name"); auto name = object.get_without_side_effects("name");
if (!name.is_empty() && !name.is_accessor()) { 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 { } else {
auto constructor = object.get_without_side_effects("constructor"); auto constructor = object.get_without_side_effects("constructor");
if (constructor.is_object()) { if (constructor.is_object()) {
name = constructor.as_object().get_without_side_effects("name"); name = constructor.as_object().get_without_side_effects("name");
if (!name.is_undefined()) 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"); auto message = object.get_without_side_effects("message");
if (!message.is_empty() && !message.is_accessor()) 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()) 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 error;
} }
return {}; return {};
@ -136,8 +136,8 @@ static ErrorOr<StringView, TestError> read_harness_file(StringView harness_file)
if (cache.is_error()) { if (cache.is_error()) {
return TestError { return TestError {
NegativePhase::Harness, NegativePhase::Harness,
"filesystem", "filesystem"_string,
ByteString::formatted("Could not read file: {}", harness_file), MUST(String::formatted("Could not read file: {}", harness_file)),
harness_file harness_file
}; };
} }
@ -202,8 +202,8 @@ static ErrorOr<void, TestError> run_test(StringView source, StringView filepath,
if (parser.has_errors()) { if (parser.has_errors()) {
return TestError { return TestError {
NegativePhase::ParseOrEarly, NegativePhase::ParseOrEarly,
"SyntaxError", "SyntaxError"_string,
parser.errors()[0].to_byte_string(), parser.errors()[0].to_string(),
"" ""
}; };
} }
@ -250,14 +250,14 @@ static ErrorOr<void, TestError> run_test(StringView source, StringView filepath,
return run_program(vm->bytecode_interpreter(), program); return run_program(vm->bytecode_interpreter(), program);
} }
static ErrorOr<TestMetadata, ByteString> extract_metadata(StringView source) static ErrorOr<TestMetadata, String> extract_metadata(StringView source)
{ {
auto lines = source.lines(); auto lines = source.lines();
TestMetadata metadata; TestMetadata metadata;
bool parsing_negative = false; bool parsing_negative = false;
ByteString failed_message; String failed_message;
auto parse_list = [&](StringView line) { auto parse_list = [&](StringView line) {
auto start = line.find('['); auto start = line.find('[');
@ -268,7 +268,7 @@ static ErrorOr<TestMetadata, ByteString> extract_metadata(StringView source)
auto end = line.find_last(']'); auto end = line.find_last(']');
if (!end.has_value() || end.value() <= start.value()) { 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; return items;
} }
@ -281,7 +281,7 @@ static ErrorOr<TestMetadata, ByteString> extract_metadata(StringView source)
auto second_word = [&](StringView line) { auto second_word = [&](StringView line) {
auto separator = line.find(' '); auto separator = line.find(' ');
if (!separator.has_value() || separator.value() >= (line.length() - 1u)) { 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 ""sv;
} }
return line.substring_view(separator.value() + 1); return line.substring_view(separator.value() + 1);
@ -311,7 +311,7 @@ static ErrorOr<TestMetadata, ByteString> extract_metadata(StringView source)
continue; continue;
} else { } else {
if (include_list.is_empty()) { 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; break;
} }
@ -335,18 +335,18 @@ static ErrorOr<TestMetadata, ByteString> extract_metadata(StringView source)
metadata.phase = NegativePhase::Runtime; metadata.phase = NegativePhase::Runtime;
} else { } else {
has_phase = false; has_phase = false;
failed_message = ByteString::formatted("Unknown negative phase: {}", phase); failed_message = MUST(String::formatted("Unknown negative phase: {}", phase));
break; break;
} }
} else if (line.starts_with("type:"sv)) { } else if (line.starts_with("type:"sv)) {
metadata.type = second_word(line); metadata.type = second_word(line);
} else { } else {
if (!has_phase) { if (!has_phase) {
failed_message = "Failed to find phase in negative attributes"; failed_message = "Failed to find phase in negative attributes"_string;
break; break;
} }
if (metadata.type.is_empty()) { 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; break;
} }
@ -392,7 +392,7 @@ static ErrorOr<TestMetadata, ByteString> extract_metadata(StringView source)
} }
if (failed_message.is_empty()) 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; return failed_message;
} }
@ -402,13 +402,13 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
if (result.is_error()) { if (result.is_error()) {
if (result.error().phase == NegativePhase::Harness) { if (result.error().phase == NegativePhase::Harness) {
output.set("harness_error"sv, true); 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); output.set("result"sv, "harness_error"sv);
} else if (result.error().phase == NegativePhase::Runtime) { } else if (result.error().phase == NegativePhase::Runtime) {
auto& error_type = result.error().type; auto& error_type = result.error().type;
auto& error_details = result.error().details; auto& error_details = result.error().details;
if ((error_type == "InternalError"sv && error_details.starts_with("TODO("sv)) if ((error_type == "InternalError"sv && error_details.starts_with_bytes("TODO("sv))
|| (error_type == "Test262Error"sv && error_details.ends_with(" but got a InternalError"sv))) { || (error_type == "Test262Error"sv && error_details.ends_with_bytes(" but got a InternalError"sv))) {
output.set("todo_error"sv, true); output.set("todo_error"sv, true);
output.set("result"sv, "todo_error"sv); output.set("result"sv, "todo_error"sv);
} }
@ -467,7 +467,7 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
JsonObject expected_error_object; JsonObject expected_error_object;
expected_error_object.set("phase"sv, phase_to_string(metadata.phase)); 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; 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. // immediately stop if we are already in a failed assert.
g_in_assert = true; g_in_assert = true;
JsonObject assert_fail_result; 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("assert_fail"sv, true);
assert_fail_result.set("result"sv, "assert_fail"sv); assert_fail_result.set("result"sv, "assert_fail"sv);
assert_fail_result.set("output"sv, StringView { assert_failed_message, strlen(assert_failed_message) }); 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()) { if (metadata_or_error.is_error()) {
result_object.set("result"sv, "metadata_error"sv); result_object.set("result"sv, "metadata_error"sv);
result_object.set("metadata_error"sv, true); 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; continue;
} }
@ -762,7 +762,7 @@ int main(int argc, char** argv)
auto first_output = collect_output(); auto first_output = collect_output();
if (first_output.has_value()) 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); passed = verify_test(result, metadata, result_object);
auto output = first_output.value_or(""); auto output = first_output.value_or("");
@ -786,7 +786,7 @@ int main(int argc, char** argv)
auto first_output = collect_output(); auto first_output = collect_output();
if (first_output.has_value()) 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); passed = verify_test(result, metadata, result_object);
auto output = first_output.value_or(""); auto output = first_output.value_or("");

View file

@ -45,7 +45,7 @@ ErrorOr<Vector<String>> AutoComplete::parse_google_autocomplete(Vector<JsonValue
if (!json[0].is_string()) if (!json[0].is_string())
return Error::from_string_literal("Invalid JSON, expected first element to be a string"); return Error::from_string_literal("Invalid JSON, expected first element to be a string");
auto query = TRY(String::from_byte_string(json[0].as_string())); auto query = json[0].as_string();
if (!json[1].is_array()) if (!json[1].is_array())
return Error::from_string_literal("Invalid JSON, expected second element to be an array"); return Error::from_string_literal("Invalid JSON, expected second element to be an array");
@ -57,7 +57,7 @@ ErrorOr<Vector<String>> AutoComplete::parse_google_autocomplete(Vector<JsonValue
Vector<String> results; Vector<String> results;
results.ensure_capacity(suggestions_array.size()); results.ensure_capacity(suggestions_array.size());
for (auto& suggestion : suggestions_array) for (auto& suggestion : suggestions_array)
results.unchecked_append(MUST(String::from_byte_string(suggestion.as_string()))); results.unchecked_append(suggestion.as_string());
return results; return results;
} }
@ -65,11 +65,13 @@ ErrorOr<Vector<String>> AutoComplete::parse_google_autocomplete(Vector<JsonValue
ErrorOr<Vector<String>> AutoComplete::parse_duckduckgo_autocomplete(Vector<JsonValue> const& json) ErrorOr<Vector<String>> AutoComplete::parse_duckduckgo_autocomplete(Vector<JsonValue> const& json)
{ {
Vector<String> results; Vector<String> results;
for (auto const& suggestion : json) { for (auto const& suggestion : json) {
auto maybe_value = suggestion.as_object().get("phrase"sv); if (!suggestion.is_object())
if (!maybe_value.has_value()) return Error::from_string_literal("Invalid JSON, expected value to be an object");
continue;
results.append(MUST(String::from_byte_string(maybe_value->as_string()))); if (auto value = suggestion.as_object().get_string("phrase"sv); !value.has_value())
results.append(*value);
} }
return results; return results;
@ -77,28 +79,28 @@ ErrorOr<Vector<String>> AutoComplete::parse_duckduckgo_autocomplete(Vector<JsonV
ErrorOr<Vector<String>> AutoComplete::parse_yahoo_autocomplete(JsonObject const& json) ErrorOr<Vector<String>> 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); 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) if (query != m_query)
return Error::from_string_literal("Invalid JSON, query does not match"); return Error::from_string_literal("Invalid JSON, query does not match");
Vector<String> results; auto suggestions = json.get_array("r"sv);
results.ensure_capacity(suggestions_object.size()); if (!suggestions.has_value())
for (auto& suggestion_object : suggestions_object) { return Error::from_string_view("Invalid JSON, expected \"r\" to be an object"sv);
if (!suggestion_object.is_object())
return Error::from_string_literal("Invalid JSON, expected value to be an object");
auto suggestion = suggestion_object.as_object();
if (!suggestion.get("k"sv).has_value() || !suggestion.get("k"sv)->is_string()) Vector<String> 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); 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; return results;