diff --git a/Userland/Libraries/LibJS/Runtime/Value.h b/Userland/Libraries/LibJS/Runtime/Value.h index 6bcbdeb6ac..b23aa93eb0 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.h +++ b/Userland/Libraries/LibJS/Runtime/Value.h @@ -433,6 +433,110 @@ inline bool Value::operator==(Value const& value) const { return same_value(*thi namespace AK { +template<> +class Optional { + template + friend class Optional; + +public: + using ValueType = JS::Value; + + Optional() = default; + + Optional(Optional const& other) + { + if (other.has_value()) + m_value = other.m_value; + } + + Optional(Optional&& other) + : m_value(other.m_value) + { + } + + template + explicit(!IsConvertible) Optional(U&& value) requires(!IsSame, Optional> && IsConstructible) + : m_value(forward(value)) + { + } + + Optional& operator=(Optional const& other) + { + if (this != &other) { + clear(); + m_value = other.m_value; + } + return *this; + } + + Optional& operator=(Optional&& other) + { + if (this != &other) { + clear(); + m_value = other.m_value; + } + return *this; + } + + void clear() + { + m_value = {}; + } + + [[nodiscard]] bool has_value() const + { + return !m_value.is_empty(); + } + + [[nodiscard]] JS::Value& value() & + { + VERIFY(has_value()); + return m_value; + } + + [[nodiscard]] JS::Value const& value() const& + { + VERIFY(has_value()); + return m_value; + } + + [[nodiscard]] JS::Value value() && + { + return release_value(); + } + + [[nodiscard]] JS::Value release_value() + { + VERIFY(has_value()); + JS::Value released_value = m_value; + clear(); + return released_value; + } + + JS::Value value_or(JS::Value const& fallback) const& + { + if (has_value()) + return value(); + return fallback; + } + + [[nodiscard]] JS::Value value_or(JS::Value&& fallback) && + { + if (has_value()) + return value(); + return fallback; + } + + JS::Value const& operator*() const { return value(); } + JS::Value& operator*() { return value(); } + + JS::Value const* operator->() const { return &value(); } + JS::Value* operator->() { return &value(); } + +private: + JS::Value m_value; +}; + template<> struct Formatter : Formatter { ErrorOr format(FormatBuilder& builder, JS::Value value)