Procházet zdrojové kódy

LibWeb: Support plain (throw) JS::Completion in WebIDL::ExceptionOr

This makes it possible to propagate exceptions from a function that
returns JS::ThrowCompletionOr via TRY() in another function that returns
WebIDL::ExceptionOr.
Linus Groh před 2 roky
rodič
revize
4461234898

+ 4 - 1
Userland/Libraries/LibWeb/Bindings/ExceptionOrUtils.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, the SerenityOS developers.
+ * Copyright (c) 2021-2022, the SerenityOS developers.
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -75,6 +75,9 @@ ALWAYS_INLINE JS::Completion dom_exception_to_throw_completion(auto&& vm, auto&&
         },
         [&](JS::NonnullGCPtr<WebIDL::DOMException> const& exception) {
             return throw_completion(exception);
+        },
+        [&](JS::Completion const& completion) {
+            return completion;
         });
 }
 

+ 16 - 6
Userland/Libraries/LibWeb/WebIDL/ExceptionOr.h

@@ -9,6 +9,7 @@
 #include <AK/NonnullRefPtr.h>
 #include <AK/Optional.h>
 #include <AK/RefPtr.h>
+#include <LibJS/Runtime/Completion.h>
 #include <LibWeb/WebIDL/DOMException.h>
 
 namespace Web::WebIDL {
@@ -59,9 +60,18 @@ public:
     {
     }
 
-    ExceptionOr(Variant<SimpleException, JS::NonnullGCPtr<DOMException>> exception)
-        : m_exception(move(exception).template downcast<Empty, SimpleException, JS::NonnullGCPtr<DOMException>>())
+    ExceptionOr(JS::Completion exception)
+        : m_exception(move(exception))
+    {
+        auto const& completion = m_exception.get<JS::Completion>();
+        VERIFY(completion.is_error());
+    }
+
+    ExceptionOr(Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> exception)
+        : m_exception(move(exception).template downcast<Empty, SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion>())
     {
+        if (auto* completion = m_exception.template get_pointer<JS::Completion>())
+            VERIFY(completion->is_error());
     }
 
     ExceptionOr(ExceptionOr&& other) = default;
@@ -78,9 +88,9 @@ public:
         return m_result.release_value();
     }
 
-    Variant<SimpleException, JS::NonnullGCPtr<DOMException>> exception() const
+    Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> exception() const
     {
-        return m_exception.template downcast<SimpleException, JS::NonnullGCPtr<DOMException>>();
+        return m_exception.template downcast<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion>();
     }
 
     bool is_exception() const
@@ -90,13 +100,13 @@ public:
 
     // These are for compatibility with the TRY() macro in AK.
     [[nodiscard]] bool is_error() const { return is_exception(); }
-    Variant<SimpleException, JS::NonnullGCPtr<DOMException>> release_error() { return exception(); }
+    Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> release_error() { return exception(); }
 
 private:
     Optional<ValueType> m_result;
 
     // https://webidl.spec.whatwg.org/#idl-exceptions
-    Variant<Empty, SimpleException, JS::NonnullGCPtr<DOMException>> m_exception {};
+    Variant<Empty, SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> m_exception {};
 };
 
 template<>