2025-04-01 18:26:13 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2025, stelar7 <dudedbz@gmail.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <LibWeb/IndexedDB/Internal/Index.h>
|
|
|
|
|
#include <LibWeb/IndexedDB/Internal/ObjectStore.h>
|
|
|
|
|
|
|
|
|
|
namespace Web::IndexedDB {
|
|
|
|
|
|
|
|
|
|
GC_DEFINE_ALLOCATOR(Index);
|
|
|
|
|
|
|
|
|
|
Index::~Index() = default;
|
|
|
|
|
|
2025-05-02 14:31:58 +02:00
|
|
|
|
GC::Ref<Index> Index::create(JS::Realm& realm, GC::Ref<ObjectStore> store, String const& name, KeyPath const& key_path, bool unique, bool multi_entry)
|
2025-04-01 18:26:13 +02:00
|
|
|
|
{
|
|
|
|
|
return realm.create<Index>(store, name, key_path, unique, multi_entry);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-02 14:31:58 +02:00
|
|
|
|
Index::Index(GC::Ref<ObjectStore> store, String const& name, KeyPath const& key_path, bool unique, bool multi_entry)
|
2025-04-01 18:26:13 +02:00
|
|
|
|
: m_object_store(store)
|
2025-05-02 14:31:58 +02:00
|
|
|
|
, m_name(name)
|
2025-04-01 18:26:13 +02:00
|
|
|
|
, m_unique(unique)
|
|
|
|
|
, m_multi_entry(multi_entry)
|
|
|
|
|
, m_key_path(key_path)
|
|
|
|
|
{
|
2025-04-01 18:37:23 +02:00
|
|
|
|
store->index_set().set(name, *this);
|
2025-04-01 18:26:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Index::visit_edges(Visitor& visitor)
|
|
|
|
|
{
|
|
|
|
|
Base::visit_edges(visitor);
|
|
|
|
|
visitor.visit(m_object_store);
|
|
|
|
|
|
|
|
|
|
for (auto& record : m_records) {
|
|
|
|
|
visitor.visit(record.key);
|
|
|
|
|
visitor.visit(record.value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-01 18:37:23 +02:00
|
|
|
|
void Index::set_name(String name)
|
|
|
|
|
{
|
|
|
|
|
// NOTE: Update the key in the map so it still matches the name
|
|
|
|
|
auto old_value = m_object_store->index_set().take(m_name).release_value();
|
|
|
|
|
m_object_store->index_set().set(name, old_value);
|
|
|
|
|
|
|
|
|
|
m_name = move(name);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 11:38:29 +02:00
|
|
|
|
bool Index::has_record_with_key(GC::Ref<Key> key)
|
|
|
|
|
{
|
|
|
|
|
auto index = m_records.find_if([&key](auto const& record) {
|
2025-04-29 19:56:34 +02:00
|
|
|
|
return Key::equals(record.key, key);
|
2025-04-11 11:38:29 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return index != m_records.end();
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-06 11:36:11 +02:00
|
|
|
|
// https://w3c.github.io/IndexedDB/#index-referenced-value
|
|
|
|
|
HTML::SerializationRecord Index::referenced_value(IndexRecord const& index_record) const
|
|
|
|
|
{
|
|
|
|
|
// Records in an index are said to have a referenced value.
|
|
|
|
|
// This is the value of the record in the index’s referenced object store which has a key equal to the index’s record’s value.
|
|
|
|
|
return m_object_store
|
|
|
|
|
->records()
|
|
|
|
|
.first_matching([&](auto const& store_record) {
|
|
|
|
|
return Key::equals(store_record.key, index_record.value);
|
|
|
|
|
})
|
|
|
|
|
.value()
|
|
|
|
|
.value;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 10:04:43 +02:00
|
|
|
|
void Index::clear_records()
|
|
|
|
|
{
|
|
|
|
|
m_records.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 22:18:14 +02:00
|
|
|
|
Optional<IndexRecord&> Index::first_in_range(GC::Ref<IDBKeyRange> range)
|
|
|
|
|
{
|
|
|
|
|
return m_records.first_matching([&](auto const& record) {
|
|
|
|
|
return range->is_in_range(record.key);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 22:41:18 +02:00
|
|
|
|
GC::ConservativeVector<IndexRecord> Index::first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
|
|
|
|
|
{
|
|
|
|
|
GC::ConservativeVector<IndexRecord> records(range->heap());
|
|
|
|
|
for (auto const& record : m_records) {
|
|
|
|
|
if (range->is_in_range(record.key))
|
|
|
|
|
records.append(record);
|
|
|
|
|
|
|
|
|
|
if (count.has_value() && records.size() >= *count)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return records;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 22:54:08 +02:00
|
|
|
|
u64 Index::count_records_in_range(GC::Ref<IDBKeyRange> range)
|
|
|
|
|
{
|
|
|
|
|
u64 count = 0;
|
|
|
|
|
for (auto const& record : m_records) {
|
|
|
|
|
if (range->is_in_range(record.key))
|
|
|
|
|
++count;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-01 18:26:13 +02:00
|
|
|
|
}
|