瀏覽代碼

LibJS: Specialize Optional<Value>

Values can be "empty" which only has a valid meaning for array holes.
We can however use this state the represent the empty state of an
Optional<Value> which is used in a lot of placed, because of Completion
having one.
This saves 8 bytes for every Optional<Value>.
davidot 3 年之前
父節點
當前提交
8381e7f1e6
共有 1 個文件被更改,包括 104 次插入0 次删除
  1. 104 0
      Userland/Libraries/LibJS/Runtime/Value.h

+ 104 - 0
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<JS::Value> {
+    template<typename U>
+    friend class Optional;
+
+public:
+    using ValueType = JS::Value;
+
+    Optional() = default;
+
+    Optional(Optional<JS::Value> const& other)
+    {
+        if (other.has_value())
+            m_value = other.m_value;
+    }
+
+    Optional(Optional&& other)
+        : m_value(other.m_value)
+    {
+    }
+
+    template<typename U = JS::Value>
+    explicit(!IsConvertible<U&&, JS::Value>) Optional(U&& value) requires(!IsSame<RemoveCVReference<U>, Optional<JS::Value>> && IsConstructible<JS::Value, U&&>)
+        : m_value(forward<U>(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<JS::Value> : Formatter<StringView> {
     ErrorOr<void> format(FormatBuilder& builder, JS::Value value)