| 
									
										
										
										
											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-04-01 18:26:13 +02:00
										 |  |  |  | } |