| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2025-03-24 20:43:12 +01:00
										 |  |  |  |  * Copyright (c) 2024-2025, stelar7 <dudedbz@gmail.com> | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  |  * | 
					
						
							|  |  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 20:50:52 +01:00
										 |  |  |  | #include <AK/String.h>
 | 
					
						
							|  |  |  |  | #include <LibJS/Runtime/Array.h>
 | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  | #include <LibWeb/Bindings/IDBObjectStorePrototype.h>
 | 
					
						
							|  |  |  |  | #include <LibWeb/Bindings/Intrinsics.h>
 | 
					
						
							|  |  |  |  | #include <LibWeb/HTML/EventNames.h>
 | 
					
						
							|  |  |  |  | #include <LibWeb/IndexedDB/IDBObjectStore.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace Web::IndexedDB { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | GC_DEFINE_ALLOCATOR(IDBObjectStore); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | IDBObjectStore::~IDBObjectStore() = default; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 20:43:12 +01:00
										 |  |  |  | IDBObjectStore::IDBObjectStore(JS::Realm& realm, GC::Ref<ObjectStore> store, GC::Ref<IDBTransaction> transaction) | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  |     : PlatformObject(realm) | 
					
						
							| 
									
										
										
										
											2025-03-24 20:43:12 +01:00
										 |  |  |  |     , m_store(store) | 
					
						
							|  |  |  |  |     , m_transaction(transaction) | 
					
						
							| 
									
										
										
										
											2025-03-24 21:18:26 +01:00
										 |  |  |  |     , m_name(store->name()) | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 20:43:12 +01:00
										 |  |  |  | GC::Ref<IDBObjectStore> IDBObjectStore::create(JS::Realm& realm, GC::Ref<ObjectStore> store, GC::Ref<IDBTransaction> transaction) | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-03-24 20:43:12 +01:00
										 |  |  |  |     return realm.create<IDBObjectStore>(realm, store, transaction); | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void IDBObjectStore::initialize(JS::Realm& realm) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     Base::initialize(realm); | 
					
						
							|  |  |  |  |     WEB_SET_PROTOTYPE_FOR_INTERFACE(IDBObjectStore); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 20:43:12 +01:00
										 |  |  |  | void IDBObjectStore::visit_edges(Visitor& visitor) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     Base::visit_edges(visitor); | 
					
						
							|  |  |  |  |     visitor.visit(m_store); | 
					
						
							|  |  |  |  |     visitor.visit(m_transaction); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 20:50:52 +01:00
										 |  |  |  | // https://w3c.github.io/IndexedDB/#dom-idbobjectstore-keypath
 | 
					
						
							|  |  |  |  | JS::Value IDBObjectStore::key_path() const | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     if (!m_store->key_path().has_value()) | 
					
						
							|  |  |  |  |         return JS::js_null(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return m_store->key_path().value().visit( | 
					
						
							|  |  |  |  |         [&](String const& value) -> JS::Value { | 
					
						
							|  |  |  |  |             return JS::PrimitiveString::create(realm().vm(), value); | 
					
						
							|  |  |  |  |         }, | 
					
						
							|  |  |  |  |         [&](Vector<String> const& value) -> JS::Value { | 
					
						
							|  |  |  |  |             return JS::Array::create_from<String>(realm(), value.span(), [&](auto const& entry) -> JS::Value { | 
					
						
							|  |  |  |  |                 return JS::PrimitiveString::create(realm().vm(), entry); | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 21:18:26 +01:00
										 |  |  |  | // https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name
 | 
					
						
							|  |  |  |  | WebIDL::ExceptionOr<void> IDBObjectStore::set_name(String const& value) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     auto& realm = this->realm(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 1. Let name be the given value.
 | 
					
						
							|  |  |  |  |     auto const& name = value; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 2. Let transaction be this’s transaction.
 | 
					
						
							|  |  |  |  |     auto& transaction = m_transaction; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 3. Let store be this’s object store.
 | 
					
						
							|  |  |  |  |     auto& store = m_store; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // FIXME: 4. If store has been deleted, throw an "InvalidStateError" DOMException.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 5. If transaction is not an upgrade transaction, throw an "InvalidStateError" DOMException.
 | 
					
						
							|  |  |  |  |     if (transaction->mode() != Bindings::IDBTransactionMode::Versionchange) | 
					
						
							|  |  |  |  |         return WebIDL::InvalidStateError::create(realm, "Attempted to set name outside of version change"_string); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 6. If transaction’s state is not active, throw a "TransactionInactiveError" DOMException.
 | 
					
						
							|  |  |  |  |     if (transaction->state() != IDBTransaction::TransactionState::Active) | 
					
						
							|  |  |  |  |         return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active"_string); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 7. If store’s name is equal to name, terminate these steps.
 | 
					
						
							|  |  |  |  |     if (store->name() == name) | 
					
						
							|  |  |  |  |         return {}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 8. If an object store named name already exists in store’s database, throw a "ConstraintError" DOMException.
 | 
					
						
							|  |  |  |  |     if (store->database()->has_object_store_named(name)) | 
					
						
							|  |  |  |  |         return WebIDL::ConstraintError::create(realm, "Object store with the given name already exists"_string); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 9. Set store’s name to name.
 | 
					
						
							|  |  |  |  |     store->set_name(name); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 10. Set this’s name to name.
 | 
					
						
							|  |  |  |  |     m_name = name; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return {}; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 18:56:26 +01:00
										 |  |  |  | } |