AK+Everywhere: Store JSON object keys as String

This commit is contained in:
Timothy Flynn 2025-02-17 12:18:27 -05:00 committed by Tim Flynn
parent 70eb0ba1cd
commit e591636419
Notes: github-actions[bot] 2025-02-21 00:29:28 +00:00
23 changed files with 119 additions and 111 deletions

View file

@ -261,9 +261,14 @@ bool JsonObject::has_object(StringView key) const
return value.has_value() && value->is_object();
}
void JsonObject::set(ByteString const& key, JsonValue value)
void JsonObject::set(String key, JsonValue value)
{
m_members.set(key, move(value));
m_members.set(move(key), move(value));
}
void JsonObject::set(StringView key, JsonValue value)
{
set(MUST(String::from_utf8(key)), move(value));
}
bool JsonObject::remove(StringView key)

View file

@ -15,12 +15,13 @@
#include <AK/JsonArray.h>
#include <AK/JsonObjectSerializer.h>
#include <AK/JsonValue.h>
#include <AK/String.h>
namespace AK {
class JsonObject {
template<typename Callback>
using CallbackErrorType = decltype(declval<Callback>()(declval<ByteString const&>(), declval<JsonValue const&>()).release_error());
using CallbackErrorType = decltype(declval<Callback>()(declval<String const&>(), declval<JsonValue const&>()).release_error());
public:
JsonObject();
@ -86,7 +87,8 @@ public:
Optional<double> get_double_with_precision_loss(StringView key) const;
Optional<float> get_float_with_precision_loss(StringView key) const;
void set(ByteString const& key, JsonValue value);
void set(String key, JsonValue value);
void set(StringView key, JsonValue value);
template<typename Callback>
void for_each_member(Callback callback) const
@ -95,7 +97,7 @@ public:
callback(member.key, member.value);
}
template<FallibleFunction<ByteString const&, JsonValue const&> Callback>
template<FallibleFunction<String const&, JsonValue const&> Callback>
ErrorOr<void, CallbackErrorType<Callback>> try_for_each_member(Callback&& callback) const
{
for (auto const& member : m_members)
@ -114,7 +116,7 @@ public:
[[nodiscard]] ByteString to_byte_string() const;
private:
OrderedHashMap<ByteString, JsonValue> m_members;
OrderedHashMap<String, JsonValue> m_members;
};
template<typename Builder>

View file

@ -749,11 +749,11 @@ 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", ByteString::formatted(StringView { format, strlen(format) }, args...));
object.set("static_offset", 0);
object.set("invariant_offset", has_invariant ? option_to_complete.length() : 0u);
object.set("display_trivia", StringView { option.help_string, strlen(option.help_string) });
object.set("trailing_trivia", option.argument_mode == OptionArgumentMode::Required ? " "sv : ""sv);
object.set("completion"sv, ByteString::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) });
object.set("trailing_trivia"sv, option.argument_mode == OptionArgumentMode::Required ? " "sv : ""sv);
outln(file, "{}", object.to_byte_string());
};

View file

@ -56,9 +56,9 @@ void FrameActor::send_frame_update_message()
}
JsonObject message;
message.set("from", name());
message.set("type", "frameUpdate"sv);
message.set("frames", move(frames));
message.set("from"sv, name());
message.set("type"sv, "frameUpdate"sv);
message.set("frames"sv, move(frames));
send_message(move(message));
}

View file

@ -93,7 +93,7 @@ void WalkerActor::handle_message(StringView type, JsonObject const& message)
send_message(move(response));
JsonObject message;
message.set("from", name());
message.set("from"sv, name());
send_message(move(message));
return;
@ -175,12 +175,12 @@ JsonValue WalkerActor::serialize_node(JsonObject const& node) const
JsonArray attrs;
if (auto attributes = node.get_object("attributes"sv); attributes.has_value()) {
attributes->for_each_member([&](ByteString const& name, JsonValue const& value) {
attributes->for_each_member([&](String const& name, JsonValue const& value) {
if (!value.is_string())
return;
JsonObject attr;
attr.set("name"sv, name);
attr.set("name"sv, name.to_byte_string());
attr.set("value"sv, value.as_string());
attrs.must_append(move(attr));
});

View file

@ -88,7 +88,7 @@ void WatcherActor::handle_message(StringView type, JsonObject const& message)
target.send_frame_update_message();
JsonObject message;
message.set("from", name());
message.set("from"sv, name());
send_message(move(message));
return;

View file

@ -448,7 +448,7 @@ Object* JSONObject::parse_json_object(VM& vm, JsonObject const& json_object)
auto& realm = *vm.current_realm();
auto object = Object::create(realm, realm.intrinsics().object_prototype());
json_object.for_each_member([&](auto& key, auto& value) {
object->define_direct_property(key, parse_json_value(vm, value), default_attributes);
object->define_direct_property(key.to_byte_string(), parse_json_value(vm, value), default_attributes);
});
return object;
}

View file

@ -370,12 +370,12 @@ inline JSFileResult TestRunner::run_file_test(ByteString const& test_path)
file_result.logged_messages.append(message.to_string_without_side_effects().to_byte_string());
}
test_json.value().as_object().for_each_member([&](ByteString const& suite_name, JsonValue const& suite_value) {
test_json.value().as_object().for_each_member([&](String const& suite_name, JsonValue const& suite_value) {
Test::Suite suite { test_path, suite_name };
VERIFY(suite_value.is_object());
suite_value.as_object().for_each_member([&](ByteString const& test_name, JsonValue const& test_value) {
suite_value.as_object().for_each_member([&](String const& test_name, JsonValue const& test_value) {
Test::Case test { test_name, Test::Result::Fail, "", 0 };
VERIFY(test_value.is_object());
@ -427,10 +427,10 @@ inline JSFileResult TestRunner::run_file_test(ByteString const& test_path)
});
if (top_level_result.is_error()) {
Test::Suite suite { test_path, "<top-level>" };
Test::Suite suite { test_path, "<top-level>"_string };
suite.most_severe_test_result = Result::Crashed;
Test::Case test_case { "<top-level>", Test::Result::Fail, "", 0 };
Test::Case test_case { "<top-level>"_string, Test::Result::Fail, "", 0 };
auto error = top_level_result.release_error().release_value().release_value();
if (error.is_object()) {
StringBuilder detail_builder;

View file

@ -10,6 +10,7 @@
#pragma once
#include <AK/ByteString.h>
#include <AK/String.h>
#include <AK/Vector.h>
namespace Test {
@ -23,7 +24,7 @@ enum class Result {
};
struct Case {
ByteString name;
String name;
Result result;
ByteString details;
u64 duration_us;
@ -31,7 +32,7 @@ struct Case {
struct Suite {
ByteString path;
ByteString name;
String name;
// A failed test takes precedence over a skipped test, which both have
// precedence over a passed test
Result most_severe_test_result { Result::Pass };

View file

@ -243,36 +243,36 @@ inline void TestRunner::print_test_results_as_json() const
auto name = suite.name;
if (name == "__$$TOP_LEVEL$$__"sv)
name = ByteString::empty();
name = String {};
auto path = *LexicalPath::relative_path(suite.path, m_test_root);
tests.set(ByteString::formatted("{}/{}::{}", path, name, case_.name), result_name);
tests.set(MUST(String::formatted("{}/{}::{}", path, name, case_.name)), result_name);
}
}
root.set("duration", static_cast<double>(duration_us) / 1000000.);
root.set("results", move(tests));
root.set("duration"sv, static_cast<double>(duration_us) / 1000000.);
root.set("results"sv, move(tests));
} else {
JsonObject suites;
suites.set("failed", m_counts.suites_failed);
suites.set("passed", m_counts.suites_passed);
suites.set("total", m_counts.suites_failed + m_counts.suites_passed);
suites.set("failed"sv, m_counts.suites_failed);
suites.set("passed"sv, m_counts.suites_passed);
suites.set("total"sv, m_counts.suites_failed + m_counts.suites_passed);
JsonObject tests;
tests.set("failed", m_counts.tests_failed);
tests.set("passed", m_counts.tests_passed);
tests.set("skipped", m_counts.tests_skipped);
tests.set("xfail", m_counts.tests_expected_failed);
tests.set("total", m_counts.tests_failed + m_counts.tests_passed + m_counts.tests_skipped + m_counts.tests_expected_failed);
tests.set("failed"sv, m_counts.tests_failed);
tests.set("passed"sv, m_counts.tests_passed);
tests.set("skipped"sv, m_counts.tests_skipped);
tests.set("xfail"sv, m_counts.tests_expected_failed);
tests.set("total"sv, m_counts.tests_failed + m_counts.tests_passed + m_counts.tests_skipped + m_counts.tests_expected_failed);
JsonObject results;
results.set("suites", suites);
results.set("tests", tests);
results.set("suites"sv, suites);
results.set("tests"sv, tests);
root.set("results", results);
root.set("files_total", m_counts.files_total);
root.set("duration", m_total_elapsed_time_in_ms / 1000.0);
root.set("results"sv, results);
root.set("files_total"sv, m_counts.files_total);
root.set("duration"sv, m_total_elapsed_time_in_ms / 1000.0);
}
outln("{}", root.to_byte_string());
}

View file

@ -145,7 +145,7 @@ static ErrorOr<JsonObject, Error> validate_capabilities(JsonValue const& capabil
else if (name.contains(':')) {
// If name is known to the implementation, let deserialized be the result of trying to deserialize value in
// an implementation-specific way. Otherwise, let deserialized be set to value.
if (name.starts_with("ladybird:"sv))
if (name.starts_with_bytes("ladybird:"sv))
deserialized = TRY(deserialize_as_ladybird_capability(name, value));
}

View file

@ -173,7 +173,7 @@ static ErrorOr<MatchedRoute, Error> match_route(HTTP::HttpRequest const& request
static JsonValue make_success_response(JsonValue value)
{
JsonObject result;
result.set("value", move(value));
result.set("value"sv, move(value));
return result;
}
@ -329,14 +329,14 @@ ErrorOr<void, Client::WrappedError> Client::send_error_response(HTTP::HttpReques
auto reason = HTTP::HttpResponse::reason_phrase_for_code(error.http_status);
JsonObject error_response;
error_response.set("error", error.error);
error_response.set("message", error.message);
error_response.set("stacktrace", ""sv);
error_response.set("error"sv, error.error);
error_response.set("message"sv, error.message);
error_response.set("stacktrace"sv, ""sv);
if (error.data.has_value())
error_response.set("data", *error.data);
error_response.set("data"sv, *error.data);
JsonObject result;
result.set("value", move(error_response));
result.set("value"sv, move(error_response));
auto content = result.serialized<StringBuilder>();

View file

@ -116,7 +116,7 @@ ErrorOr<JsonObject, Error> deserialize_as_a_proxy(JsonValue const& parameter)
JsonObject proxy;
// 3. For each enumerable own property in parameter run the following substeps:
TRY(parameter.as_object().try_for_each_member([&](ByteString const& key, JsonValue const& value) -> ErrorOr<void, Error> {
TRY(parameter.as_object().try_for_each_member([&](String const& key, JsonValue const& value) -> ErrorOr<void, Error> {
// 1. Let key be the name of the property.
// 2. Let value be the result of getting a property named name from capability.

View file

@ -135,7 +135,7 @@ Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value)
JsonObject user_prompt_handler;
// 6. For each prompt type → handler in value:
TRY(value.as_object().try_for_each_member([&](ByteString const& prompt_type, JsonValue const& handler_value) -> ErrorOr<void, WebDriver::Error> {
TRY(value.as_object().try_for_each_member([&](String const& prompt_type, JsonValue const& handler_value) -> ErrorOr<void, WebDriver::Error> {
// 1. If is string value is false and valid prompt types does not contain prompt type return error with error code invalid argument.
if (!is_string_value && !valid_prompt_types.contains_slow(prompt_type))
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("'{}' is not a valid prompt type", prompt_type));
@ -192,7 +192,7 @@ bool check_user_prompt_handler_matches(JsonObject const& requested_prompt_handle
return true;
// 2. For each request prompt type → request handler in requested prompt handler:
auto result = requested_prompt_handler.try_for_each_member([&](ByteString const& request_prompt_type, JsonValue const& request_handler) -> ErrorOr<void> {
auto result = requested_prompt_handler.try_for_each_member([&](String const& request_prompt_type, JsonValue const& request_handler) -> ErrorOr<void> {
// 1. If the user prompt handler contains request prompt type:
if (auto handler = s_user_prompt_handler->get(prompt_type_from_string(request_prompt_type)); handler.has_value()) {
// 1. If the requested prompt handler's handler is not equal to the user prompt handler's handler, return false.
@ -215,7 +215,7 @@ void update_the_user_prompt_handler(JsonObject const& requested_prompt_handler)
s_user_prompt_handler = UserPromptHandler::ValueType {};
// 2. For each request prompt type → request handler in requested prompt handler:
requested_prompt_handler.for_each_member([&](ByteString const& request_prompt_type, JsonValue const& request_handler) {
requested_prompt_handler.for_each_member([&](String const& request_prompt_type, JsonValue const& request_handler) {
// 1. Set user prompt handler[request prompt type] to request handler.
s_user_prompt_handler->set(
prompt_type_from_string(request_prompt_type),

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.append("</span>"sv);
dom_node_attributes.empend(MUST(String::from_byte_string(name)), MUST(String::from_byte_string(value_string)));
dom_node_attributes.empend(name, MUST(String::from_byte_string(value_string)));
});
}

View file

@ -69,7 +69,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto properties = json.as_object();
// Check we're in alphabetical order
ByteString most_recent_name = "";
String most_recent_name;
properties.for_each_member([&](auto& name, auto&) {
if (name < most_recent_name) {
warnln("`{}` is in the wrong position in `{}`. Please keep this list alphabetical!", name, properties_json_path);
@ -91,7 +91,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
void replace_logical_aliases(JsonObject& properties)
{
AK::HashMap<ByteString, ByteString> logical_aliases;
AK::HashMap<String, ByteString> logical_aliases;
properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object());
auto const& value_as_object = value.as_object();
@ -142,10 +142,10 @@ enum class PropertyID {
All,
)~~~");
Vector<ByteString> inherited_shorthand_property_ids;
Vector<ByteString> inherited_longhand_property_ids;
Vector<ByteString> noninherited_shorthand_property_ids;
Vector<ByteString> noninherited_longhand_property_ids;
Vector<String> inherited_shorthand_property_ids;
Vector<String> inherited_longhand_property_ids;
Vector<String> noninherited_shorthand_property_ids;
Vector<String> noninherited_longhand_property_ids;
properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object());
@ -573,7 +573,7 @@ bool is_animatable_property(PropertyID property_id)
properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object());
VERIFY(!name.is_empty() && !is_ascii_digit(name[0])); // Ensure `PropertyKey`s are not Numbers.
VERIFY(!name.is_empty() && !is_ascii_digit(name.bytes_as_string_view()[0])); // Ensure `PropertyKey`s are not Numbers.
if (is_legacy_alias(value.as_object()))
return;

View file

@ -43,7 +43,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return 0;
}
static String get_snake_case_function_name_for_css_property_name(ByteString const& name)
static String get_snake_case_function_name_for_css_property_name(StringView name)
{
auto snake_case_name = snake_casify(name);
if (snake_case_name.starts_with('_'))
@ -182,7 +182,7 @@ interface mixin GeneratedCSSStyleProperties {
// For each CSS property property that is a supported CSS property and that begins with the string -webkit-,
// the following partial interface applies where webkit-cased attribute is obtained by running the CSS property
// to IDL attribute algorithm for property, with the lowercase first flag set.
if (name.starts_with("-webkit-"sv)) {
if (name.starts_with_bytes("-webkit-"sv)) {
member_generator.set("name:webkit", css_property_to_idl_attribute(name, /* lowercase_first= */ true));
member_generator.append(R"~~~(
[CEReactions, LegacyNullToEmptyString, AttributeCallbackName=@name:snakecase@_webkit, ImplementedAs=@name:acceptable_cpp@] attribute CSSOMString @name:webkit@;

View file

@ -98,10 +98,10 @@ static JsonValue serialize_cookie(Web::Cookie::Cookie const& cookie)
static JsonValue serialize_rect(Gfx::IntRect const& rect)
{
JsonObject serialized_rect = {};
serialized_rect.set("x", rect.x());
serialized_rect.set("y", rect.y());
serialized_rect.set("width", rect.width());
serialized_rect.set("height", rect.height());
serialized_rect.set("x"sv, rect.x());
serialized_rect.set("y"sv, rect.y());
serialized_rect.set("width"sv, rect.width());
serialized_rect.set("height"sv, rect.height());
return serialized_rect;
}

View file

@ -76,10 +76,10 @@ Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonVal
JsonObject body;
// "sessionId"
// session's session ID.
body.set("sessionId", JsonValue { session->session_id() });
body.set("sessionId"sv, JsonValue { session->session_id() });
// "capabilities"
// capabilities
body.set("capabilities", move(capabilities));
body.set("capabilities"sv, move(capabilities));
// 8. Set session' current top-level browsing context to one of the endpoint node's top-level browsing contexts,
// preferring the top-level browsing context that has system focus, or otherwise preferring any top-level
@ -130,8 +130,8 @@ Web::WebDriver::Response Client::get_status(Web::WebDriver::Parameters, JsonValu
// "message"
// An implementation-defined string explaining the remote end's readiness state.
JsonObject body;
body.set("ready", readiness_state);
body.set("message", ByteString::formatted("{} to accept a new session", readiness_state ? "Ready"sv : "Not ready"sv));
body.set("ready"sv, readiness_state);
body.set("message"sv, ByteString::formatted("{} to accept a new session", readiness_state ? "Ready"sv : "Not ready"sv));
// 2. Return success with data body.
return JsonValue { body };

View file

@ -47,7 +47,7 @@ ErrorOr<NonnullRefPtr<Session>> Session::create(NonnullRefPtr<Client> client, Js
// -> Otherwise
else {
// Set a property of capabilities with name "proxy" and a value that is a new JSON Object.
capabilities.set("proxy", JsonObject {});
capabilities.set("proxy"sv, JsonObject {});
}
// FIXME: 4. If capabilites has a property named "acceptInsecureCerts", set the endpoint node's accept insecure TLS flag

View file

@ -158,9 +158,9 @@ TEST_CASE(json_64_bit_value_coerced_to_32_bit)
TEST_CASE(json_duplicate_keys)
{
JsonObject json;
json.set("test", "foo"sv);
json.set("test", "bar"sv);
json.set("test", "baz"sv);
json.set("test"sv, "foo"sv);
json.set("test"sv, "bar"sv);
json.set("test"sv, "baz"sv);
EXPECT_EQ(json.to_byte_string(), "{\"test\":\"baz\"}");
}

View file

@ -166,19 +166,19 @@ TESTJS_RUN_FILE_FUNCTION(ByteString const& test_file, JS::Realm& realm, JS::Exec
bool test_passed = true;
ByteString message;
ByteString expectation_string;
String expectation_string;
switch (expectation) {
case Early:
case Fail:
expectation_string = "File should not parse";
expectation_string = "File should not parse"_string;
test_passed = !parse_succeeded;
if (!test_passed)
message = "Expected the file to fail parsing, but it did not";
break;
case Pass:
case ExplicitPass:
expectation_string = "File should parse";
expectation_string = "File should parse"_string;
test_passed = parse_succeeded;
if (!test_passed)
message = "Expected the file to parse, but it did not";
@ -193,6 +193,6 @@ TESTJS_RUN_FILE_FUNCTION(ByteString const& test_file, JS::Realm& realm, JS::Exec
{},
duration_ms,
test_result,
{ Test::Suite { test_path, "Parse file", test_result, { { expectation_string, test_result, message, static_cast<u64>(duration_ms) * 1000u } } } }
{ Test::Suite { test_path, "Parse file"_string, test_result, { { move(expectation_string), test_result, message, static_cast<u64>(duration_ms) * 1000u } } } }
};
}

View file

@ -401,16 +401,16 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
{
if (result.is_error()) {
if (result.error().phase == NegativePhase::Harness) {
output.set("harness_error", true);
output.set("harness_file", result.error().harness_file);
output.set("result", "harness_error"sv);
output.set("harness_error"sv, true);
output.set("harness_file"sv, 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))) {
output.set("todo_error", true);
output.set("result", "todo_error"sv);
output.set("todo_error"sv, true);
output.set("result"sv, "todo_error"sv);
}
}
}
@ -419,8 +419,8 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
auto output_messages = output.get_byte_string("output"sv);
VERIFY(output_messages.has_value());
if (output_messages->contains("AsyncTestFailure:InternalError: TODO("sv)) {
output.set("todo_error", true);
output.set("result", "todo_error"sv);
output.set("todo_error"sv, true);
output.set("result"sv, "todo_error"sv);
}
}
@ -440,9 +440,9 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
auto error_to_json = [&phase_to_string](TestError const& error) {
JsonObject error_object;
error_object.set("phase", phase_to_string(error.phase));
error_object.set("type", error.type);
error_object.set("details", error.details);
error_object.set("phase"sv, phase_to_string(error.phase));
error_object.set("type"sv, error.type);
error_object.set("details"sv, error.details);
return error_object;
};
@ -451,10 +451,10 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
ScopeGuard set_error = [&] {
JsonObject error_object;
error_object.set("expected", expected_error);
error_object.set("got", got_error);
error_object.set("expected"sv, expected_error);
error_object.set("got"sv, got_error);
output.set("error", error_object);
output.set("error"sv, error_object);
};
if (!metadata.is_negative) {
@ -466,8 +466,8 @@ static bool verify_test(ErrorOr<void, TestError>& result, TestMetadata const& me
}
JsonObject expected_error_object;
expected_error_object.set("phase", phase_to_string(metadata.phase));
expected_error_object.set("type", metadata.type.to_byte_string());
expected_error_object.set("phase"sv, phase_to_string(metadata.phase));
expected_error_object.set("type"sv, metadata.type.to_byte_string());
expected_error = expected_error_object;
@ -528,10 +528,10 @@ 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", s_current_test);
assert_fail_result.set("assert_fail", true);
assert_fail_result.set("result", "assert_fail"sv);
assert_fail_result.set("output", StringView { assert_failed_message, strlen(assert_failed_message) });
assert_fail_result.set("test"sv, 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) });
outln(saved_stdout_fd, "RESULT {}{}", assert_fail_result.to_byte_string(), '\0');
// (Attempt to) Ensure that messages are written before quitting.
fflush(saved_stdout_fd);
@ -730,7 +730,7 @@ int main(int argc, char** argv)
StringView original_contents = source_with_strict.substring_view(strict_length);
JsonObject result_object;
result_object.set("test", path);
result_object.set("test"sv, path);
ScopeGuard output_guard = [&] {
outln(saved_stdout_fd, "RESULT {}{}", result_object.to_byte_string(), '\0');
@ -739,22 +739,22 @@ int main(int argc, char** argv)
auto metadata_or_error = extract_metadata(original_contents);
if (metadata_or_error.is_error()) {
result_object.set("result", "metadata_error"sv);
result_object.set("metadata_error", true);
result_object.set("metadata_output", metadata_or_error.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());
continue;
}
auto& metadata = metadata_or_error.value();
if (metadata.skip_test == SkipTest::Yes) {
result_object.set("result", "skipped"sv);
result_object.set("result"sv, "skipped"sv);
continue;
}
bool passed = true;
if (metadata.strict_mode != StrictMode::OnlyStrict) {
result_object.set("strict_mode", false);
result_object.set("strict_mode"sv, false);
ARM_TIMER();
auto result = run_test(original_contents, path, metadata);
@ -762,15 +762,15 @@ int main(int argc, char** argv)
auto first_output = collect_output();
if (first_output.has_value())
result_object.set("output", *first_output);
result_object.set("output"sv, *first_output);
passed = verify_test(result, metadata, result_object);
auto output = first_output.value_or("");
if (metadata.is_async && !s_parse_only) {
if (!output.contains("Test262:AsyncTestComplete"sv) || output.contains("Test262:AsyncTestFailure"sv)) {
result_object.set("async_fail", true);
result_object.set("async_fail"sv, true);
if (!first_output.has_value())
result_object.set("output", JsonValue {});
result_object.set("output"sv, JsonValue {});
passed = false;
}
@ -778,7 +778,7 @@ int main(int argc, char** argv)
}
if (passed && metadata.strict_mode != StrictMode::NoStrict) {
result_object.set("strict_mode", true);
result_object.set("strict_mode"sv, true);
ARM_TIMER();
auto result = run_test(with_strict, path, metadata);
@ -786,16 +786,16 @@ int main(int argc, char** argv)
auto first_output = collect_output();
if (first_output.has_value())
result_object.set("strict_output", *first_output);
result_object.set("strict_output"sv, *first_output);
passed = verify_test(result, metadata, result_object);
auto output = first_output.value_or("");
if (metadata.is_async && !s_parse_only) {
if (!output.contains("Test262:AsyncTestComplete"sv) || output.contains("Test262:AsyncTestFailure"sv)) {
result_object.set("async_fail", true);
result_object.set("async_fail"sv, true);
if (!first_output.has_value())
result_object.set("output", JsonValue {});
result_object.set("output"sv, JsonValue {});
passed = false;
}