Forráskód Böngészése

LibCore+Userland: Make Promise's on_resolve fallible

This will be primarily necessary for BackgroundAction integration, but
it already allows us to add proper error handling in LibIMAP :^)
kleines Filmröllchen 2 éve
szülő
commit
8f4d0d3797

+ 2 - 2
Userland/Applications/Browser/CookieJar.cpp

@@ -571,10 +571,10 @@ void CookieJar::select_all_cookies_from_database(OnSelectAllCookiesResult on_res
                 on_result(cookie.release_value());
         },
         [&]() {
-            promise->resolve({});
+            MUST(promise->resolve({}));
         },
         [&](auto) {
-            promise->resolve({});
+            MUST(promise->resolve({}));
         });
 
     MUST(promise->await());

+ 6 - 4
Userland/Libraries/LibCore/Promise.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2021, Kyle Pereira <hey@xylepereira.me>
+ * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -16,14 +17,15 @@ class Promise : public Object {
     C_OBJECT(Promise);
 
 public:
-    Function<void(Result&)> on_resolved;
+    Function<ErrorOr<void>(Result&)> on_resolved;
 
-    void resolve(Result&& result)
+    ErrorOr<void> resolve(Result&& result)
     {
         m_pending_or_error = move(result);
 
         if (on_resolved)
-            on_resolved(m_pending_or_error.value());
+            return on_resolved(m_pending_or_error->value());
+        return {};
     }
 
     void cancel(Error error)
@@ -56,7 +58,7 @@ public:
         RefPtr<Promise<T>> new_promise = Promise<T>::construct();
         on_resolved = [new_promise, func](Result& result) {
             auto t = func(result);
-            new_promise->resolve(move(t));
+            return new_promise->resolve(move(t));
         };
         return new_promise;
     }

+ 5 - 5
Userland/Libraries/LibFileSystemAccessClient/Client.cpp

@@ -124,19 +124,19 @@ void Client::handle_prompt_end(i32 request_id, i32 error, Optional<IPC::File> co
         // to handle it as opening a new, named file.
         if (error != -1 && error != ENOENT)
             GUI::MessageBox::show_error(request_data.parent_window, DeprecatedString::formatted("Opening \"{}\" failed: {}", *chosen_file, strerror(error)));
-        request_data.promise->resolve(Error::from_errno(error));
+        request_data.promise->resolve(Error::from_errno(error)).release_value_but_fixme_should_propagate_errors();
         return;
     }
 
     if (Core::DeprecatedFile::is_device(ipc_file->fd())) {
         GUI::MessageBox::show_error(request_data.parent_window, DeprecatedString::formatted("Opening \"{}\" failed: Cannot open device files", *chosen_file));
-        request_data.promise->resolve(Error::from_string_literal("Cannot open device files"));
+        request_data.promise->resolve(Error::from_string_literal("Cannot open device files")).release_value_but_fixme_should_propagate_errors();
         return;
     }
 
     if (Core::DeprecatedFile::is_directory(ipc_file->fd())) {
         GUI::MessageBox::show_error(request_data.parent_window, DeprecatedString::formatted("Opening \"{}\" failed: Cannot open directory", *chosen_file));
-        request_data.promise->resolve(Error::from_errno(EISDIR));
+        request_data.promise->resolve(Error::from_errno(EISDIR)).release_value_but_fixme_should_propagate_errors();
         return;
     }
 
@@ -146,11 +146,11 @@ void Client::handle_prompt_end(i32 request_id, i32 error, Optional<IPC::File> co
         return File({}, move(stream), filename);
     }();
     if (file_or_error.is_error()) {
-        request_data.promise->resolve(file_or_error.release_error());
+        request_data.promise->resolve(file_or_error.release_error()).release_value_but_fixme_should_propagate_errors();
         return;
     }
 
-    request_data.promise->resolve(file_or_error.release_value());
+    request_data.promise->resolve(file_or_error.release_value()).release_value_but_fixme_should_propagate_errors();
 }
 
 void Client::die()

+ 7 - 6
Userland/Libraries/LibIMAP/Client.cpp

@@ -64,7 +64,7 @@ ErrorOr<void> Client::on_ready_to_receive()
 
     // Once we get server hello we can start sending.
     if (m_connect_pending) {
-        m_connect_pending->resolve({});
+        TRY(m_connect_pending->resolve({}));
         m_connect_pending.clear();
         m_buffer.clear();
         return {};
@@ -227,13 +227,13 @@ ErrorOr<void> Client::handle_parsed_response(ParseStatus&& parse_status)
         bool should_send_next = false;
         if (!parse_status.successful) {
             m_expecting_response = false;
-            m_pending_promises.first()->resolve({});
+            TRY(m_pending_promises.first()->resolve({}));
             m_pending_promises.remove(0);
         }
         if (parse_status.response.has_value()) {
             m_expecting_response = false;
             should_send_next = parse_status.response->has<SolidResponse>();
-            m_pending_promises.first()->resolve(move(parse_status.response));
+            TRY(m_pending_promises.first()->resolve(move(parse_status.response)));
             m_pending_promises.remove(0);
         }
 
@@ -386,13 +386,14 @@ RefPtr<Promise<Optional<SolidResponse>>> Client::append(StringView mailbox, Mess
     auto response_promise = Promise<Optional<Response>>::construct();
     m_pending_promises.append(response_promise);
 
-    continue_req->on_resolved = [this, message2 { move(message) }](auto& data) {
+    continue_req->on_resolved = [this, message2 { move(message) }](auto& data) -> ErrorOr<void> {
         if (!data.has_value()) {
-            MUST(handle_parsed_response({ .successful = false, .response = {} }));
+            TRY(handle_parsed_response({ .successful = false, .response = {} }));
         } else {
-            MUST(send_raw(message2.data));
+            TRY(send_raw(message2.data));
             m_expecting_response = true;
         }
+        return {};
     };
 
     return cast_promise<SolidResponse>(response_promise);

+ 4 - 3
Userland/Services/WebDriver/Session.cpp

@@ -42,7 +42,8 @@ ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<S
     server->on_accept = [this, promise](auto client_socket) {
         auto maybe_connection = adopt_nonnull_ref_or_enomem(new (nothrow) WebContentConnection(move(client_socket), m_client, session_id()));
         if (maybe_connection.is_error()) {
-            promise->resolve(maybe_connection.release_error());
+            // Use of MUST in this function is safe, as our promise callback can never error out.
+            MUST(promise->resolve(maybe_connection.release_error()));
             return;
         }
 
@@ -56,11 +57,11 @@ ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<S
         if (m_current_window_handle.is_empty())
             m_current_window_handle = handle_name;
 
-        promise->resolve({});
+        MUST(promise->resolve({}));
     };
 
     server->on_accept_error = [promise](auto error) {
-        promise->resolve(move(error));
+        MUST(promise->resolve(move(error)));
     };
 
     return server;