From 96600e77c2ce17eccb675eb137ec9cdd28ac0074 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Mon, 21 Aug 2023 15:13:18 -0600 Subject: [PATCH] LibJS: Enable storing Value and Handle in HashMaps We have the right conversions to make this work, so let's make it possible to have a `HashMap, V>` and look for a specific T inside it without having to create a temporary handle. This involves adding some operator== implementations, and some specializations of AK::Traits. --- Userland/Libraries/LibJS/Heap/Handle.h | 25 ++++++++++++++++++++++++ Userland/Libraries/LibJS/Runtime/Value.h | 17 ++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Userland/Libraries/LibJS/Heap/Handle.h b/Userland/Libraries/LibJS/Heap/Handle.h index d74f2426e8..f816aa9ef8 100644 --- a/Userland/Libraries/LibJS/Heap/Handle.h +++ b/Userland/Libraries/LibJS/Heap/Handle.h @@ -162,6 +162,9 @@ public: auto value() const { return *m_value; } bool is_null() const { return m_handle.is_null() && !m_value.has_value(); } + bool operator==(Value const& value) const { return value == m_value; } + bool operator==(Handle const& other) const { return other.m_value == this->m_value; } + private: explicit Handle(Value value) : m_value(value) @@ -184,3 +187,25 @@ inline Handle make_handle(Value value) } } + +namespace AK { + +template +struct Traits> : public GenericTraits> { + static unsigned hash(JS::Handle const& handle) { return Traits::hash(handle); } +}; + +template<> +struct Traits> : public GenericTraits> { + static unsigned hash(JS::Handle const& handle) { return Traits::hash(handle.value()); } +}; + +namespace Detail { +template +inline constexpr bool IsHashCompatible, T> = true; + +template +inline constexpr bool IsHashCompatible> = true; + +} +} diff --git a/Userland/Libraries/LibJS/Runtime/Value.h b/Userland/Libraries/LibJS/Runtime/Value.h index 6196d1545b..85e31667cc 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.h +++ b/Userland/Libraries/LibJS/Runtime/Value.h @@ -619,6 +619,18 @@ public: return *this; } + template + ALWAYS_INLINE bool operator==(Optional const& other) const + { + return has_value() == other.has_value() && (!has_value() || value() == other.value()); + } + + template + ALWAYS_INLINE bool operator==(O const& other) const + { + return has_value() && value() == other; + } + void clear() { m_value = {}; @@ -688,4 +700,9 @@ struct Formatter : Formatter { } }; +template<> +struct Traits : GenericTraits { + static unsigned hash(JS::Value value) { return Traits::hash(value.encoded()); } +}; + }