diff --git a/Libraries/LibWeb/IndexedDB/IDBCursor.cpp b/Libraries/LibWeb/IndexedDB/IDBCursor.cpp index 7cd586a4790..e6d5fc5729f 100644 --- a/Libraries/LibWeb/IndexedDB/IDBCursor.cpp +++ b/Libraries/LibWeb/IndexedDB/IDBCursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, stelar7 + * Copyright (c) 2024-2025, stelar7 * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,6 +8,7 @@ #include #include #include +#include namespace Web::IndexedDB { @@ -15,14 +16,23 @@ GC_DEFINE_ALLOCATOR(IDBCursor); IDBCursor::~IDBCursor() = default; -IDBCursor::IDBCursor(JS::Realm& realm) +IDBCursor::IDBCursor(JS::Realm& realm, GC::Ref transaction, GC::Ptr position, Bindings::IDBCursorDirection direction, bool got_value, GC::Ptr key, JS::Value value, CursorSource source, GC::Ref range, bool key_only) : PlatformObject(realm) + , m_transaction(transaction) + , m_position(position) + , m_direction(direction) + , m_got_value(got_value) + , m_key(key) + , m_value(value) + , m_source(source) + , m_range(range) + , m_key_only(key_only) { } -GC::Ref IDBCursor::create(JS::Realm& realm) +GC::Ref IDBCursor::create(JS::Realm& realm, GC::Ref transaction, GC::Ptr position, Bindings::IDBCursorDirection direction, bool got_value, GC::Ptr key, JS::Value value, CursorSource source, GC::Ref range, bool key_only) { - return realm.create(realm); + return realm.create(realm, transaction, position, direction, got_value, key, value, source, range, key_only); } void IDBCursor::initialize(JS::Realm& realm) @@ -31,4 +41,29 @@ void IDBCursor::initialize(JS::Realm& realm) Base::initialize(realm); } +void IDBCursor::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_transaction); + visitor.visit(m_position); + visitor.visit(m_object_store_position); + visitor.visit(m_key); + visitor.visit(m_range); + visitor.visit(m_request); + + m_source.visit([&](auto& source) { + visitor.visit(source); + }); +} + +// https://w3c.github.io/IndexedDB/#dom-idbcursor-key +JS::Value IDBCursor::key() +{ + // The key getter steps are to return the result of converting a key to a value with the cursor’s current key. + if (!m_key) + return JS::js_undefined(); + + return convert_a_key_to_a_value(realm(), *m_key); +} + } diff --git a/Libraries/LibWeb/IndexedDB/IDBCursor.h b/Libraries/LibWeb/IndexedDB/IDBCursor.h index 004880aca34..56937c333c6 100644 --- a/Libraries/LibWeb/IndexedDB/IDBCursor.h +++ b/Libraries/LibWeb/IndexedDB/IDBCursor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, stelar7 + * Copyright (c) 2024-2025, stelar7 * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,10 +7,18 @@ #pragma once #include +#include #include +#include +#include +#include +#include +#include namespace Web::IndexedDB { +using CursorSource = Variant, GC::Ref>; + // https://w3c.github.io/IndexedDB/#cursor-interface class IDBCursor : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(IDBCursor, Bindings::PlatformObject); @@ -18,10 +26,55 @@ class IDBCursor : public Bindings::PlatformObject { public: virtual ~IDBCursor() override; - [[nodiscard]] static GC::Ref create(JS::Realm&); + [[nodiscard]] static GC::Ref create(JS::Realm&, GC::Ref, GC::Ptr, Bindings::IDBCursorDirection, bool, GC::Ptr, JS::Value, CursorSource, GC::Ref, bool); + + [[nodiscard]] CursorSource source() { return m_source; } + [[nodiscard]] Bindings::IDBCursorDirection direction() { return m_direction; } + [[nodiscard]] JS::Value key(); + [[nodiscard]] JS::Value value() { return m_value.value_or(JS::js_undefined()); } + [[nodiscard]] GC::Ptr request() { return m_request; } + [[nodiscard]] GC::Ref transaction() { return m_transaction; } + [[nodiscard]] GC::Ref range() { return m_range; } + [[nodiscard]] GC::Ptr position() { return m_position; } + [[nodiscard]] GC::Ptr object_store_position() { return m_object_store_position; } + [[nodiscard]] bool key_only() const { return m_key_only; } + [[nodiscard]] bool got_value() const { return m_got_value; } protected: - explicit IDBCursor(JS::Realm&); + explicit IDBCursor(JS::Realm&, GC::Ref, GC::Ptr, Bindings::IDBCursorDirection, bool, GC::Ptr, JS::Value, CursorSource, GC::Ref, bool); virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor& visitor) override; + +private: + // A cursor has a transaction, the transaction that was active when the cursor was created. + GC::Ref m_transaction; + + // A cursor has a position within its range. + GC::Ptr m_position; + + // When iterating indexes the cursor also has an object store position + GC::Ptr m_object_store_position; + + // A cursor has a direction that determines whether it moves in monotonically increasing or decreasing order of the record keys when iterated, and if it skips duplicated values when iterating indexes. + Bindings::IDBCursorDirection m_direction; + + // A cursor has a got value flag. + bool m_got_value { false }; + + // A cursor has a key and a value which represent the key and the value of the last iterated record. + GC::Ptr m_key; + Optional m_value; + + // A cursor has a source that indicates which index or an object store is associated with the records over which the cursor is iterating. + CursorSource m_source; + + // A cursor has a range of records in either an index or an object store. + GC::Ref m_range; + + // A cursor has a request, which is the request used to open the cursor. + GC::Ptr m_request; + + // A cursor also has a key only flag, that indicates whether the cursor’s value is exposed via the API. + bool m_key_only { false }; }; } diff --git a/Libraries/LibWeb/IndexedDB/IDBCursor.idl b/Libraries/LibWeb/IndexedDB/IDBCursor.idl index d97bc8d87a3..331468f3f0a 100644 --- a/Libraries/LibWeb/IndexedDB/IDBCursor.idl +++ b/Libraries/LibWeb/IndexedDB/IDBCursor.idl @@ -2,11 +2,11 @@ [Exposed=(Window,Worker)] interface IDBCursor { - [FIXME] readonly attribute (IDBObjectStore or IDBIndex) source; - [FIXME] readonly attribute IDBCursorDirection direction; - [FIXME] readonly attribute any key; + readonly attribute (IDBObjectStore or IDBIndex) source; + readonly attribute IDBCursorDirection direction; + readonly attribute any key; [FIXME] readonly attribute any primaryKey; - [FIXME, SameObject] readonly attribute IDBRequest request; + [SameObject] readonly attribute IDBRequest request; [FIXME] undefined advance([EnforceRange] unsigned long count); [FIXME] undefined continue(optional any key); [FIXME] undefined continuePrimaryKey(any key, any primaryKey);