diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 8e3b83a0bc6..842fbd2dc0d 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -195,6 +195,7 @@ HTMLVideoElement HashChangeEvent Headers History +IDBDatabase IDBFactory IDBOpenDBRequest IDBRequest diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 1dcebd6affa..16afd614a5e 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -504,6 +504,7 @@ set(SOURCES IndexedDB/Internal/Database.cpp IndexedDB/IDBFactory.cpp IndexedDB/IDBOpenDBRequest.cpp + IndexedDB/IDBDatabase.cpp IndexedDB/IDBRequest.cpp Internals/Inspector.cpp Internals/InternalAnimationTimeline.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 0e828e5960a..0e25e224d16 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -568,6 +568,7 @@ class Performance; namespace Web::IndexedDB { class Database; class IDBFactory; +class IDBDatabase; class IDBOpenDBRequest; class IDBRequest; } diff --git a/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp b/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp new file mode 100644 index 00000000000..2e00a42857c --- /dev/null +++ b/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::IndexedDB { + +JS_DEFINE_ALLOCATOR(IDBDatabase); + +IDBDatabase::IDBDatabase(JS::Realm& realm, Database& db) + : EventTarget(realm) + , m_name(db.name()) + , m_object_store_names(HTML::DOMStringList::create(realm, {})) + , m_associated_database(db) +{ + db.associate(*this); +} + +IDBDatabase::~IDBDatabase() = default; + +JS::NonnullGCPtr IDBDatabase::create(JS::Realm& realm, Database& db) +{ + return realm.heap().allocate(realm, realm, db); +} + +void IDBDatabase::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(IDBDatabase); +} + +void IDBDatabase::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_object_store_names); + visitor.visit(m_associated_database); +} + +void IDBDatabase::set_onabort(WebIDL::CallbackType* event_handler) +{ + set_event_handler_attribute(HTML::EventNames::abort, event_handler); +} + +WebIDL::CallbackType* IDBDatabase::onabort() +{ + return event_handler_attribute(HTML::EventNames::abort); +} + +void IDBDatabase::set_onerror(WebIDL::CallbackType* event_handler) +{ + set_event_handler_attribute(HTML::EventNames::error, event_handler); +} + +WebIDL::CallbackType* IDBDatabase::onerror() +{ + return event_handler_attribute(HTML::EventNames::error); +} + +void IDBDatabase::set_onclose(WebIDL::CallbackType* event_handler) +{ + set_event_handler_attribute(HTML::EventNames::close, event_handler); +} + +WebIDL::CallbackType* IDBDatabase::onclose() +{ + return event_handler_attribute(HTML::EventNames::close); +} + +void IDBDatabase::set_onversionchange(WebIDL::CallbackType* event_handler) +{ + set_event_handler_attribute(HTML::EventNames::versionchange, event_handler); +} + +WebIDL::CallbackType* IDBDatabase::onversionchange() +{ + return event_handler_attribute(HTML::EventNames::versionchange); +} + +} diff --git a/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.h b/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.h new file mode 100644 index 00000000000..656b676391d --- /dev/null +++ b/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Web::IndexedDB { + +// FIXME: I'm not sure if this object should do double duty as both the connection and the interface +// but the spec treats it as such...? +// https://w3c.github.io/IndexedDB/#IDBDatabase-interface +// https://www.w3.org/TR/IndexedDB/#database-connection +class IDBDatabase : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(IDBDatabase, DOM::EventTarget); + JS_DECLARE_ALLOCATOR(IDBDatabase); + + enum ConnectionState { + Open, + Closed, + }; + +public: + virtual ~IDBDatabase() override; + + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, Database&); + + void set_version(u64 version) { m_version = version; } + void set_close_pending(bool close_pending) { m_close_pending = close_pending; } + + [[nodiscard]] JS::NonnullGCPtr object_store_names() { return m_object_store_names; } + [[nodiscard]] String name() const { return m_name; } + [[nodiscard]] u64 version() const { return m_version; } + [[nodiscard]] bool close_pending() const { return m_close_pending; } + [[nodiscard]] ConnectionState state() const { return m_state; } + [[nodiscard]] JS::NonnullGCPtr associated_database() { return m_associated_database; } + + void set_onabort(WebIDL::CallbackType*); + WebIDL::CallbackType* onabort(); + void set_onclose(WebIDL::CallbackType*); + WebIDL::CallbackType* onclose(); + void set_onerror(WebIDL::CallbackType*); + WebIDL::CallbackType* onerror(); + void set_onversionchange(WebIDL::CallbackType*); + WebIDL::CallbackType* onversionchange(); + +protected: + explicit IDBDatabase(JS::Realm&, Database&); + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor& visitor) override; + +private: + u64 m_version { 0 }; + String m_name; + JS::NonnullGCPtr m_object_store_names; + + // Each connection has a close pending flag which is initially false. + bool m_close_pending { false }; + // When a connection is initially created it is in an opened state. + ConnectionState m_state { ConnectionState::Open }; + + // NOTE: There is an associated database in the spec, but there is no mention where it is assigned, nor where its from + // So we stash the one we have when opening a connection. + JS::NonnullGCPtr m_associated_database; +}; + +} diff --git a/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.idl b/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.idl new file mode 100644 index 00000000000..2b396057514 --- /dev/null +++ b/Userland/Libraries/LibWeb/IndexedDB/IDBDatabase.idl @@ -0,0 +1,31 @@ +#import +#import + +[Exposed=(Window,Worker)] +interface IDBDatabase : EventTarget { + readonly attribute DOMString name; + readonly attribute unsigned long long version; + readonly attribute DOMStringList objectStoreNames; + + [FIXME, NewObject] IDBTransaction transaction((DOMString or sequence) storeNames, optional IDBTransactionMode mode = "readonly", optional IDBTransactionOptions options = {}); + [FIXME] undefined close(); + [FIXME, NewObject] IDBObjectStore createObjectStore(DOMString name, optional IDBObjectStoreParameters options = {}); + [FIXME] undefined deleteObjectStore(DOMString name); + + // Event handlers: + attribute EventHandler onabort; + attribute EventHandler onclose; + attribute EventHandler onerror; + attribute EventHandler onversionchange; +}; + +enum IDBTransactionDurability { "default", "strict", "relaxed" }; + +dictionary IDBTransactionOptions { + IDBTransactionDurability durability = "default"; +}; + +dictionary IDBObjectStoreParameters { + (DOMString or sequence)? keyPath = null; + boolean autoIncrement = false; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 2e5436e4026..5627dab9ccc 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -243,6 +243,7 @@ libweb_js_bindings(HTML/WorkerGlobalScope) libweb_js_bindings(HTML/WorkerLocation) libweb_js_bindings(HTML/WorkerNavigator) libweb_js_bindings(HighResolutionTime/Performance) +libweb_js_bindings(IndexedDB/IDBDatabase) libweb_js_bindings(IndexedDB/IDBFactory) libweb_js_bindings(IndexedDB/IDBOpenDBRequest) libweb_js_bindings(IndexedDB/IDBRequest)