ExceptionOr.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/NonnullRefPtr.h>
  8. #include <AK/Optional.h>
  9. #include <AK/RefPtr.h>
  10. #include <LibJS/Runtime/Completion.h>
  11. #include <LibWeb/WebIDL/DOMException.h>
  12. namespace Web::WebIDL {
  13. #define ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E) \
  14. E(EvalError) \
  15. E(RangeError) \
  16. E(ReferenceError) \
  17. E(TypeError) \
  18. E(URIError)
  19. #define E(x) x,
  20. enum class SimpleExceptionType {
  21. ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E)
  22. };
  23. #undef E
  24. struct SimpleException {
  25. SimpleExceptionType type;
  26. String message;
  27. };
  28. template<typename ValueType>
  29. class ExceptionOr {
  30. public:
  31. ExceptionOr() requires(IsSame<ValueType, Empty>)
  32. : m_result(Empty {})
  33. {
  34. }
  35. ExceptionOr(ValueType const& result)
  36. : m_result(result)
  37. {
  38. }
  39. ExceptionOr(ValueType&& result)
  40. : m_result(move(result))
  41. {
  42. }
  43. // Allows implicit construction of ExceptionOr<T> from a type U if T(U) is a supported constructor.
  44. // Most commonly: Value from Object* or similar, so we can omit the curly braces from "return { TRY(...) };".
  45. // Disabled for POD types to avoid weird conversion shenanigans.
  46. template<typename WrappedValueType>
  47. ExceptionOr(WrappedValueType result) requires(!IsPOD<ValueType>)
  48. : m_result(move(result))
  49. {
  50. }
  51. ExceptionOr(JS::NonnullGCPtr<DOMException> exception)
  52. : m_exception(move(exception))
  53. {
  54. }
  55. ExceptionOr(SimpleException exception)
  56. : m_exception(move(exception))
  57. {
  58. }
  59. ExceptionOr(JS::Completion exception)
  60. : m_exception(move(exception))
  61. {
  62. auto const& completion = m_exception.get<JS::Completion>();
  63. VERIFY(completion.is_error());
  64. }
  65. ExceptionOr(Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> exception)
  66. : m_exception(move(exception).template downcast<Empty, SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion>())
  67. {
  68. if (auto* completion = m_exception.template get_pointer<JS::Completion>())
  69. VERIFY(completion->is_error());
  70. }
  71. ExceptionOr(ExceptionOr&& other) = default;
  72. ExceptionOr(ExceptionOr const& other) = default;
  73. ~ExceptionOr() = default;
  74. ValueType& value() requires(!IsSame<ValueType, Empty>)
  75. {
  76. return m_result.value();
  77. }
  78. ValueType release_value()
  79. {
  80. return m_result.release_value();
  81. }
  82. Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> exception() const
  83. {
  84. return m_exception.template downcast<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion>();
  85. }
  86. bool is_exception() const
  87. {
  88. return !m_exception.template has<Empty>();
  89. }
  90. // These are for compatibility with the TRY() macro in AK.
  91. [[nodiscard]] bool is_error() const { return is_exception(); }
  92. Variant<SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> release_error() { return exception(); }
  93. private:
  94. Optional<ValueType> m_result;
  95. // https://webidl.spec.whatwg.org/#idl-exceptions
  96. Variant<Empty, SimpleException, JS::NonnullGCPtr<DOMException>, JS::Completion> m_exception {};
  97. };
  98. template<>
  99. class ExceptionOr<void> : public ExceptionOr<Empty> {
  100. public:
  101. using ExceptionOr<Empty>::ExceptionOr;
  102. };
  103. }