diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2022-02-24 20:08:48 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-27 20:37:57 +0100 |
commit | feb00b7105bbb55ba28b3fe8b6c526695f77bc84 (patch) | |
tree | 4be5bcdf63171729618deff8194db8fbcdb5bc3f | |
parent | 6682afb5d4d6b7455f85fa3a8f07dd14cae4211e (diff) | |
download | serenity-feb00b7105bbb55ba28b3fe8b6c526695f77bc84.zip |
Everywhere: Make JSON serialization fallible
This allows us to eliminate a major source of infallible allocation in
the Kernel, as well as lay down the groundwork for OOM fallibility in
userland.
-rw-r--r-- | AK/JsonArray.h | 5 | ||||
-rw-r--r-- | AK/JsonArraySerializer.h | 206 | ||||
-rw-r--r-- | AK/JsonObject.h | 5 | ||||
-rw-r--r-- | AK/JsonObjectSerializer.h | 226 | ||||
-rw-r--r-- | Kernel/Bus/USB/SysFSUSB.cpp | 36 | ||||
-rw-r--r-- | Kernel/Coredump.cpp | 30 | ||||
-rw-r--r-- | Kernel/FileSystem/VirtualFileSystem.cpp | 11 | ||||
-rw-r--r-- | Kernel/FileSystem/VirtualFileSystem.h | 2 | ||||
-rw-r--r-- | Kernel/GlobalProcessExposed.cpp | 495 | ||||
-rw-r--r-- | Kernel/PerformanceEventBuffer.cpp | 118 | ||||
-rw-r--r-- | Kernel/Process.h | 5 | ||||
-rw-r--r-- | Kernel/ProcessSpecificExposed.cpp | 123 | ||||
-rw-r--r-- | Userland/Applications/PixelPaint/Image.cpp | 30 | ||||
-rw-r--r-- | Userland/Applications/PixelPaint/ImageEditor.cpp | 18 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.cpp | 33 | ||||
-rw-r--r-- | Userland/Services/LaunchServer/Launcher.cpp | 14 | ||||
-rw-r--r-- | Userland/Services/WebContent/ConnectionFromClient.cpp | 12 |
18 files changed, 809 insertions, 564 deletions
diff --git a/AK/JsonArray.h b/AK/JsonArray.h index 7088fc9eda..57b6308dd1 100644 --- a/AK/JsonArray.h +++ b/AK/JsonArray.h @@ -85,8 +85,9 @@ private: template<typename Builder> inline void JsonArray::serialize(Builder& builder) const { - JsonArraySerializer serializer { builder }; - for_each([&](auto& value) { serializer.add(value); }); + auto serializer = MUST(JsonArraySerializer<>::try_create(builder)); + for_each([&](auto& value) { MUST(serializer.add(value)); }); + MUST(serializer.finish()); } template<typename Builder> diff --git a/AK/JsonArraySerializer.h b/AK/JsonArraySerializer.h index fa0f3086af..3a757765a1 100644 --- a/AK/JsonArraySerializer.h +++ b/AK/JsonArraySerializer.h @@ -1,132 +1,216 @@ /* * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org> + * Copyright (c) 2022, Idan Horowitz <idan.horowitz@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include <AK/JsonValue.h> +#include <AK/Error.h> +#include <AK/Try.h> + +#ifndef KERNEL +# include <AK/JsonValue.h> +#endif namespace AK { template<typename Builder> +inline constexpr bool IsLegacyBuilder = requires(Builder builder) { builder.try_append('\0'); }; + +template<typename Builder = void> class JsonObjectSerializer; -template<typename Builder> +template<typename Builder = void> class JsonArraySerializer { public: - explicit JsonArraySerializer(Builder& builder) - : m_builder(builder) + static ErrorOr<JsonArraySerializer> try_create(Builder& builder) + { + if constexpr (IsLegacyBuilder<Builder>) + TRY(builder.try_append('[')); + else + TRY(builder.append('[')); + return JsonArraySerializer { builder }; + } + + JsonArraySerializer(JsonArraySerializer&& other) + : m_builder(other.m_builder) + , m_empty(other.m_empty) + , m_finished(exchange(other.m_finished, true)) { - (void)m_builder.append('['); } JsonArraySerializer(const JsonArraySerializer&) = delete; - JsonArraySerializer(JsonArraySerializer&&) = delete; ~JsonArraySerializer() { - if (!m_finished) - finish(); + VERIFY(m_finished); } #ifndef KERNEL - void add(const JsonValue& value) + ErrorOr<void> add(const JsonValue& value) { - begin_item(); + TRY(begin_item()); value.serialize(m_builder); + return {}; } #endif - void add(StringView value) + ErrorOr<void> add(StringView value) { - begin_item(); - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(value); - (void)m_builder.append('"'); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(value)); + TRY(m_builder.try_append('"')); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(value)); + TRY(m_builder.append('"')); + } + return {}; } - void add(const String& value) - { - begin_item(); - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(value); - (void)m_builder.append('"'); +#ifndef KERNEL + ErrorOr<void> add(const String& value) + { + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(value)); + TRY(m_builder.try_append('"')); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(value)); + TRY(m_builder.append('"')); + } + return {}; } +#endif - void add(const char* value) + ErrorOr<void> add(const char* value) { - begin_item(); - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(value); - (void)m_builder.append('"'); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(value)); + TRY(m_builder.try_append('"')); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(value)); + TRY(m_builder.append('"')); + } + return {}; } - void add(bool value) + ErrorOr<void> add(bool value) { - begin_item(); - (void)m_builder.append(value ? "true"sv : "false"sv); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_append(value ? "true"sv : "false"sv)); + else + TRY(m_builder.append(value ? "true"sv : "false"sv)); + return {}; } - void add(int value) + ErrorOr<void> add(int value) { - begin_item(); - (void)m_builder.appendff("{}", value); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(unsigned value) + ErrorOr<void> add(unsigned value) { - begin_item(); - (void)m_builder.appendff("{}", value); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(long value) + ErrorOr<void> add(long value) { - begin_item(); - (void)m_builder.appendff("{}", value); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(long unsigned value) + ErrorOr<void> add(long unsigned value) { - begin_item(); - (void)m_builder.appendff("{}", value); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(long long value) + ErrorOr<void> add(long long value) { - begin_item(); - (void)m_builder.appendff("{}", value); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(long long unsigned value) + ErrorOr<void> add(long long unsigned value) { - begin_item(); - (void)m_builder.appendff("{}", value); + TRY(begin_item()); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - JsonArraySerializer<Builder> add_array() + ErrorOr<JsonArraySerializer<Builder>> add_array() { - begin_item(); - return JsonArraySerializer(m_builder); + TRY(begin_item()); + return JsonArraySerializer::try_create(m_builder); } // Implemented in JsonObjectSerializer.h - JsonObjectSerializer<Builder> add_object(); + ErrorOr<JsonObjectSerializer<Builder>> add_object(); - void finish() + ErrorOr<void> finish() { VERIFY(!m_finished); m_finished = true; - (void)m_builder.append(']'); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_append(']')); + else + TRY(m_builder.append(']')); + return {}; } private: - void begin_item() + explicit JsonArraySerializer(Builder& builder) + : m_builder(builder) + { + } + + ErrorOr<void> begin_item() { - if (!m_empty) - (void)m_builder.append(','); + VERIFY(!m_finished); + if (!m_empty) { + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_append(',')); + else + TRY(m_builder.append(',')); + } m_empty = false; + return {}; } Builder& m_builder; @@ -134,6 +218,16 @@ private: bool m_finished { false }; }; +// Template magic to allow for JsonArraySerializer<>::try_create(...) - Blame CxByte +template<> +struct JsonArraySerializer<void> { + template<typename Builder> + static ErrorOr<JsonArraySerializer<Builder>> try_create(Builder& builder) + { + return JsonArraySerializer<Builder>::try_create(builder); + } +}; + } using AK::JsonArraySerializer; diff --git a/AK/JsonObject.h b/AK/JsonObject.h index 8d27fdf829..469ac97e44 100644 --- a/AK/JsonObject.h +++ b/AK/JsonObject.h @@ -162,10 +162,11 @@ private: template<typename Builder> inline void JsonObject::serialize(Builder& builder) const { - JsonObjectSerializer serializer { builder }; + auto serializer = MUST(JsonObjectSerializer<>::try_create(builder)); for_each_member([&](auto& key, auto& value) { - serializer.add(key, value); + MUST(serializer.add(key, value)); }); + MUST(serializer.finish()); } template<typename Builder> diff --git a/AK/JsonObjectSerializer.h b/AK/JsonObjectSerializer.h index 804ae09732..faea026d8c 100644 --- a/AK/JsonObjectSerializer.h +++ b/AK/JsonObjectSerializer.h @@ -1,12 +1,15 @@ /* * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org> + * Copyright (c) 2022, Idan Horowitz <idan.horowitz@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once +#include <AK/Error.h> #include <AK/JsonArraySerializer.h> +#include <AK/Try.h> #ifndef KERNEL # include <AK/JsonValue.h> @@ -17,132 +20,217 @@ namespace AK { template<typename Builder> class JsonObjectSerializer { public: - explicit JsonObjectSerializer(Builder& builder) - : m_builder(builder) + static ErrorOr<JsonObjectSerializer> try_create(Builder& builder) + { + if constexpr (IsLegacyBuilder<Builder>) + TRY(builder.try_append('{')); + else + TRY(builder.append('{')); + return JsonObjectSerializer { builder }; + } + + JsonObjectSerializer(JsonObjectSerializer&& other) + : m_builder(other.m_builder) + , m_empty(other.m_empty) + , m_finished(exchange(other.m_finished, true)) { - (void)m_builder.append('{'); } JsonObjectSerializer(const JsonObjectSerializer&) = delete; - JsonObjectSerializer(JsonObjectSerializer&&) = delete; ~JsonObjectSerializer() { - if (!m_finished) - finish(); + VERIFY(m_finished); } #ifndef KERNEL - void add(StringView key, const JsonValue& value) + ErrorOr<void> add(StringView key, const JsonValue& value) { - begin_item(key); + TRY(begin_item(key)); value.serialize(m_builder); + return {}; } #endif - void add(StringView key, StringView value) + ErrorOr<void> add(StringView key, StringView value) { - begin_item(key); - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(value); - (void)m_builder.append('"'); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(value)); + TRY(m_builder.try_append('"')); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(value)); + TRY(m_builder.append('"')); + } + return {}; } - void add(StringView key, const String& value) +#ifndef KERNEL + ErrorOr<void> add(StringView key, const String& value) { - begin_item(key); - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(value); - (void)m_builder.append('"'); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(value)); + TRY(m_builder.try_append('"')); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(value)); + TRY(m_builder.append('"')); + } + return {}; } +#endif - void add(StringView key, const char* value) + ErrorOr<void> add(StringView key, const char* value) { - begin_item(key); - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(value); - (void)m_builder.append('"'); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(value)); + TRY(m_builder.try_append('"')); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(value)); + TRY(m_builder.append('"')); + } + return {}; } - void add(StringView key, bool value) + ErrorOr<void> add(StringView key, bool value) { - begin_item(key); - (void)m_builder.append(value ? "true" : "false"); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_append(value ? "true" : "false")); + else + TRY(m_builder.append(value ? "true" : "false")); + return {}; } - void add(StringView key, int value) + ErrorOr<void> add(StringView key, int value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(StringView key, unsigned value) + ErrorOr<void> add(StringView key, unsigned value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(StringView key, long value) + ErrorOr<void> add(StringView key, long value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(StringView key, long unsigned value) + ErrorOr<void> add(StringView key, long unsigned value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(StringView key, long long value) + ErrorOr<void> add(StringView key, long long value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } - void add(StringView key, long long unsigned value) + ErrorOr<void> add(StringView key, long long unsigned value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } #ifndef KERNEL - void add(StringView key, double value) + ErrorOr<void> add(StringView key, double value) { - begin_item(key); - (void)m_builder.appendff("{}", value); + TRY(begin_item(key)); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_appendff("{}", value)); + else + TRY(m_builder.appendff("{}", value)); + return {}; } #endif - JsonArraySerializer<Builder> add_array(StringView key) + ErrorOr<JsonArraySerializer<Builder>> add_array(StringView key) { - begin_item(key); - return JsonArraySerializer(m_builder); + TRY(begin_item(key)); + return JsonArraySerializer<Builder>::try_create(m_builder); } - JsonObjectSerializer<Builder> add_object(StringView key) + ErrorOr<JsonObjectSerializer<Builder>> add_object(StringView key) { - begin_item(key); - return JsonObjectSerializer(m_builder); + TRY(begin_item(key)); + return JsonObjectSerializer::try_create(m_builder); } - void finish() + ErrorOr<void> finish() { VERIFY(!m_finished); m_finished = true; - (void)m_builder.append('}'); + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_append('}')); + else + TRY(m_builder.append('}')); + return {}; } private: - void begin_item(StringView key) + explicit JsonObjectSerializer(Builder& builder) + : m_builder(builder) { - if (!m_empty) - (void)m_builder.append(','); + } + + ErrorOr<void> begin_item(StringView key) + { + VERIFY(!m_finished); + if (!m_empty) { + if constexpr (IsLegacyBuilder<Builder>) + TRY(m_builder.try_append(',')); + else + TRY(m_builder.append(',')); + } m_empty = false; - (void)m_builder.append('"'); - (void)m_builder.append_escaped_for_json(key); - (void)m_builder.append("\":"); + if constexpr (IsLegacyBuilder<Builder>) { + TRY(m_builder.try_append('"')); + TRY(m_builder.try_append_escaped_for_json(key)); + TRY(m_builder.try_append("\":")); + } else { + TRY(m_builder.append('"')); + TRY(m_builder.append_escaped_for_json(key)); + TRY(m_builder.append("\":")); + } + return {}; } Builder& m_builder; @@ -150,11 +238,21 @@ private: bool m_finished { false }; }; +// Template magic to allow for JsonObjectSerializer<>::try_create(...) - Blame CxByte +template<> +struct JsonObjectSerializer<void> { + template<typename Builder> + static ErrorOr<JsonObjectSerializer<Builder>> try_create(Builder& builder) + { + return JsonObjectSerializer<Builder>::try_create(builder); + } +}; + template<typename Builder> -JsonObjectSerializer<Builder> JsonArraySerializer<Builder>::add_object() +ErrorOr<JsonObjectSerializer<Builder>> JsonArraySerializer<Builder>::add_object() { - begin_item(); - return JsonObjectSerializer(m_builder); + TRY(begin_item()); + return JsonObjectSerializer<Builder>::try_create(m_builder); } } diff --git a/Kernel/Bus/USB/SysFSUSB.cpp b/Kernel/Bus/USB/SysFSUSB.cpp index 0ae6a5fdb3..567910bdee 100644 --- a/Kernel/Bus/USB/SysFSUSB.cpp +++ b/Kernel/Bus/USB/SysFSUSB.cpp @@ -27,24 +27,24 @@ SysFSUSBDeviceInformation::~SysFSUSBDeviceInformation() ErrorOr<void> SysFSUSBDeviceInformation::try_generate(KBufferBuilder& builder) { VERIFY(m_lock.is_locked()); - JsonArraySerializer array { builder }; - - auto obj = array.add_object(); - obj.add("device_address", m_device->address()); - obj.add("usb_spec_compliance_bcd", m_device->device_descriptor().usb_spec_compliance_bcd); - obj.add("device_class", m_device->device_descriptor().device_class); - obj.add("device_sub_class", m_device->device_descriptor().device_sub_class); - obj.add("device_protocol", m_device->device_descriptor().device_protocol); - obj.add("max_packet_size", m_device->device_descriptor().max_packet_size); - obj.add("vendor_id", m_device->device_descriptor().vendor_id); - obj.add("product_id", m_device->device_descriptor().product_id); - obj.add("device_release_bcd", m_device->device_descriptor().device_release_bcd); - obj.add("manufacturer_id_descriptor_index", m_device->device_descriptor().manufacturer_id_descriptor_index); - obj.add("product_string_descriptor_index", m_device->device_descriptor().product_string_descriptor_index); - obj.add("serial_number_descriptor_index", m_device->device_descriptor().serial_number_descriptor_index); - obj.add("num_configurations", m_device->device_descriptor().num_configurations); - obj.finish(); - array.finish(); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + + auto obj = TRY(array.add_object()); + TRY(obj.add("device_address", m_device->address())); + TRY(obj.add("usb_spec_compliance_bcd", m_device->device_descriptor().usb_spec_compliance_bcd)); + TRY(obj.add("device_class", m_device->device_descriptor().device_class)); + TRY(obj.add("device_sub_class", m_device->device_descriptor().device_sub_class)); + TRY(obj.add("device_protocol", m_device->device_descriptor().device_protocol)); + TRY(obj.add("max_packet_size", m_device->device_descriptor().max_packet_size)); + TRY(obj.add("vendor_id", m_device->device_descriptor().vendor_id)); + TRY(obj.add("product_id", m_device->device_descriptor().product_id)); + TRY(obj.add("device_release_bcd", m_device->device_descriptor().device_release_bcd)); + TRY(obj.add("manufacturer_id_descriptor_index", m_device->device_descriptor().manufacturer_id_descriptor_index)); + TRY(obj.add("product_string_descriptor_index", m_device->device_descriptor().product_string_descriptor_index)); + TRY(obj.add("serial_number_descriptor_index", m_device->device_descriptor().serial_number_descriptor_index)); + TRY(obj.add("num_configurations", m_device->device_descriptor().num_configurations)); + TRY(obj.finish()); + TRY(array.finish()); return {}; } diff --git a/Kernel/Coredump.cpp b/Kernel/Coredump.cpp index fe4629d53a..47958440f1 100644 --- a/Kernel/Coredump.cpp +++ b/Kernel/Coredump.cpp @@ -220,22 +220,26 @@ ErrorOr<void> Coredump::create_notes_process_data(auto& builder) const TRY(builder.append_bytes(ReadonlyBytes { (void*)&info, sizeof(info) })); { - JsonObjectSerializer process_obj { builder }; - process_obj.add("pid"sv, m_process->pid().value()); - process_obj.add("termination_signal"sv, m_process->termination_signal()); - process_obj.add("executable_path"sv, m_process->executable() ? TRY(m_process->executable()->try_serialize_absolute_path())->view() : ""sv); + auto process_obj = TRY(JsonObjectSerializer<>::try_create(builder)); + TRY(process_obj.add("pid"sv, m_process->pid().value())); + TRY(process_obj.add("termination_signal"sv, m_process->termination_signal())); + TRY(process_obj.add("executable_path"sv, m_process->executable() ? TRY(m_process->executable()->try_serialize_absolute_path())->view() : ""sv)); { - auto arguments_array = process_obj.add_array("arguments"sv); + auto arguments_array = TRY(process_obj.add_array("arguments"sv)); for (auto const& argument : m_process->arguments()) - arguments_array.add(argument.view()); + TRY(arguments_array.add(argument.view())); + TRY(arguments_array.finish()); } { - auto environment_array = process_obj.add_array("environment"sv); + auto environment_array = TRY(process_obj.add_array("environment"sv)); for (auto const& variable : m_process->environment()) - environment_array.add(variable.view()); + TRY(environment_array.add(variable.view())); + TRY(environment_array.finish()); } + + TRY(process_obj.finish()); } TRY(builder.append('\0')); @@ -296,10 +300,12 @@ ErrorOr<void> Coredump::create_notes_metadata_data(auto& builder) const TRY(builder.append_bytes(ReadonlyBytes { (void*)&metadata, sizeof(metadata) })); { - JsonObjectSerializer metadata_obj { builder }; - m_process->for_each_coredump_property([&](auto& key, auto& value) { - metadata_obj.add(key.view(), value.view()); - }); + auto metadata_obj = TRY(JsonObjectSerializer<>::try_create(builder)); + TRY(m_process->for_each_coredump_property([&](auto& key, auto& value) -> ErrorOr<void> { + TRY(metadata_obj.add(key.view(), value.view())); + return {}; + })); + TRY(metadata_obj.finish()); } TRY(builder.append('\0')); return {}; diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index ca63fdd7da..74eabfb8f1 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -725,13 +725,12 @@ ErrorOr<void> VirtualFileSystem::rmdir(StringView path, Custody& base) return parent_inode.remove_child(KLexicalPath::basename(path)); } -void VirtualFileSystem::for_each_mount(Function<IterationDecision(Mount const&)> callback) const +ErrorOr<void> VirtualFileSystem::for_each_mount(Function<ErrorOr<void>(Mount const&)> callback) const { - m_mounts.with([&](auto& mounts) { - for (auto& mount : mounts) { - if (callback(mount) == IterationDecision::Break) - break; - } + return m_mounts.with([&](auto& mounts) -> ErrorOr<void> { + for (auto& mount : mounts) + TRY(callback(mount)); + return {}; }); } diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 72993c3093..61ebc2ce12 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -68,7 +68,7 @@ public: ErrorOr<void> mknod(StringView path, mode_t, dev_t, Custody& base); ErrorOr<NonnullRefPtr<Custody>> open_directory(StringView path, Custody& base); - void for_each_mount(Function<IterationDecision(const Mount&)>) const; + ErrorOr<void> for_each_mount(Function<ErrorOr<void>(const Mount&)>) const; InodeIdentifier root_inode_id() const; diff --git a/Kernel/GlobalProcessExposed.cpp b/Kernel/GlobalProcessExposed.cpp index 3cbc7139e5..1353389577 100644 --- a/Kernel/GlobalProcessExposed.cpp +++ b/Kernel/GlobalProcessExposed.cpp @@ -40,33 +40,35 @@ private: ProcFSAdapters(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - NetworkingManagement::the().for_each([&array](auto& adapter) { - auto obj = array.add_object(); - obj.add("name", adapter.name()); - obj.add("class_name", adapter.class_name()); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(NetworkingManagement::the().try_for_each([&array](auto& adapter) -> ErrorOr<void> { + auto obj = TRY(array.add_object()); + TRY(obj.add("name", adapter.name())); + TRY(obj.add("class_name", adapter.class_name())); auto mac_address = adapter.mac_address().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("mac_address", mac_address->view()); + TRY(obj.add("mac_address", mac_address->view())); if (!adapter.ipv4_address().is_zero()) { auto ipv4_address = adapter.ipv4_address().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("ipv4_address", ipv4_address->view()); + TRY(obj.add("ipv4_address", ipv4_address->view())); auto ipv4_netmask = adapter.ipv4_netmask().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("ipv4_netmask", ipv4_netmask->view()); + TRY(obj.add("ipv4_netmask", ipv4_netmask->view())); } if (!adapter.ipv4_gateway().is_zero()) { auto ipv4_gateway = adapter.ipv4_gateway().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("ipv4_gateway", ipv4_gateway->view()); + TRY(obj.add("ipv4_gateway", ipv4_gateway->view())); } - obj.add("packets_in", adapter.packets_in()); - obj.add("bytes_in", adapter.bytes_in()); - obj.add("packets_out", adapter.packets_out()); - obj.add("bytes_out", adapter.bytes_out()); - obj.add("link_up", adapter.link_up()); - obj.add("link_speed", adapter.link_speed()); - obj.add("link_full_duplex", adapter.link_full_duplex()); - obj.add("mtu", adapter.mtu()); - }); - array.finish(); + TRY(obj.add("packets_in", adapter.packets_in())); + TRY(obj.add("bytes_in", adapter.bytes_in())); + TRY(obj.add("packets_out", adapter.packets_out())); + TRY(obj.add("bytes_out", adapter.bytes_out())); + TRY(obj.add("link_up", adapter.link_up())); + TRY(obj.add("link_speed", adapter.link_speed())); + TRY(obj.add("link_full_duplex", adapter.link_full_duplex())); + TRY(obj.add("mtu", adapter.mtu())); + TRY(obj.finish()); + return {}; + })); + TRY(array.finish()); return {}; } }; @@ -79,15 +81,19 @@ private: ProcFSARP(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - arp_table().for_each([&](const auto& it) { - auto obj = array.add_object(); - auto mac_address = it.value.to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("mac_address", mac_address->view()); - auto ip_address = it.key.to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("ip_address", ip_address->view()); - }); - array.finish(); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(arp_table().with([&](const auto& table) -> ErrorOr<void> { + for (auto& it : table) { + auto obj = TRY(array.add_object()); + auto mac_address = it.value.to_string().release_value_but_fixme_should_propagate_errors(); + TRY(obj.add("mac_address", mac_address->view())); + auto ip_address = it.key.to_string().release_value_but_fixme_should_propagate_errors(); + TRY(obj.add("ip_address", ip_address->view())); + TRY(obj.finish()); + } + return {}; + })); + TRY(array.finish()); return {}; } }; @@ -100,29 +106,31 @@ private: ProcFSTCP(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - TCPSocket::for_each([&array](auto& socket) { - auto obj = array.add_object(); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(TCPSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> { + auto obj = TRY(array.add_object()); auto local_address = socket.local_address().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("local_address", local_address->view()); - obj.add("local_port", socket.local_port()); + TRY(obj.add("local_address", local_address->view())); + TRY(obj.add("local_port", socket.local_port())); auto peer_address = socket.peer_address().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("peer_address", peer_address->view()); - obj.add("peer_port", socket.peer_port()); - obj.add("state", TCPSocket::to_string(socket.state())); - obj.add("ack_number", socket.ack_number()); - obj.add("sequence_number", socket.sequence_number()); - obj.add("packets_in", socket.packets_in()); - obj.add("bytes_in", socket.bytes_in()); - obj.add("packets_out", socket.packets_out()); - obj.add("bytes_out", socket.bytes_out()); + TRY(obj.add("peer_address", peer_address->view())); + TRY(obj.add("peer_port", socket.peer_port())); + TRY(obj.add("state", TCPSocket::to_string(socket.state()))); + TRY(obj.add("ack_number", socket.ack_number())); + TRY(obj.add("sequence_number", socket.sequence_number())); + TRY(obj.add("packets_in", socket.packets_in())); + TRY(obj.add("bytes_in", socket.bytes_in())); + TRY(obj.add("packets_out", socket.packets_out())); + TRY(obj.add("bytes_out", socket.bytes_out())); if (Process::current().is_superuser() || Process::current().uid() == socket.origin_uid()) { - obj.add("origin_pid", socket.origin_pid().value()); - obj.add("origin_uid", socket.origin_uid().value()); - obj.add("origin_gid", socket.origin_gid().value()); + TRY(obj.add("origin_pid", socket.origin_pid().value())); + TRY(obj.add("origin_uid", socket.origin_uid().value())); + TRY(obj.add("origin_gid", socket.origin_gid().value())); } - }); - array.finish(); + TRY(obj.finish()); + return {}; + })); + TRY(array.finish()); return {}; } }; @@ -135,18 +143,20 @@ private: ProcFSLocalNet(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - LocalSocket::for_each([&array](auto& socket) { - auto obj = array.add_object(); - obj.add("path", socket.socket_path()); - obj.add("origin_pid", socket.origin_pid().value()); - obj.add("origin_uid", socket.origin_uid().value()); - obj.add("origin_gid", socket.origin_gid().value()); - obj.add("acceptor_pid", socket.acceptor_pid().value()); - obj.add("acceptor_uid", socket.acceptor_uid().value()); - obj.add("acceptor_gid", socket.acceptor_gid().value()); - }); - array.finish(); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(LocalSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> { + auto obj = TRY(array.add_object()); + TRY(obj.add("path", socket.socket_path())); + TRY(obj.add("origin_pid", socket.origin_pid().value())); + TRY(obj.add("origin_uid", socket.origin_uid().value())); + TRY(obj.add("origin_gid", socket.origin_gid().value())); + TRY(obj.add("acceptor_pid", socket.acceptor_pid().value())); + TRY(obj.add("acceptor_uid", socket.acceptor_uid().value())); + TRY(obj.add("acceptor_gid", socket.acceptor_gid().value())); + TRY(obj.finish()); + return {}; + })); + TRY(array.finish()); return {}; } }; @@ -159,22 +169,24 @@ private: ProcFSUDP(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - UDPSocket::for_each([&array](auto& socket) { - auto obj = array.add_object(); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(UDPSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> { + auto obj = TRY(array.add_object()); auto local_address = socket.local_address().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("local_address", local_address->view()); - obj.add("local_port", socket.local_port()); + TRY(obj.add("local_address", local_address->view())); + TRY(obj.add("local_port", socket.local_port())); auto peer_address = socket.peer_address().to_string().release_value_but_fixme_should_propagate_errors(); - obj.add("peer_address", peer_address->view()); - obj.add("peer_port", socket.peer_port()); + TRY(obj.add("peer_address", peer_address->view())); + TRY(obj.add("peer_port", socket.peer_port())); if (Process::current().is_superuser() || Process::current().uid() == socket.origin_uid()) { - obj.add("origin_pid", socket.origin_pid().value()); - obj.add("origin_uid", socket.origin_uid().value()); - obj.add("origin_gid", socket.origin_gid().value()); + TRY(obj.add("origin_pid", socket.origin_pid().value())); + TRY(obj.add("origin_uid", socket.origin_uid().value())); + TRY(obj.add("origin_gid", socket.origin_gid().value())); } - }); - array.finish(); + TRY(obj.finish()); + return {}; + })); + TRY(array.finish()); return {}; } }; @@ -349,43 +361,33 @@ private: ProcFSDiskUsage(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - ErrorOr<void> result; - VirtualFileSystem::the().for_each_mount([&array, &result](auto& mount) { + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(VirtualFileSystem::the().for_each_mount([&array](auto& mount) -> ErrorOr<void> { auto& fs = mount.guest_fs(); - auto fs_object = array.add_object(); - fs_object.add("class_name", fs.class_name()); - fs_object.add("total_block_count", fs.total_block_count()); - fs_object.add("free_block_count", fs.free_block_count()); - fs_object.add("total_inode_count", fs.total_inode_count()); - fs_object.add("free_inode_count", fs.free_inode_count()); - auto mount_point_or_error = mount.absolute_path(); - if (mount_point_or_error.is_error()) { - result = mount_point_or_error.release_error(); - return IterationDecision::Break; - } - fs_object.add("mount_point", mount_point_or_error.value()->view()); - fs_object.add("block_size", static_cast<u64>(fs.block_size())); - fs_object.add("readonly", fs.is_readonly()); - fs_object.add("mount_flags", mount.flags()); + auto fs_object = TRY(array.add_object()); + TRY(fs_object.add("class_name", fs.class_name())); + TRY(fs_object.add("total_block_count", fs.total_block_count())); + TRY(fs_object.add("free_block_count", fs.free_block_count())); + TRY(fs_object.add("total_inode_count", fs.total_inode_count())); + TRY(fs_object.add("free_inode_count", fs.free_inode_count())); + auto mount_point = TRY(mount.absolute_path()); + TRY(fs_object.add("mount_point", mount_point->view())); + TRY(fs_object.add("block_size", static_cast<u64>(fs.block_size()))); + TRY(fs_object.add("readonly", fs.is_readonly())); + TRY(fs_object.add("mount_flags", mount.flags())); if (fs.is_file_backed()) { - auto pseudo_path_or_error = static_cast<const FileBackedFileSystem&>(fs).file_description().pseudo_path(); - if (pseudo_path_or_error.is_error()) { - // We're probably out of memory and should not attempt to continue. - result = pseudo_path_or_error.release_error(); - return IterationDecision::Break; - } - fs_object.add("source", pseudo_path_or_error.value()->view()); + auto pseudo_path = TRY(static_cast<const FileBackedFileSystem&>(fs).file_description().pseudo_path()); + TRY(fs_object.add("source", pseudo_path->view())); } else { - fs_object.add("source", "none"); + TRY(fs_object.add("source", "none")); } - return IterationDecision::Continue; - }); - if (!result.is_error()) - array.finish(); - return result; + TRY(fs_object.finish()); + return {}; + })); + TRY(array.finish()); + return {}; } }; @@ -404,18 +406,18 @@ private: auto system_memory = MM.get_system_memory_info(); - JsonObjectSerializer<KBufferBuilder> json { builder }; - json.add("kmalloc_allocated", stats.bytes_allocated); - json.add("kmalloc_available", stats.bytes_free); - json.add("user_physical_allocated", system_memory.user_physical_pages_used); - json.add("user_physical_available", system_memory.user_physical_pages - system_memory.user_physical_pages_used); - json.add("user_physical_committed", system_memory.user_physical_pages_committed); - json.add("user_physical_uncommitted", system_memory.user_physical_pages_uncommitted); - json.add("super_physical_allocated", system_memory.super_physical_pages_used); - json.add("super_physical_available", system_memory.super_physical_pages - system_memory.super_physical_pages_used); - json.add("kmalloc_call_count", stats.kmalloc_call_count); - json.add("kfree_call_count", stats.kfree_call_count); - json.finish(); + auto json = TRY(JsonObjectSerializer<>::try_create(builder)); + TRY(json.add("kmalloc_allocated", stats.bytes_allocated)); + TRY(json.add("kmalloc_available", stats.bytes_free)); + TRY(json.add("user_physical_allocated", system_memory.user_physical_pages_used)); + TRY(json.add("user_physical_available", system_memory.user_physical_pages - system_memory.user_physical_pages_used)); + TRY(json.add("user_physical_committed", system_memory.user_physical_pages_committed)); + TRY(json.add("user_physical_uncommitted", system_memory.user_physical_pages_uncommitted)); + TRY(json.add("super_physical_allocated", system_memory.super_physical_pages_used)); + TRY(json.add("super_physical_available", system_memory.super_physical_pages - system_memory.super_physical_pages_used)); + TRY(json.add("kmalloc_call_count", stats.kmalloc_call_count)); + TRY(json.add("kfree_call_count", stats.kfree_call_count)); + TRY(json.finish()); return {}; } }; @@ -428,17 +430,17 @@ private: ProcFSSystemStatistics(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonObjectSerializer<KBufferBuilder> json { builder }; + auto json = TRY(JsonObjectSerializer<>::try_create(builder)); auto total_time_scheduled = Scheduler::get_total_time_scheduled(); - json.add("total_time", total_time_scheduled.total); - json.add("kernel_time", total_time_scheduled.total_kernel); - json.add("user_time", total_time_scheduled.total - total_time_scheduled.total_kernel); + TRY(json.add("total_time", total_time_scheduled.total)); + TRY(json.add("kernel_time", total_time_scheduled.total_kernel)); + TRY(json.add("user_time", total_time_scheduled.total - total_time_scheduled.total_kernel)); u64 idle_time = 0; Processor::for_each([&](Processor& processor) { idle_time += processor.time_spent_idle(); }); - json.add("idle_time", idle_time); - json.finish(); + TRY(json.add("idle_time", idle_time)); + TRY(json.finish()); return {}; } }; @@ -451,11 +453,11 @@ private: ProcFSOverallProcesses(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonObjectSerializer<KBufferBuilder> json { builder }; + auto json = TRY(JsonObjectSerializer<>::try_create(builder)); // Keep this in sync with CProcessStatistics. auto build_process = [&](JsonArraySerializer<KBufferBuilder>& array, const Process& process) -> ErrorOr<void> { - auto process_object = array.add_object(); + auto process_object = TRY(array.add_object()); if (process.is_user_process()) { StringBuilder pledge_builder; @@ -466,90 +468,96 @@ private: ENUMERATE_PLEDGE_PROMISES #undef __ENUMERATE_PLEDGE_PROMISE - process_object.add("pledge", pledge_builder.string_view()); + TRY(process_object.add("pledge", pledge_builder.string_view())); switch (process.veil_state()) { case VeilState::None: - process_object.add("veil", "None"); + TRY(process_object.add("veil", "None")); break; case VeilState::Dropped: - process_object.add("veil", "Dropped"); + TRY(process_object.add("veil", "Dropped")); break; case VeilState::Locked: - process_object.add("veil", "Locked"); + TRY(process_object.add("veil", "Locked")); break; } } else { - process_object.add("pledge", ""sv); - process_object.add("veil", ""sv); + TRY(process_object.add("pledge", ""sv)); + TRY(process_object.add("veil", ""sv)); } - process_object.add("pid", process.pid().value()); - process_object.add("pgid", process.tty() ? process.tty()->pgid().value() : 0); - process_object.add("pgp", process.pgid().value()); - process_object.add("sid", process.sid().value()); - process_object.add("uid", process.uid().value()); - process_object.add("gid", process.gid().value()); - process_object.add("ppid", process.ppid().value()); - process_object.add("nfds", process.fds().with_shared([](auto& fds) { return fds.open_count(); })); - process_object.add("name", process.name()); - process_object.add("executable", process.executable() ? TRY(process.executable()->try_serialize_absolute_path())->view() : ""sv); - process_object.add("tty", process.tty() ? process.tty()->tty_name().view() : "notty"sv); - process_object.add("amount_virtual", process.address_space().amount_virtual()); - process_object.add("amount_resident", process.address_space().amount_resident()); - process_object.add("amount_dirty_private", process.address_space().amount_dirty_private()); - process_object.add("amount_clean_inode", TRY(process.address_space().amount_clean_inode())); - process_object.add("amount_shared", process.address_space().amount_shared()); - process_object.add("amount_purgeable_volatile", process.address_space().amount_purgeable_volatile()); - process_object.add("amount_purgeable_nonvolatile", process.address_space().amount_purgeable_nonvolatile()); - process_object.add("dumpable", process.is_dumpable()); - process_object.add("kernel", process.is_kernel_process()); - auto thread_array = process_object.add_array("threads"); - process.for_each_thread([&](const Thread& thread) { + TRY(process_object.add("pid", process.pid().value())); + TRY(process_object.add("pgid", process.tty() ? process.tty()->pgid().value() : 0)); + TRY(process_object.add("pgp", process.pgid().value())); + TRY(process_object.add("sid", process.sid().value())); + TRY(process_object.add("uid", process.uid().value())); + TRY(process_object.add("gid", process.gid().value())); + TRY(process_object.add("ppid", process.ppid().value())); + TRY(process_object.add("nfds", process.fds().with_shared([](auto& fds) { return fds.open_count(); }))); + TRY(process_object.add("name", process.name())); + TRY(process_object.add("executable", process.executable() ? TRY(process.executable()->try_serialize_absolute_path())->view() : ""sv)); + TRY(process_object.add("tty", process.tty() ? process.tty()->tty_name().view() : "notty"sv)); + TRY(process_object.add("amount_virtual", process.address_space().amount_virtual())); + TRY(process_object.add("amount_resident", process.address_space().amount_resident())); + TRY(process_object.add("amount_dirty_private", process.address_space().amount_dirty_private())); + TRY(process_object.add("amount_clean_inode", TRY(process.address_space().amount_clean_inode()))); + TRY(process_object.add("amount_shared", process.address_space().amount_shared())); + TRY(process_object.add("amount_purgeable_volatile", process.address_space().amount_purgeable_volatile())); + TRY(process_object.add("amount_purgeable_nonvolatile", process.address_space().amount_purgeable_nonvolatile())); + TRY(process_object.add("dumpable", process.is_dumpable())); + TRY(process_object.add("kernel", process.is_kernel_process())); + auto thread_array = TRY(process_object.add_array("threads")); + TRY(process.try_for_each_thread([&](const Thread& thread) -> ErrorOr<void> { SpinlockLocker locker(thread.get_lock()); - auto thread_object = thread_array.add_object(); + auto thread_object = TRY(thread_array.add_object()); #if LOCK_DEBUG - thread_object.add("lock_count", thread.lock_count()); + TRY(thread_object.add("lock_count", thread.lock_count())); #endif - thread_object.add("tid", thread.tid().value()); - thread_object.add("name", thread.name()); - thread_object.add("times_scheduled", thread.times_scheduled()); - thread_object.add("time_user", thread.time_in_user()); - thread_object.add("time_kernel", thread.time_in_kernel()); - thread_object.add("state", thread.state_string()); - thread_object.add("cpu", thread.cpu()); - thread_object.add("priority", thread.priority()); - thread_object.add("syscall_count", thread.syscall_count()); - thread_object.add("inode_faults", thread.inode_faults()); - thread_object.add("zero_faults", thread.zero_faults()); - thread_object.add("cow_faults", thread.cow_faults()); - thread_object.add("file_read_bytes", thread.file_read_bytes()); - thread_object.add("file_write_bytes", thread.file_write_bytes()); - thread_object.add("unix_socket_read_bytes", thread.unix_socket_read_bytes()); - thread_object.add("unix_socket_write_bytes", thread.unix_socket_write_bytes()); - thread_object.add("ipv4_socket_read_bytes", thread.ipv4_socket_read_bytes()); - thread_object.add("ipv4_socket_write_bytes", thread.ipv4_socket_write_bytes()); - }); - + TRY(thread_object.add("tid", thread.tid().value())); + TRY(thread_object.add("name", thread.name())); + TRY(thread_object.add("times_scheduled", thread.times_scheduled())); + TRY(thread_object.add("time_user", thread.time_in_user())); + TRY(thread_object.add("time_kernel", thread.time_in_kernel())); + TRY(thread_object.add("state", thread.state_string())); + TRY(thread_object.add("cpu", thread.cpu())); + TRY(thread_object.add("priority", thread.priority())); + TRY(thread_object.add("syscall_count", thread.syscall_count())); + TRY(thread_object.add("inode_faults", thread.inode_faults())); + TRY(thread_object.add("zero_faults", thread.zero_faults())); + TRY(thread_object.add("cow_faults", thread.cow_faults())); + TRY(thread_object.add("file_read_bytes", thread.file_read_bytes())); + TRY(thread_object.add("file_write_bytes", thread.file_write_bytes())); + TRY(thread_object.add("unix_socket_read_bytes", thread.unix_socket_read_bytes())); + TRY(thread_object.add("unix_socket_write_bytes", thread.unix_socket_write_bytes())); + TRY(thread_object.add("ipv4_socket_read_bytes", thread.ipv4_socket_read_bytes())); + TRY(thread_object.add("ipv4_socket_write_bytes", thread.ipv4_socket_write_bytes())); + + TRY(thread_object.finish()); + return {}; + })); + TRY(thread_array.finish()); + TRY(process_object.finish()); return {}; }; SpinlockLocker lock(g_scheduler_lock); { { - auto array = json.add_array("processes"); + auto array = TRY(json.add_array("processes")); TRY(build_process(array, *Scheduler::colonel())); TRY(Process::all_instances().with([&](auto& processes) -> ErrorOr<void> { for (auto& process : processes) TRY(build_process(array, process)); return {}; })); + TRY(array.finish()); } auto total_time_scheduled = Scheduler::get_total_time_scheduled(); - json.add("total_time", total_time_scheduled.total); - json.add("total_time_kernel", total_time_scheduled.total_kernel); + TRY(json.add("total_time", total_time_scheduled.total)); + TRY(json.add("total_time_kernel", total_time_scheduled.total_kernel)); } + TRY(json.finish()); return {}; } }; @@ -561,28 +569,37 @@ private: ProcFSCPUInformation(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - Processor::for_each( - [&](Processor& proc) { + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(Processor::try_for_each( + [&](Processor& proc) -> ErrorOr<void> { auto& info = proc.info(); - auto obj = array.add_object(); - obj.add("processor", proc.id()); - obj.add("cpuid", info.cpuid()); - obj.add("family", info.display_family()); + auto obj = TRY(array.add_object()); + TRY(obj.add("processor", proc.id())); + TRY(obj.add("cpuid", info.cpuid())); + TRY(obj.add("family", info.display_family())); - auto features_array = obj.add_array("features"); + auto features_array = TRY(obj.add_array("features")); auto keep_empty = false; + + ErrorOr<void> result; // FIXME: Make this nicer info.features().for_each_split_view(' ', keep_empty, [&](StringView feature) { - features_array.add(feature); + if (result.is_error()) + return; + result = features_array.add(feature); }); - features_array.finish(); - - obj.add("model", info.display_model()); - obj.add("stepping", info.stepping()); - obj.add("type", info.type()); - obj.add("brand", info.brand()); - }); - array.finish(); + TRY(result); + + TRY(features_array.finish()); + + TRY(obj.add("model", info.display_model())); + TRY(obj.add("stepping", info.stepping())); + TRY(obj.add("type", info.type())); + TRY(obj.add("brand", info.brand())); + + TRY(obj.finish()); + return {}; + })); + TRY(array.finish()); return {}; } }; @@ -612,17 +629,25 @@ private: ProcFSInterrupts(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - InterruptManagement::the().enumerate_interrupt_handlers([&array](GenericInterruptHandler& handler) { - auto obj = array.add_object(); - obj.add("purpose", handler.purpose()); - obj.add("interrupt_line", handler.interrupt_number()); - obj.add("controller", handler.controller()); - obj.add("cpu_handler", 0); // FIXME: Determine the responsible CPU for each interrupt handler. - obj.add("device_sharing", (unsigned)handler.sharing_devices_count()); - obj.add("call_count", (unsigned)handler.get_invoking_count()); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + ErrorOr<void> result; // FIXME: Make this nicer + InterruptManagement::the().enumerate_interrupt_handlers([&array, &result](GenericInterruptHandler& handler) { + if (result.is_error()) + return; + result = ([&]() -> ErrorOr<void> { + auto obj = TRY(array.add_object()); + TRY(obj.add("purpose", handler.purpose())); + TRY(obj.add("interrupt_line", handler.interrupt_number())); + TRY(obj.add("controller", handler.controller())); + TRY(obj.add("cpu_handler", 0)); // FIXME: Determine the responsible CPU for each interrupt handler. + TRY(obj.add("device_sharing", (unsigned)handler.sharing_devices_count())); + TRY(obj.add("call_count", (unsigned)handler.get_invoking_count())); + TRY(obj.finish()); + return {}; + })(); }); - array.finish(); + TRY(result); + TRY(array.finish()); return {}; } }; @@ -634,9 +659,9 @@ private: ProcFSKeymap(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonObjectSerializer<KBufferBuilder> json { builder }; - json.add("keymap", HIDManagement::the().keymap_name()); - json.finish(); + auto json = TRY(JsonObjectSerializer<>::try_create(builder)); + TRY(json.add("keymap", HIDManagement::the().keymap_name())); + TRY(json.finish()); return {}; } }; @@ -650,22 +675,30 @@ private: ProcFSPCI(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - PCI::enumerate([&array](PCI::DeviceIdentifier const& device_identifier) { - auto obj = array.add_object(); - obj.add("domain", device_identifier.address().domain()); - obj.add("bus", device_identifier.address().bus()); - obj.add("device", device_identifier.address().device()); - obj.add("function", device_identifier.address().function()); - obj.add("vendor_id", device_identifier.hardware_id().vendor_id); - obj.add("device_id", device_identifier.hardware_id().device_id); - obj.add("revision_id", device_identifier.revision_id().value()); - obj.add("subclass", device_identifier.subclass_code().value()); - obj.add("class", device_identifier.class_code().value()); - obj.add("subsystem_id", device_identifier.subsystem_id().value()); - obj.add("subsystem_vendor_id", device_identifier.subsystem_vendor_id().value()); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + ErrorOr<void> result; // FIXME: Make this nicer + PCI::enumerate([&array, &result](PCI::DeviceIdentifier const& device_identifier) { + if (result.is_error()) + return; + result = ([&]() -> ErrorOr<void> { + auto obj = TRY(array.add_object()); + TRY(obj.add("domain", device_identifier.address().domain())); + TRY(obj.add("bus", device_identifier.address().bus())); + TRY(obj.add("device", device_identifier.address().device())); + TRY(obj.add("function", device_identifier.address().function())); + TRY(obj.add("vendor_id", device_identifier.hardware_id().vendor_id)); + TRY(obj.add("device_id", device_identifier.hardware_id().device_id)); + TRY(obj.add("revision_id", device_identifier.revision_id().value())); + TRY(obj.add("subclass", device_identifier.subclass_code().value())); + TRY(obj.add("class", device_identifier.class_code().value())); + TRY(obj.add("subsystem_id", device_identifier.subsystem_id().value())); + TRY(obj.add("subsystem_vendor_id", device_identifier.subsystem_vendor_id().value())); + TRY(obj.finish()); + return {}; + })(); }); - array.finish(); + TRY(result); + TRY(array.finish()); return {}; } }; @@ -678,21 +711,23 @@ private: ProcFSDevices(); virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override { - JsonArraySerializer array { builder }; - DeviceManagement::the().for_each([&array](auto& device) { - auto obj = array.add_object(); - obj.add("major", device.major().value()); - obj.add("minor", device.minor().value()); - obj.add("class_name", device.class_name()); + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(DeviceManagement::the().try_for_each([&array](auto& device) -> ErrorOr<void> { + auto obj = TRY(array.add_object()); + TRY(obj.add("major", device.major().value())); + TRY(obj.add("minor", device.minor().value())); + TRY(obj.add("class_name", device.class_name())); if (device.is_block_device()) - obj.add("type", "block"); + TRY(obj.add("type", "block")); else if (device.is_character_device()) - obj.add("type", "character"); + TRY(obj.add("type", "character")); else VERIFY_NOT_REACHED(); - }); - array.finish(); + TRY(obj.finish()); + return {}; + })); + TRY(array.finish()); return {}; } }; diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index 2799ee2ae9..8ef21aad18 100644 --- a/Kernel/PerformanceEventBuffer.cpp +++ b/Kernel/PerformanceEventBuffer.cpp @@ -198,14 +198,14 @@ template<typename Serializer> ErrorOr<void> PerformanceEventBuffer::to_json_impl(Serializer& object) const { { - auto strings = object.add_array("strings"); - for (auto const& it : m_strings) { - strings.add(it->view()); - } + auto strings = TRY(object.add_array("strings")); + for (auto const& it : m_strings) + TRY(strings.add(it->view())); + TRY(strings.finish()); } bool show_kernel_addresses = Process::current().is_superuser(); - auto array = object.add_array("events"); + auto array = TRY(object.add_array("events")); bool seen_first_sample = false; for (size_t i = 0; i < m_count; ++i) { auto const& event = at(i); @@ -215,109 +215,109 @@ ErrorOr<void> PerformanceEventBuffer::to_json_impl(Serializer& object) const continue; } - auto event_object = array.add_object(); + auto event_object = TRY(array.add_object()); switch (event.type) { case PERF_EVENT_SAMPLE: - event_object.add("type", "sample"); + TRY(event_object.add("type", "sample")); break; case PERF_EVENT_MALLOC: - event_object.add("type", "malloc"); - event_object.add("ptr", static_cast<u64>(event.data.malloc.ptr)); - event_object.add("size", static_cast<u64>(event.data.malloc.size)); + TRY(event_object.add("type", "malloc")); + TRY(event_object.add("ptr", static_cast<u64>(event.data.malloc.ptr))); + TRY(event_object.add("size", static_cast<u64>(event.data.malloc.size))); break; case PERF_EVENT_FREE: - event_object.add("type", "free"); - event_object.add("ptr", static_cast<u64>(event.data.free.ptr)); + TRY(event_object.add("type", "free")); + TRY(event_object.add("ptr", static_cast<u64>(event.data.free.ptr))); break; case PERF_EVENT_MMAP: - event_object.add("type", "mmap"); - event_object.add("ptr", static_cast<u64>(event.data.mmap.ptr)); - event_object.add("size", static_cast<u64>(event.data.mmap.size)); - event_object.add("name", event.data.mmap.name); + TRY(event_object.add("type", "mmap")); + TRY(event_object.add("ptr", static_cast<u64>(event.data.mmap.ptr))); + TRY(event_object.add("size", static_cast<u64>(event.data.mmap.size))); + TRY(event_object.add("name", event.data.mmap.name)); break; case PERF_EVENT_MUNMAP: - event_object.add("type", "munmap"); - event_object.add("ptr", static_cast<u64>(event.data.munmap.ptr)); - event_object.add("size", static_cast<u64>(event.data.munmap.size)); + TRY(event_object.add("type", "munmap")); + TRY(event_object.add("ptr", static_cast<u64>(event.data.munmap.ptr))); + TRY(event_object.add("size", static_cast<u64>(event.data.munmap.size))); break; case PERF_EVENT_PROCESS_CREATE: - event_object.add("type", "process_create"); - event_object.add("parent_pid", static_cast<u64>(event.data.process_create.parent_pid)); - event_object.add("executable", event.data.process_create.executable); + TRY(event_object.add("type", "process_create")); + TRY(event_object.add("parent_pid", static_cast<u64>(event.data.process_create.parent_pid))); + TRY(event_object.add("executable", event.data.process_create.executable)); break; case PERF_EVENT_PROCESS_EXEC: - event_object.add("type", "process_exec"); - event_object.add("executable", event.data.process_exec.executable); + TRY(event_object.add("type", "process_exec")); + TRY(event_object.add("executable", event.data.process_exec.executable)); break; case PERF_EVENT_PROCESS_EXIT: - event_object.add("type", "process_exit"); + TRY(event_object.add("type", "process_exit")); break; case PERF_EVENT_THREAD_CREATE: - event_object.add("type", "thread_create"); - event_object.add("parent_tid", static_cast<u64>(event.data.thread_create.parent_tid)); + TRY(event_object.add("type", "thread_create")); + TRY(event_object.add("parent_tid", static_cast<u64>(event.data.thread_create.parent_tid))); break; case PERF_EVENT_THREAD_EXIT: - event_object.add("type", "thread_exit"); + TRY(event_object.add("type", "thread_exit")); break; case PERF_EVENT_CONTEXT_SWITCH: - event_object.add("type", "context_switch"); - event_object.add("next_pid", static_cast<u64>(event.data.context_switch.next_pid)); - event_object.add("next_tid", static_cast<u64>(event.data.context_switch.next_tid)); + TRY(event_object.add("type", "context_switch")); + TRY(event_object.add("next_pid", static_cast<u64>(event.data.context_switch.next_pid))); + TRY(event_object.add("next_tid", static_cast<u64>(event.data.context_switch.next_tid))); break; case PERF_EVENT_KMALLOC: - event_object.add("type", "kmalloc"); - event_object.add("ptr", static_cast<u64>(event.data.kmalloc.ptr)); - event_object.add("size", static_cast<u64>(event.data.kmalloc.size)); + TRY(event_object.add("type", "kmalloc")); + TRY(event_object.add("ptr", static_cast<u64>(event.data.kmalloc.ptr))); + TRY(event_object.add("size", static_cast<u64>(event.data.kmalloc.size))); break; case PERF_EVENT_KFREE: - event_object.add("type", "kfree"); - event_object.add("ptr", static_cast<u64>(event.data.kfree.ptr)); - event_object.add("size", static_cast<u64>(event.data.kfree.size)); + TRY(event_object.add("type", "kfree")); + TRY(event_object.add("ptr", static_cast<u64>(event.data.kfree.ptr))); + TRY(event_object.add("size", static_cast<u64>(event.data.kfree.size))); break; case PERF_EVENT_PAGE_FAULT: - event_object.add("type", "page_fault"); + TRY(event_object.add("type", "page_fault")); break; case PERF_EVENT_SYSCALL: - event_object.add("type", "syscall"); + TRY(event_object.add("type", "syscall")); break; case PERF_EVENT_SIGNPOST: - event_object.add("type"sv, "signpost"sv); - event_object.add("arg1"sv, event.data.signpost.arg1); - event_object.add("arg2"sv, event.data.signpost.arg2); + TRY(event_object.add("type"sv, "signpost"sv)); + TRY(event_object.add("arg1"sv, event.data.signpost.arg1)); + TRY(event_object.add("arg2"sv, event.data.signpost.arg2)); break; case PERF_EVENT_READ: - event_object.add("type", "read"); - event_object.add("fd", event.data.read.fd); - event_object.add("size"sv, event.data.read.size); - event_object.add("filename_index"sv, event.data.read.filename_index); - event_object.add("start_timestamp"sv, event.data.read.start_timestamp); - event_object.add("success"sv, event.data.read.success); + TRY(event_object.add("type", "read")); + TRY(event_object.add("fd", event.data.read.fd)); + TRY(event_object.add("size"sv, event.data.read.size)); + TRY(event_object.add("filename_index"sv, event.data.read.filename_index)); + TRY(event_object.add("start_timestamp"sv, event.data.read.start_timestamp)); + TRY(event_object.add("success"sv, event.data.read.success)); break; } - event_object.add("pid", event.pid); - event_object.add("tid", event.tid); - event_object.add("timestamp", event.timestamp); - event_object.add("lost_samples", seen_first_sample ? event.lost_samples : 0); + TRY(event_object.add("pid", event.pid)); + TRY(event_object.add("tid", event.tid)); + TRY(event_object.add("timestamp", event.timestamp)); + TRY(event_object.add("lost_samples", seen_first_sample ? event.lost_samples : 0)); if (event.type == PERF_EVENT_SAMPLE) seen_first_sample = true; - auto stack_array = event_object.add_array("stack"); + auto stack_array = TRY(event_object.add_array("stack")); for (size_t j = 0; j < event.stack_size; ++j) { auto address = event.stack[j]; if (!show_kernel_addresses && !Memory::is_user_address(VirtualAddress { address })) address = 0xdeadc0de; - stack_array.add(address); + TRY(stack_array.add(address)); } - stack_array.finish(); - event_object.finish(); + TRY(stack_array.finish()); + TRY(event_object.finish()); } - array.finish(); - object.finish(); + TRY(array.finish()); + TRY(object.finish()); return {}; } ErrorOr<void> PerformanceEventBuffer::to_json(KBufferBuilder& builder) const { - JsonObjectSerializer object(builder); + auto object = TRY(JsonObjectSerializer<>::try_create(builder)); return to_json_impl(object); } diff --git a/Kernel/Process.h b/Kernel/Process.h index d1acc52d64..0d3773224d 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -488,12 +488,13 @@ public: Thread::WaitBlockerSet& wait_blocker_set() { return m_wait_blocker_set; } template<typename Callback> - void for_each_coredump_property(Callback callback) const + ErrorOr<void> for_each_coredump_property(Callback callback) const { for (auto const& property : m_coredump_properties) { if (property.key && property.value) - callback(*property.key, *property.value); + TRY(callback(*property.key, *property.value)); } + return {}; } ErrorOr<void> set_coredump_property(NonnullOwnPtr<KString> key, NonnullOwnPtr<KString> value); diff --git a/Kernel/ProcessSpecificExposed.cpp b/Kernel/ProcessSpecificExposed.cpp index 6189168d7d..c0db187b18 100644 --- a/Kernel/ProcessSpecificExposed.cpp +++ b/Kernel/ProcessSpecificExposed.cpp @@ -21,7 +21,7 @@ namespace Kernel { ErrorOr<void> Process::procfs_get_thread_stack(ThreadID thread_id, KBufferBuilder& builder) const { - JsonArraySerializer array { builder }; + auto array = TRY(JsonArraySerializer<>::try_create(builder)); auto thread = Thread::from_tid(thread_id); if (!thread) return ESRCH; @@ -34,10 +34,10 @@ ErrorOr<void> Process::procfs_get_thread_stack(ThreadID thread_id, KBufferBuilde address = 0xdeadc0de; kernel_address_added = true; } - array.add(address); + TRY(array.add(address)); } - array.finish(); + TRY(array.finish()); return {}; } @@ -125,31 +125,31 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_file_descriptions_directory(const ErrorOr<void> Process::procfs_get_pledge_stats(KBufferBuilder& builder) const { - JsonObjectSerializer obj { builder }; -#define __ENUMERATE_PLEDGE_PROMISE(x) \ - if (has_promised(Pledge::x)) { \ - if (!builder.is_empty()) \ - TRY(builder.try_append(' ')); \ - TRY(builder.try_append(#x)); \ + auto obj = TRY(JsonObjectSerializer<>::try_create(builder)); +#define __ENUMERATE_PLEDGE_PROMISE(x) \ + if (has_promised(Pledge::x)) { \ + if (!promises_builder.is_empty()) \ + TRY(promises_builder.try_append(' ')); \ + TRY(promises_builder.try_append(#x)); \ } if (has_promises()) { - StringBuilder builder; + StringBuilder promises_builder; ENUMERATE_PLEDGE_PROMISES - obj.add("promises", builder.string_view()); + TRY(obj.add("promises", promises_builder.string_view())); } #undef __ENUMERATE_PLEDGE_PROMISE - obj.finish(); + TRY(obj.finish()); return {}; } ErrorOr<void> Process::procfs_get_unveil_stats(KBufferBuilder& builder) const { - JsonArraySerializer array { builder }; - TRY(unveiled_paths().for_each_node_in_tree_order([&](auto const& unveiled_path) { + auto array = TRY(JsonArraySerializer<>::try_create(builder)); + TRY(unveiled_paths().for_each_node_in_tree_order([&](auto const& unveiled_path) -> ErrorOr<IterationDecision> { if (!unveiled_path.was_explicitly_unveiled()) - return; - auto obj = array.add_object(); - obj.add("path", unveiled_path.path()); + return IterationDecision::Continue; + auto obj = TRY(array.add_object()); + TRY(obj.add("path", unveiled_path.path())); StringBuilder permissions_builder; if (unveiled_path.permissions() & UnveilAccess::Read) permissions_builder.append('r'); @@ -161,9 +161,11 @@ ErrorOr<void> Process::procfs_get_unveil_stats(KBufferBuilder& builder) const permissions_builder.append('c'); if (unveiled_path.permissions() & UnveilAccess::Browse) permissions_builder.append('b'); - obj.add("permissions", permissions_builder.string_view()); + TRY(obj.add("permissions", permissions_builder.string_view())); + TRY(obj.finish()); + return IterationDecision::Continue; })); - array.finish(); + TRY(array.finish()); return {}; } @@ -179,76 +181,78 @@ ErrorOr<void> Process::procfs_get_perf_events(KBufferBuilder& builder) const ErrorOr<void> Process::procfs_get_fds_stats(KBufferBuilder& builder) const { - JsonArraySerializer array { builder }; + auto array = TRY(JsonArraySerializer<>::try_create(builder)); return fds().with_shared([&](auto& fds) -> ErrorOr<void> { if (fds.open_count() == 0) { - array.finish(); + TRY(array.finish()); return {}; } size_t count = 0; - fds.enumerate([&](auto& file_description_metadata) { + TRY(fds.try_enumerate([&](auto& file_description_metadata) -> ErrorOr<void> { if (!file_description_metadata.is_valid()) { count++; - return; + return {}; } bool cloexec = file_description_metadata.flags() & FD_CLOEXEC; RefPtr<OpenFileDescription> description = file_description_metadata.description(); - auto description_object = array.add_object(); - description_object.add("fd", count); + auto description_object = TRY(array.add_object()); + TRY(description_object.add("fd", count)); // TODO: Better OOM handling. auto pseudo_path_or_error = description->pseudo_path(); - description_object.add("absolute_path", pseudo_path_or_error.is_error() ? "???"sv : pseudo_path_or_error.value()->view()); - description_object.add("seekable", description->file().is_seekable()); - description_object.add("class", description->file().class_name()); - description_object.add("offset", description->offset()); - description_object.add("cloexec", cloexec); - description_object.add("blocking", description->is_blocking()); - description_object.add("can_read", description->can_read()); - description_object.add("can_write", description->can_write()); + TRY(description_object.add("absolute_path", pseudo_path_or_error.is_error() ? "???"sv : pseudo_path_or_error.value()->view())); + TRY(description_object.add("seekable", description->file().is_seekable())); + TRY(description_object.add("class", description->file().class_name())); + TRY(description_object.add("offset", description->offset())); + TRY(description_object.add("cloexec", cloexec)); + TRY(description_object.add("blocking", description->is_blocking())); + TRY(description_object.add("can_read", description->can_read())); + TRY(description_object.add("can_write", description->can_write())); Inode* inode = description->inode(); if (inode != nullptr) { - auto inode_object = description_object.add_object("inode"); - inode_object.add("fsid", inode->fsid().value()); - inode_object.add("index", inode->index().value()); - inode_object.finish(); + auto inode_object = TRY(description_object.add_object("inode")); + TRY(inode_object.add("fsid", inode->fsid().value())); + TRY(inode_object.add("index", inode->index().value())); + TRY(inode_object.finish()); } + TRY(description_object.finish()); count++; - }); + return {}; + })); - array.finish(); + TRY(array.finish()); return {}; }); } ErrorOr<void> Process::procfs_get_virtual_memory_stats(KBufferBuilder& builder) const { - JsonArraySerializer array { builder }; + auto array = TRY(JsonArraySerializer<>::try_create(builder)); { SpinlockLocker lock(address_space().get_lock()); for (auto const& region : address_space().regions()) { if (!region->is_user() && !Process::current().is_superuser()) continue; - auto region_object = array.add_object(); - region_object.add("readable", region->is_readable()); - region_object.add("writable", region->is_writable()); - region_object.add("executable", region->is_executable()); - region_object.add("stack", region->is_stack()); - region_object.add("shared", region->is_shared()); - region_object.add("syscall", region->is_syscall_region()); - region_object.add("purgeable", region->vmobject().is_anonymous()); + auto region_object = TRY(array.add_object()); + TRY(region_object.add("readable", region->is_readable())); + TRY(region_object.add("writable", region->is_writable())); + TRY(region_object.add("executable", region->is_executable())); + TRY(region_object.add("stack", region->is_stack())); + TRY(region_object.add("shared", region->is_shared())); + TRY(region_object.add("syscall", region->is_syscall_region())); + TRY(region_object.add("purgeable", region->vmobject().is_anonymous())); if (region->vmobject().is_anonymous()) { - region_object.add("volatile", static_cast<Memory::AnonymousVMObject const&>(region->vmobject()).is_volatile()); + TRY(region_object.add("volatile", static_cast<Memory::AnonymousVMObject const&>(region->vmobject()).is_volatile())); } - region_object.add("cacheable", region->is_cacheable()); - region_object.add("address", region->vaddr().get()); - region_object.add("size", region->size()); - region_object.add("amount_resident", region->amount_resident()); - region_object.add("amount_dirty", region->amount_dirty()); - region_object.add("cow_pages", region->cow_pages()); - region_object.add("name", region->name()); - region_object.add("vmobject", region->vmobject().class_name()); + TRY(region_object.add("cacheable", region->is_cacheable())); + TRY(region_object.add("address", region->vaddr().get())); + TRY(region_object.add("size", region->size())); + TRY(region_object.add("amount_resident", region->amount_resident())); + TRY(region_object.add("amount_dirty", region->amount_dirty())); + TRY(region_object.add("cow_pages", region->cow_pages())); + TRY(region_object.add("name", region->name())); + TRY(region_object.add("vmobject", region->vmobject().class_name())); StringBuilder pagemap_builder; for (size_t i = 0; i < region->page_count(); ++i) { @@ -260,10 +264,11 @@ ErrorOr<void> Process::procfs_get_virtual_memory_stats(KBufferBuilder& builder) else pagemap_builder.append('P'); } - region_object.add("pagemap", pagemap_builder.string_view()); + TRY(region_object.add("pagemap", pagemap_builder.string_view())); + TRY(region_object.finish()); } } - array.finish(); + TRY(array.finish()); return {}; } diff --git a/Userland/Applications/PixelPaint/Image.cpp b/Userland/Applications/PixelPaint/Image.cpp index c4ada542a7..9a28b60d4c 100644 --- a/Userland/Applications/PixelPaint/Image.cpp +++ b/Userland/Applications/PixelPaint/Image.cpp @@ -111,22 +111,22 @@ ErrorOr<NonnullRefPtr<Image>> Image::try_create_from_pixel_paint_json(JsonObject void Image::serialize_as_json(JsonObjectSerializer<StringBuilder>& json) const { - json.add("width", m_size.width()); - json.add("height", m_size.height()); + MUST(json.add("width", m_size.width())); + MUST(json.add("height", m_size.height())); { - auto json_layers = json.add_array("layers"); + auto json_layers = MUST(json.add_array("layers")); for (const auto& layer : m_layers) { Gfx::BMPWriter bmp_dumber; - auto json_layer = json_layers.add_object(); - json_layer.add("width", layer.size().width()); - json_layer.add("height", layer.size().height()); - json_layer.add("name", layer.name()); - json_layer.add("locationx", layer.location().x()); - json_layer.add("locationy", layer.location().y()); - json_layer.add("opacity_percent", layer.opacity_percent()); - json_layer.add("visible", layer.is_visible()); - json_layer.add("selected", layer.is_selected()); - json_layer.add("bitmap", encode_base64(bmp_dumber.dump(layer.bitmap()))); + auto json_layer = MUST(json_layers.add_object()); + MUST(json_layer.add("width", layer.size().width())); + MUST(json_layer.add("height", layer.size().height())); + MUST(json_layer.add("name", layer.name())); + MUST(json_layer.add("locationx", layer.location().x())); + MUST(json_layer.add("locationy", layer.location().y())); + MUST(json_layer.add("opacity_percent", layer.opacity_percent())); + MUST(json_layer.add("visible", layer.is_visible())); + MUST(json_layer.add("selected", layer.is_selected())); + MUST(json_layer.add("bitmap", encode_base64(bmp_dumber.dump(layer.bitmap())))); } } } @@ -134,9 +134,9 @@ void Image::serialize_as_json(JsonObjectSerializer<StringBuilder>& json) const ErrorOr<void> Image::write_to_file(const String& file_path) const { StringBuilder builder; - JsonObjectSerializer json(builder); + auto json = MUST(JsonObjectSerializer<>::try_create(builder)); serialize_as_json(json); - json.finish(); + MUST(json.finish()); auto file = TRY(Core::File::open(file_path, (Core::OpenMode)(Core::OpenMode::WriteOnly | Core::OpenMode::Truncate))); if (!file->write(builder.string_view())) diff --git a/Userland/Applications/PixelPaint/ImageEditor.cpp b/Userland/Applications/PixelPaint/ImageEditor.cpp index 5b2192ff52..3c3d87be17 100644 --- a/Userland/Applications/PixelPaint/ImageEditor.cpp +++ b/Userland/Applications/PixelPaint/ImageEditor.cpp @@ -602,20 +602,20 @@ void ImageEditor::save_project_as() Result<void, String> ImageEditor::save_project_to_file(Core::File& file) const { StringBuilder builder; - JsonObjectSerializer json(builder); + auto json = MUST(JsonObjectSerializer<>::try_create(builder)); m_image->serialize_as_json(json); - auto json_guides = json.add_array("guides"); + auto json_guides = MUST(json.add_array("guides")); for (const auto& guide : m_guides) { - auto json_guide = json_guides.add_object(); - json_guide.add("offset"sv, (double)guide.offset()); + auto json_guide = MUST(json_guides.add_object()); + MUST(json_guide.add("offset"sv, (double)guide.offset())); if (guide.orientation() == Guide::Orientation::Vertical) - json_guide.add("orientation", "vertical"); + MUST(json_guide.add("orientation", "vertical")); else if (guide.orientation() == Guide::Orientation::Horizontal) - json_guide.add("orientation", "horizontal"); - json_guide.finish(); + MUST(json_guide.add("orientation", "horizontal")); + MUST(json_guide.finish()); } - json_guides.finish(); - json.finish(); + MUST(json_guides.finish()); + MUST(json.finish()); if (!file.write(builder.string_view())) return String { file.error_string() }; diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 95cc0ffe88..46ec48a9ac 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -1185,10 +1185,10 @@ void Document::set_cookie(String const& cookie_string, Cookie::Source source) String Document::dump_dom_tree_as_json() const { StringBuilder builder; - JsonObjectSerializer json(builder); + auto json = MUST(JsonObjectSerializer<>::try_create(builder)); serialize_tree_as_json(json); - json.finish(); + MUST(json.finish()); return builder.to_string(); } diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index a20c94011e..4676ef44b6 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -723,47 +723,52 @@ bool Node::is_uninteresting_whitespace_node() const void Node::serialize_tree_as_json(JsonObjectSerializer<StringBuilder>& object) const { - object.add("name", node_name().view()); - object.add("id", id()); + MUST(object.add("name", node_name().view())); + MUST(object.add("id", id())); if (is_document()) { - object.add("type", "document"); + MUST(object.add("type", "document")); } else if (is_element()) { - object.add("type", "element"); + MUST(object.add("type", "element")); auto const* element = static_cast<DOM::Element const*>(this); if (element->has_attributes()) { - auto attributes = object.add_object("attributes"); + auto attributes = MUST(object.add_object("attributes")); element->for_each_attribute([&attributes](auto& name, auto& value) { - attributes.add(name, value); + MUST(attributes.add(name, value)); }); + MUST(attributes.finish()); } if (element->is_browsing_context_container()) { auto const* container = static_cast<HTML::BrowsingContextContainer const*>(element); if (auto const* content_document = container->content_document()) { - auto children = object.add_array("children"); - JsonObjectSerializer<StringBuilder> content_document_object = children.add_object(); + auto children = MUST(object.add_array("children")); + JsonObjectSerializer<StringBuilder> content_document_object = MUST(children.add_object()); content_document->serialize_tree_as_json(content_document_object); + MUST(content_document_object.finish()); + MUST(children.finish()); } } } else if (is_text()) { - object.add("type", "text"); + MUST(object.add("type", "text")); auto text_node = static_cast<DOM::Text const*>(this); - object.add("text", text_node->data()); + MUST(object.add("text", text_node->data())); } else if (is_comment()) { - object.add("type"sv, "comment"sv); - object.add("data"sv, static_cast<DOM::Comment const&>(*this).data()); + MUST(object.add("type"sv, "comment"sv)); + MUST(object.add("data"sv, static_cast<DOM::Comment const&>(*this).data())); } if (has_child_nodes()) { - auto children = object.add_array("children"); + auto children = MUST(object.add_array("children")); for_each_child([&children](DOM::Node& child) { if (child.is_uninteresting_whitespace_node()) return; - JsonObjectSerializer<StringBuilder> child_object = children.add_object(); + JsonObjectSerializer<StringBuilder> child_object = MUST(children.add_object()); child.serialize_tree_as_json(child_object); + MUST(child_object.finish()); }); + MUST(children.finish()); } } diff --git a/Userland/Services/LaunchServer/Launcher.cpp b/Userland/Services/LaunchServer/Launcher.cpp index b413561c2a..09fa6d496b 100644 --- a/Userland/Services/LaunchServer/Launcher.cpp +++ b/Userland/Services/LaunchServer/Launcher.cpp @@ -45,23 +45,23 @@ void Handler::from_executable(Type handler_type, const String& executable) String Handler::to_details_str() const { StringBuilder builder; - JsonObjectSerializer obj { builder }; - obj.add("executable", executable); - obj.add("name", name); + auto obj = MUST(JsonObjectSerializer<>::try_create(builder)); + MUST(obj.add("executable", executable)); + MUST(obj.add("name", name)); switch (handler_type) { case Type::Application: - obj.add("type", "app"); + MUST(obj.add("type", "app")); break; case Type::UserDefault: - obj.add("type", "userdefault"); + MUST(obj.add("type", "userdefault")); break; case Type::UserPreferred: - obj.add("type", "userpreferred"); + MUST(obj.add("type", "userpreferred")); break; default: break; } - obj.finish(); + MUST(obj.finish()); return builder.build(); } diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 6e01c5e0a7..d9a52631b1 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -271,18 +271,18 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect auto serialize_json = [](Web::CSS::StyleProperties const& properties) -> String { StringBuilder builder; - JsonObjectSerializer serializer(builder); + auto serializer = MUST(JsonObjectSerializer<>::try_create(builder)); properties.for_each_property([&](auto property_id, auto& value) { - serializer.add(Web::CSS::string_from_property_id(property_id), value.to_string()); + MUST(serializer.add(Web::CSS::string_from_property_id(property_id), value.to_string())); }); - serializer.finish(); + MUST(serializer.finish()); return builder.to_string(); }; auto serialize_custom_properties_json = [](Web::DOM::Element const& element) -> String { StringBuilder builder; - JsonObjectSerializer serializer(builder); + auto serializer = MUST(JsonObjectSerializer<>::try_create(builder)); HashTable<String> seen_properties; auto const* element_to_check = &element; @@ -290,14 +290,14 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect for (auto const& property : element_to_check->custom_properties()) { if (!seen_properties.contains(property.key)) { seen_properties.set(property.key); - serializer.add(property.key, property.value.value->to_string()); + MUST(serializer.add(property.key, property.value.value->to_string())); } } element_to_check = element_to_check->parent_element(); } - serializer.finish(); + MUST(serializer.finish()); return builder.to_string(); }; |