LibJS: Allow Optional<Value> to be used in constant expressions

This commit is contained in:
Jonne Ransijn 2025-04-10 15:04:56 +02:00 committed by Andrew Kaster
commit c63a8c0334
Notes: github-actions[bot] 2025-04-23 03:21:22 +00:00

View file

@ -154,7 +154,7 @@ public:
return !is_nan() && !is_infinity(); return !is_nan() && !is_infinity();
} }
Value() constexpr Value()
: Value(UNDEFINED_TAG << GC::TAG_SHIFT, (u64)0) : Value(UNDEFINED_TAG << GC::TAG_SHIFT, (u64)0)
{ {
} }
@ -428,12 +428,12 @@ private:
enum class EmptyTag { Empty }; enum class EmptyTag { Empty };
Value(EmptyTag) constexpr Value(EmptyTag)
: Value(EMPTY_TAG << GC::TAG_SHIFT, (u64)0) : Value(EMPTY_TAG << GC::TAG_SHIFT, (u64)0)
{ {
} }
Value(u64 tag, u64 val) constexpr Value(u64 tag, u64 val)
{ {
ASSERT(!(tag & val)); ASSERT(!(tag & val));
m_value.encoded = tag | val; m_value.encoded = tag | val;
@ -467,9 +467,9 @@ private:
ThrowCompletionOr<i32> to_i32_slow_case(VM&) const; ThrowCompletionOr<i32> to_i32_slow_case(VM&) const;
friend Value js_undefined(); friend constexpr Value js_undefined();
friend Value js_null(); friend constexpr Value js_null();
friend Value js_special_empty_value(); friend constexpr Value js_special_empty_value();
friend ThrowCompletionOr<Value> greater_than(VM&, Value lhs, Value rhs); friend ThrowCompletionOr<Value> greater_than(VM&, Value lhs, Value rhs);
friend ThrowCompletionOr<Value> greater_than_equals(VM&, Value lhs, Value rhs); friend ThrowCompletionOr<Value> greater_than_equals(VM&, Value lhs, Value rhs);
friend ThrowCompletionOr<Value> less_than(VM&, Value lhs, Value rhs); friend ThrowCompletionOr<Value> less_than(VM&, Value lhs, Value rhs);
@ -478,17 +478,17 @@ private:
friend bool same_value_non_number(Value lhs, Value rhs); friend bool same_value_non_number(Value lhs, Value rhs);
}; };
inline Value js_undefined() inline constexpr Value js_undefined()
{ {
return Value(UNDEFINED_TAG << GC::TAG_SHIFT, (u64)0); return Value(UNDEFINED_TAG << GC::TAG_SHIFT, (u64)0);
} }
inline Value js_null() inline constexpr Value js_null()
{ {
return Value(NULL_TAG << GC::TAG_SHIFT, (u64)0); return Value(NULL_TAG << GC::TAG_SHIFT, (u64)0);
} }
inline Value js_special_empty_value() inline constexpr Value js_special_empty_value()
{ {
return Value(Value::EmptyTag::Empty); return Value(Value::EmptyTag::Empty);
} }
@ -564,38 +564,38 @@ class Optional<JS::Value> : public OptionalBase<JS::Value> {
public: public:
using ValueType = JS::Value; using ValueType = JS::Value;
Optional() = default; constexpr Optional() = default;
template<SameAs<OptionalNone> V> template<SameAs<OptionalNone> V>
Optional(V) { } constexpr Optional(V) { }
Optional(Optional<JS::Value> const& other) constexpr Optional(Optional<JS::Value> const& other)
{ {
if (other.has_value()) if (other.has_value())
m_value = other.m_value; m_value = other.m_value;
} }
Optional(Optional&& other) constexpr Optional(Optional&& other)
: m_value(other.m_value) : m_value(other.m_value)
{ {
} }
template<typename U = JS::Value> template<typename U = JS::Value>
requires(!IsSame<OptionalNone, RemoveCVReference<U>>) requires(!IsSame<OptionalNone, RemoveCVReference<U>>)
explicit(!IsConvertible<U&&, JS::Value>) Optional(U&& value) explicit(!IsConvertible<U&&, JS::Value>) constexpr Optional(U&& value)
requires(!IsSame<RemoveCVReference<U>, Optional<JS::Value>> && IsConstructible<JS::Value, U &&>) requires(!IsSame<RemoveCVReference<U>, Optional<JS::Value>> && IsConstructible<JS::Value, U &&>)
: m_value(forward<U>(value)) : m_value(forward<U>(value))
{ {
} }
template<SameAs<OptionalNone> V> template<SameAs<OptionalNone> V>
Optional& operator=(V) constexpr Optional& operator=(V)
{ {
clear(); clear();
return *this; return *this;
} }
Optional& operator=(Optional const& other) constexpr Optional& operator=(Optional const& other)
{ {
if (this != &other) { if (this != &other) {
clear(); clear();
@ -604,7 +604,7 @@ public:
return *this; return *this;
} }
Optional& operator=(Optional&& other) constexpr Optional& operator=(Optional&& other)
{ {
if (this != &other) { if (this != &other) {
clear(); clear();
@ -613,34 +613,34 @@ public:
return *this; return *this;
} }
void clear() constexpr void clear()
{ {
m_value = JS::js_special_empty_value(); m_value = JS::js_special_empty_value();
} }
[[nodiscard]] bool has_value() const [[nodiscard]] constexpr bool has_value() const
{ {
return !m_value.is_special_empty_value(); return !m_value.is_special_empty_value();
} }
[[nodiscard]] JS::Value& value() & [[nodiscard]] constexpr JS::Value& value() &
{ {
VERIFY(has_value()); VERIFY(has_value());
return m_value; return m_value;
} }
[[nodiscard]] JS::Value const& value() const& [[nodiscard]] constexpr JS::Value const& value() const&
{ {
VERIFY(has_value()); VERIFY(has_value());
return m_value; return m_value;
} }
[[nodiscard]] JS::Value value() && [[nodiscard]] constexpr JS::Value value() &&
{ {
return release_value(); return release_value();
} }
[[nodiscard]] JS::Value release_value() [[nodiscard]] constexpr JS::Value release_value()
{ {
VERIFY(has_value()); VERIFY(has_value());
JS::Value released_value = m_value; JS::Value released_value = m_value;