| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-03-03 18:04:58 +00:00
										 |  |  |  * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <AK/NonnullRefPtr.h>
 | 
					
						
							|  |  |  | #include <AK/Optional.h>
 | 
					
						
							|  |  |  | #include <AK/RefPtr.h>
 | 
					
						
							| 
									
										
										
										
											2022-09-25 17:52:27 +01:00
										 |  |  | #include <LibJS/Runtime/Completion.h>
 | 
					
						
							| 
									
										
										
										
											2022-09-25 17:28:46 +01:00
										 |  |  | #include <LibWeb/WebIDL/DOMException.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-25 17:03:42 +01:00
										 |  |  | namespace Web::WebIDL { | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  | #define ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E) \
 | 
					
						
							|  |  |  |     E(EvalError)                                   \ | 
					
						
							|  |  |  |     E(RangeError)                                  \ | 
					
						
							|  |  |  |     E(ReferenceError)                              \ | 
					
						
							|  |  |  |     E(TypeError)                                   \ | 
					
						
							|  |  |  |     E(URIError) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define E(x) x,
 | 
					
						
							|  |  |  | enum class SimpleExceptionType { | 
					
						
							|  |  |  |     ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | #undef E
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct SimpleException { | 
					
						
							|  |  |  |     SimpleExceptionType type; | 
					
						
							| 
									
										
										
										
											2023-03-03 18:04:58 +00:00
										 |  |  |     Variant<String, StringView> message; | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | using Exception = Variant<SimpleException, GC::Ref<DOMException>, JS::Completion>; | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | template<typename ValueType> | 
					
						
							| 
									
										
										
										
											2022-10-30 17:50:52 +00:00
										 |  |  | class [[nodiscard]] ExceptionOr { | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2022-10-17 00:06:11 +02:00
										 |  |  |     ExceptionOr() | 
					
						
							|  |  |  |     requires(IsSame<ValueType, Empty>) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(Empty {}) | 
					
						
							| 
									
										
										
										
											2022-03-22 07:44:33 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 |  |  |     ExceptionOr(ValueType const& result) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(result) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ExceptionOr(ValueType&& result) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(move(result)) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-25 19:11:43 +01:00
										 |  |  |     // Allows implicit construction of ExceptionOr<T> from a type U if T(U) is a supported constructor.
 | 
					
						
							|  |  |  |     // Most commonly: Value from Object* or similar, so we can omit the curly braces from "return { TRY(...) };".
 | 
					
						
							|  |  |  |     // Disabled for POD types to avoid weird conversion shenanigans.
 | 
					
						
							|  |  |  |     template<typename WrappedValueType> | 
					
						
							| 
									
										
										
										
											2022-10-17 00:06:11 +02:00
										 |  |  |     ExceptionOr(WrappedValueType result) | 
					
						
							|  |  |  |     requires(!IsPOD<ValueType>) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(ValueType { move(result) }) | 
					
						
							| 
									
										
										
										
											2022-09-25 19:11:43 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  |     ExceptionOr(GC::Ref<DOMException> exception) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(exception) | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ExceptionOr(SimpleException exception) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(move(exception)) | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-25 17:52:27 +01:00
										 |  |  |     ExceptionOr(JS::Completion exception) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(move(exception)) | 
					
						
							| 
									
										
										
										
											2022-09-25 17:52:27 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         auto const& completion = m_result_or_exception.template get<JS::Completion>(); | 
					
						
							| 
									
										
										
										
											2022-09-25 17:52:27 +01:00
										 |  |  |         VERIFY(completion.is_error()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  |     ExceptionOr(Exception exception) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         : m_result_or_exception(move(exception)) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         if (auto* completion = m_result_or_exception.template get_pointer<JS::Completion>()) | 
					
						
							| 
									
										
										
										
											2022-09-25 17:52:27 +01:00
										 |  |  |             VERIFY(completion->is_error()); | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ExceptionOr(ExceptionOr&& other) = default; | 
					
						
							| 
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 |  |  |     ExceptionOr(ExceptionOr const& other) = default; | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     ~ExceptionOr() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-17 00:06:11 +02:00
										 |  |  |     ValueType& value() | 
					
						
							|  |  |  |     requires(!IsSame<ValueType, Empty>) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         return m_result_or_exception.template get<ValueType>(); | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 07:44:33 -04:00
										 |  |  |     ValueType release_value() | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         return move(m_result_or_exception.template get<ValueType>()); | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  |     Exception exception() const | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  |         return m_result_or_exception.template downcast<SimpleException, GC::Ref<DOMException>, JS::Completion>(); | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     bool is_exception() const | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-01 15:06:27 -05:00
										 |  |  |         return !m_result_or_exception.template has<ValueType>(); | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-13 20:54:55 +01:00
										 |  |  |     ValueType release_value_but_fixme_should_propagate_errors() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         VERIFY(!is_error()); | 
					
						
							|  |  |  |         return release_value(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 07:44:33 -04:00
										 |  |  |     // These are for compatibility with the TRY() macro in AK.
 | 
					
						
							|  |  |  |     [[nodiscard]] bool is_error() const { return is_exception(); } | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  |     Exception release_error() { return exception(); } | 
					
						
							| 
									
										
										
										
											2022-03-22 07:44:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-10-11 13:15:16 +01:00
										 |  |  |     // https://webidl.spec.whatwg.org/#idl-exceptions
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  |     Variant<ValueType, SimpleException, GC::Ref<DOMException>, JS::Completion> m_result_or_exception; | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> | 
					
						
							| 
									
										
										
										
											2022-10-30 17:50:52 +00:00
										 |  |  | class [[nodiscard]] ExceptionOr<void> : public ExceptionOr<Empty> { | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-27 00:17:13 +04:30
										 |  |  |     using ExceptionOr<Empty>::ExceptionOr; | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:00 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-01-22 12:08:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace AK { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> | 
					
						
							|  |  |  | struct Formatter<Web::WebIDL::SimpleException> : Formatter<StringView> { | 
					
						
							|  |  |  |     ErrorOr<void> format(FormatBuilder& builder, Web::WebIDL::SimpleException const& exception) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto message_view = exception.message.visit( | 
					
						
							|  |  |  |             [](String const& message) -> StringView { | 
					
						
							|  |  |  |                 return message.bytes_as_string_view(); | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             [](StringView message) -> StringView { | 
					
						
							|  |  |  |                 return message; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return Formatter<StringView>::format(builder, message_view); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> | 
					
						
							|  |  |  | struct Formatter<Web::WebIDL::Exception> : Formatter<FormatString> { | 
					
						
							|  |  |  |     ErrorOr<void> format(FormatBuilder& builder, Web::WebIDL::Exception const& exception) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return exception.visit( | 
					
						
							|  |  |  |             [&](Web::WebIDL::SimpleException const& simple_exception) -> ErrorOr<void> { | 
					
						
							|  |  |  |                 return Formatter<FormatString>::format(builder, "{}"sv, simple_exception); | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             [&](GC::Ref<Web::WebIDL::DOMException> const& dom_exception) -> ErrorOr<void> { | 
					
						
							|  |  |  |                 return Formatter<FormatString>::format(builder, "{}"sv, *dom_exception); | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             [&](JS::Completion const& completion) -> ErrorOr<void> { | 
					
						
							|  |  |  |                 VERIFY(completion.is_error()); | 
					
						
							|  |  |  |                 auto value = *completion.value(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (value.is_object()) { | 
					
						
							|  |  |  |                     auto& object = value.as_object(); | 
					
						
							|  |  |  |                     static const JS::PropertyKey message_property_key { "message" }; | 
					
						
							|  |  |  |                     auto has_message_or_error = object.has_own_property(message_property_key); | 
					
						
							|  |  |  |                     if (!has_message_or_error.is_error() && has_message_or_error.value()) { | 
					
						
							|  |  |  |                         auto message_object = object.get_without_side_effects(message_property_key); | 
					
						
							|  |  |  |                         return Formatter<StringView>::format(builder, message_object.to_string_without_side_effects()); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return Formatter<StringView>::format(builder, value.to_string_without_side_effects()); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |