ExceptionOr.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2021, 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 <LibWeb/DOM/DOMException.h>
  11. namespace Web::DOM {
  12. #define ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E) \
  13. E(EvalError) \
  14. E(RangeError) \
  15. E(ReferenceError) \
  16. E(TypeError) \
  17. E(URIError)
  18. #define E(x) x,
  19. enum class SimpleExceptionType {
  20. ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E)
  21. };
  22. #undef E
  23. struct SimpleException {
  24. SimpleExceptionType type;
  25. String message;
  26. };
  27. template<typename ValueType>
  28. class ExceptionOr {
  29. public:
  30. ExceptionOr() requires(IsSame<ValueType, Empty>) = default;
  31. ExceptionOr(const ValueType& result)
  32. : m_result(result)
  33. {
  34. }
  35. ExceptionOr(ValueType&& result)
  36. : m_result(move(result))
  37. {
  38. }
  39. ExceptionOr(NonnullRefPtr<DOMException> exception)
  40. : m_exception(move(exception))
  41. {
  42. }
  43. ExceptionOr(SimpleException exception)
  44. : m_exception(move(exception))
  45. {
  46. }
  47. ExceptionOr(Variant<SimpleException, NonnullRefPtr<DOMException>> exception)
  48. : m_exception(move(exception).template downcast<Empty, SimpleException, NonnullRefPtr<DOMException>>())
  49. {
  50. }
  51. ExceptionOr(ExceptionOr&& other) = default;
  52. ExceptionOr(const ExceptionOr& other) = default;
  53. ~ExceptionOr() = default;
  54. ValueType& value() requires(!IsSame<ValueType, Empty>)
  55. {
  56. return m_result.value();
  57. }
  58. ValueType release_value() requires(!IsSame<ValueType, Empty>)
  59. {
  60. return m_result.release_value();
  61. }
  62. Variant<SimpleException, NonnullRefPtr<DOMException>> exception() const
  63. {
  64. return m_exception.template downcast<SimpleException, NonnullRefPtr<DOMException>>();
  65. }
  66. auto materialized_exception(JS::GlobalObject& global_object) const
  67. {
  68. #define E(x) JS::x*,
  69. using ResultType = Variant<ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E) NonnullRefPtr<DOMException>>;
  70. #undef E
  71. return m_exception.visit(
  72. [&](SimpleException& exception) -> ResultType {
  73. switch (exception.type) {
  74. #define E(x) \
  75. case SimpleExceptionType::x: \
  76. return JS::x::create(global_object, exception.message);
  77. ENUMERATE_SIMPLE_WEBIDL_EXCEPTION_TYPES(E)
  78. #undef E
  79. default:
  80. VERIFY_NOT_REACHED();
  81. }
  82. },
  83. [&](NonnullRefPtr<DOMException> const& exception) -> ResultType { return exception; },
  84. [](Empty) -> ResultType { VERIFY_NOT_REACHED(); });
  85. }
  86. bool is_exception() const
  87. {
  88. return !m_exception.template has<Empty>();
  89. }
  90. private:
  91. Optional<ValueType> m_result;
  92. // https://heycam.github.io/webidl/#idl-exceptions
  93. Variant<Empty, SimpleException, NonnullRefPtr<DOMException>> m_exception { Empty {} };
  94. };
  95. template<>
  96. class ExceptionOr<void> : public ExceptionOr<Empty> {
  97. public:
  98. using ExceptionOr<Empty>::ExceptionOr;
  99. };
  100. }