LibWeb: Implement the IDBDatabase interface

This commit is contained in:
stelar7 2024-11-04 18:53:05 +01:00 committed by Andrew Kaster
parent 5d9b13a970
commit 60ae5e75f8
Notes: github-actions[bot] 2024-11-08 18:11:57 +00:00
7 changed files with 196 additions and 0 deletions

View file

@ -195,6 +195,7 @@ HTMLVideoElement
HashChangeEvent
Headers
History
IDBDatabase
IDBFactory
IDBOpenDBRequest
IDBRequest

View file

@ -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

View file

@ -568,6 +568,7 @@ class Performance;
namespace Web::IndexedDB {
class Database;
class IDBFactory;
class IDBDatabase;
class IDBOpenDBRequest;
class IDBRequest;
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2024, stelar7 <dudedbz@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/IDBDatabasePrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/IndexedDB/IDBDatabase.h>
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> IDBDatabase::create(JS::Realm& realm, Database& db)
{
return realm.heap().allocate<IDBDatabase>(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);
}
}

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2024, stelar7 <dudedbz@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/HTML/DOMStringList.h>
#include <LibWeb/IndexedDB/IDBRequest.h>
#include <LibWeb/IndexedDB/Internal/Database.h>
#include <LibWeb/StorageAPI/StorageKey.h>
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<IDBDatabase> 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<HTML::DOMStringList> 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<Database> 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<HTML::DOMStringList> 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<Database> m_associated_database;
};
}

View file

@ -0,0 +1,31 @@
#import <DOM/EventTarget.idl>
#import <DOM/EventHandler.idl>
[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<DOMString>) 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<DOMString>)? keyPath = null;
boolean autoIncrement = false;
};

View file

@ -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)