diff --git a/Libraries/LibWeb/IndexedDB/IDBIndex.cpp b/Libraries/LibWeb/IndexedDB/IDBIndex.cpp index 9d11c0ec8dd..a62ea6e5e31 100644 --- a/Libraries/LibWeb/IndexedDB/IDBIndex.cpp +++ b/Libraries/LibWeb/IndexedDB/IDBIndex.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -15,14 +16,17 @@ GC_DEFINE_ALLOCATOR(IDBIndex); IDBIndex::~IDBIndex() = default; -IDBIndex::IDBIndex(JS::Realm& realm) +IDBIndex::IDBIndex(JS::Realm& realm, GC::Ref index, GC::Ref object_store) : PlatformObject(realm) + , m_index(index) + , m_object_store_handle(object_store) + , m_name(index->name()) { } -GC::Ref IDBIndex::create(JS::Realm& realm) +GC::Ref IDBIndex::create(JS::Realm& realm, GC::Ref index, GC::Ref object_store) { - return realm.create(realm); + return realm.create(realm, index, object_store); } void IDBIndex::initialize(JS::Realm& realm) @@ -31,4 +35,68 @@ void IDBIndex::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(IDBIndex); } +void IDBIndex::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_index); + visitor.visit(m_object_store_handle); +} + +// https://w3c.github.io/IndexedDB/#dom-idbindex-name +WebIDL::ExceptionOr IDBIndex::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 = this->transaction(); + + // 3. Let index be this’s index. + auto index = this->index(); + + // 4. If transaction is not an upgrade transaction, throw an "InvalidStateError" DOMException. + if (!transaction->is_upgrade_transaction()) + return WebIDL::InvalidStateError::create(realm, "Transaction is not an upgrade transaction"_string); + + // 5. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException. + if (transaction->state() != IDBTransaction::TransactionState::Active) + return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active"_string); + + // FIXME: 6. If index or index’s object store has been deleted, throw an "InvalidStateError" DOMException. + + // 7. If index’s name is equal to name, terminate these steps. + if (index->name() == name) + return {}; + + // 8. If an index named name already exists in index’s object store, throw a "ConstraintError" DOMException. + for (auto const& existing_index : m_object_store_handle->index_set()) { + if (existing_index->name() == name) + return WebIDL::ConstraintError::create(realm, "An index with the given name already exists"_string); + } + + // 9. Set index’s name to name. + index->set_name(name); + + // 10. Set this’s name to name. + m_name = name; + + return {}; +} + +// https://w3c.github.io/IndexedDB/#dom-idbindex-keypath +JS::Value IDBIndex::key_path() const +{ + return m_index->key_path().visit( + [&](String const& value) -> JS::Value { + return JS::PrimitiveString::create(realm().vm(), value); + }, + [&](Vector const& value) -> JS::Value { + return JS::Array::create_from(realm(), value.span(), [&](auto const& entry) -> JS::Value { + return JS::PrimitiveString::create(realm().vm(), entry); + }); + }); +} + } diff --git a/Libraries/LibWeb/IndexedDB/IDBIndex.h b/Libraries/LibWeb/IndexedDB/IDBIndex.h index 3e1b080a6db..ba8ef9f4815 100644 --- a/Libraries/LibWeb/IndexedDB/IDBIndex.h +++ b/Libraries/LibWeb/IndexedDB/IDBIndex.h @@ -8,6 +8,8 @@ #include #include +#include +#include namespace Web::IndexedDB { @@ -18,11 +20,32 @@ class IDBIndex : public Bindings::PlatformObject { public: virtual ~IDBIndex() override; - [[nodiscard]] static GC::Ref create(JS::Realm&); + [[nodiscard]] static GC::Ref create(JS::Realm&, GC::Ref, GC::Ref); + + WebIDL::ExceptionOr set_name(String const& value); + String name() const { return m_name; } + GC::Ref object_store() { return m_object_store_handle; } + JS::Value key_path() const; + bool multi_entry() const { return m_index->multi_entry(); } + bool unique() const { return m_index->unique(); } + + // The transaction of an index handle is the transaction of its associated object store handle. + GC::Ref transaction() { return m_object_store_handle->transaction(); } + GC::Ref index() { return m_index; } + GC::Ref store() { return m_object_store_handle; } protected: - explicit IDBIndex(JS::Realm&); + explicit IDBIndex(JS::Realm&, GC::Ref, GC::Ref); virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor& visitor) override; + +private: + // An index handle has an associated index and an associated object store handle. + GC::Ref m_index; + GC::Ref m_object_store_handle; + + // An index handle has a name, which is initialized to the name of the associated index when the index handle is created. + String m_name; }; } diff --git a/Libraries/LibWeb/IndexedDB/IDBIndex.idl b/Libraries/LibWeb/IndexedDB/IDBIndex.idl index a096122f40d..85e0ae37745 100644 --- a/Libraries/LibWeb/IndexedDB/IDBIndex.idl +++ b/Libraries/LibWeb/IndexedDB/IDBIndex.idl @@ -2,11 +2,11 @@ [Exposed=(Window,Worker)] interface IDBIndex { - [FIXME] attribute DOMString name; - [FIXME, SameObject] readonly attribute IDBObjectStore objectStore; - [FIXME] readonly attribute any keyPath; - [FIXME] readonly attribute boolean multiEntry; - [FIXME] readonly attribute boolean unique; + attribute DOMString name; + [SameObject] readonly attribute IDBObjectStore objectStore; + readonly attribute any keyPath; + readonly attribute boolean multiEntry; + readonly attribute boolean unique; [FIXME, NewObject] IDBRequest get(any query); [FIXME, NewObject] IDBRequest getKey(any query); [FIXME, NewObject] IDBRequest getAll(optional any query, optional [EnforceRange] unsigned long count);