diff --git a/Libraries/LibJS/Runtime/Completion.h b/Libraries/LibJS/Runtime/Completion.h index 0650a7feb5b..7d8ca4f739b 100644 --- a/Libraries/LibJS/Runtime/Completion.h +++ b/Libraries/LibJS/Runtime/Completion.h @@ -298,9 +298,41 @@ private: }; template<> -class [[nodiscard]] ThrowCompletionOr : public ThrowCompletionOr { +class [[nodiscard]] ThrowCompletionOr { public: - using ThrowCompletionOr::ThrowCompletionOr; + ALWAYS_INLINE ThrowCompletionOr() + : m_value(js_special_empty_value()) + { + } + + ALWAYS_INLINE ThrowCompletionOr(Empty) + : m_value(js_special_empty_value()) + { + } + + // Not `explicit` on purpose so that `return vm.throw_completion(...);` is possible. + ALWAYS_INLINE ThrowCompletionOr(Completion throw_completion) + : m_value(throw_completion.release_error().value()) + { + } + + ALWAYS_INLINE ThrowCompletionOr(ThrowCompletionOr const&) = default; + ALWAYS_INLINE ThrowCompletionOr& operator=(ThrowCompletionOr const&) = default; + ALWAYS_INLINE ThrowCompletionOr(ThrowCompletionOr&&) = default; + ALWAYS_INLINE ThrowCompletionOr& operator=(ThrowCompletionOr&&) = default; + + [[nodiscard]] bool is_throw_completion() const { return !m_value.is_special_empty_value(); } + [[nodiscard]] Completion throw_completion() const { return error(); } + [[nodiscard]] Value error_value() const { return m_value; } + + // These are for compatibility with the TRY() macro in AK. + [[nodiscard]] bool is_error() const { return !m_value.is_special_empty_value(); } + Empty release_value() { return {}; } + Completion error() const { return Completion { Completion::Type::Throw, m_value }; } + Completion release_error() { return error(); } + +private: + Value m_value; }; ThrowCompletionOr await(VM&, Value);