mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-22 09:18:55 +00:00
LibWeb/IDB: Move Records and give more descriptive names
This commit is contained in:
parent
87af53a613
commit
fe5d5639ef
Notes:
github-actions[bot]
2025-08-27 14:15:50 +00:00
Author: https://github.com/stelar7
Commit: fe5d5639ef
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5385
Reviewed-by: https://github.com/gmta ✅
5 changed files with 55 additions and 38 deletions
|
@ -1372,7 +1372,7 @@ WebIDL::ExceptionOr<GC::Ptr<Key>> store_a_record_into_an_object_store(JS::Realm&
|
||||||
|
|
||||||
// 4. Store a record in store containing key as its key and ! StructuredSerializeForStorage(value) as its value.
|
// 4. Store a record in store containing key as its key and ! StructuredSerializeForStorage(value) as its value.
|
||||||
// The record is stored in the object store’s list of records such that the list is sorted according to the key of the records in ascending order.
|
// The record is stored in the object store’s list of records such that the list is sorted according to the key of the records in ascending order.
|
||||||
Record record = {
|
ObjectStoreRecord record = {
|
||||||
.key = *key,
|
.key = *key,
|
||||||
.value = MUST(HTML::structured_serialize_for_storage(realm.vm(), value)),
|
.value = MUST(HTML::structured_serialize_for_storage(realm.vm(), value)),
|
||||||
};
|
};
|
||||||
|
@ -1523,11 +1523,11 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
VERIFY(source.has<GC::Ref<Index>>() && direction_is_next_or_prev);
|
VERIFY(source.has<GC::Ref<Index>>() && direction_is_next_or_prev);
|
||||||
|
|
||||||
// 4. Let records be the list of records in source.
|
// 4. Let records be the list of records in source.
|
||||||
Variant<ReadonlySpan<Record>, ReadonlySpan<IndexRecord>> records = source.visit(
|
Variant<ReadonlySpan<ObjectStoreRecord>, ReadonlySpan<IndexRecord>> records = source.visit(
|
||||||
[](GC::Ref<ObjectStore> object_store) -> Variant<ReadonlySpan<Record>, ReadonlySpan<IndexRecord>> {
|
[](GC::Ref<ObjectStore> object_store) -> Variant<ReadonlySpan<ObjectStoreRecord>, ReadonlySpan<IndexRecord>> {
|
||||||
return object_store->records();
|
return object_store->records();
|
||||||
},
|
},
|
||||||
[](GC::Ref<Index> index) -> Variant<ReadonlySpan<Record>, ReadonlySpan<IndexRecord>> {
|
[](GC::Ref<Index> index) -> Variant<ReadonlySpan<ObjectStoreRecord>, ReadonlySpan<IndexRecord>> {
|
||||||
return index->records();
|
return index->records();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1543,7 +1543,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
// 8. If count is not given, let count be 1.
|
// 8. If count is not given, let count be 1.
|
||||||
// NOTE: This is handled by the default parameter
|
// NOTE: This is handled by the default parameter
|
||||||
|
|
||||||
auto next_requirements = [&](Variant<Record, IndexRecord> const& record) -> bool {
|
auto next_requirements = [&](Variant<ObjectStoreRecord, IndexRecord> const& record) -> bool {
|
||||||
// * If key is defined:
|
// * If key is defined:
|
||||||
if (key) {
|
if (key) {
|
||||||
// * The record’s key is greater than or equal to key.
|
// * The record’s key is greater than or equal to key.
|
||||||
|
@ -1572,7 +1572,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
|
|
||||||
// * If position is defined and source is an object store:
|
// * If position is defined and source is an object store:
|
||||||
if (position && source.has<GC::Ref<ObjectStore>>()) {
|
if (position && source.has<GC::Ref<ObjectStore>>()) {
|
||||||
auto const& inner_record = record.get<Record>();
|
auto const& inner_record = record.get<ObjectStoreRecord>();
|
||||||
|
|
||||||
// * The record’s key is greater than position.
|
// * The record’s key is greater than position.
|
||||||
if (!Key::greater_than(inner_record.key, *position))
|
if (!Key::greater_than(inner_record.key, *position))
|
||||||
|
@ -1602,7 +1602,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
return is_in_range;
|
return is_in_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto next_unique_requirements = [&](Variant<Record, IndexRecord> const& record) -> bool {
|
auto next_unique_requirements = [&](Variant<ObjectStoreRecord, IndexRecord> const& record) -> bool {
|
||||||
// * If key is defined:
|
// * If key is defined:
|
||||||
if (key) {
|
if (key) {
|
||||||
// * The record’s key is greater than or equal to key.
|
// * The record’s key is greater than or equal to key.
|
||||||
|
@ -1639,7 +1639,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
return is_in_range;
|
return is_in_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prev_requirements = [&](Variant<Record, IndexRecord> const& record) -> bool {
|
auto prev_requirements = [&](Variant<ObjectStoreRecord, IndexRecord> const& record) -> bool {
|
||||||
// * If key is defined:
|
// * If key is defined:
|
||||||
if (key) {
|
if (key) {
|
||||||
// * The record’s key is less than or equal to key.
|
// * The record’s key is less than or equal to key.
|
||||||
|
@ -1668,7 +1668,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
|
|
||||||
// * If position is defined and source is an object store:
|
// * If position is defined and source is an object store:
|
||||||
if (position && source.has<GC::Ref<ObjectStore>>()) {
|
if (position && source.has<GC::Ref<ObjectStore>>()) {
|
||||||
auto const& inner_record = record.get<Record>();
|
auto const& inner_record = record.get<ObjectStoreRecord>();
|
||||||
|
|
||||||
// * The record’s key is less than position.
|
// * The record’s key is less than position.
|
||||||
if (!Key::less_than(inner_record.key, *position))
|
if (!Key::less_than(inner_record.key, *position))
|
||||||
|
@ -1698,7 +1698,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
return is_in_range;
|
return is_in_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prev_unique_requirements = [&](Variant<Record, IndexRecord> const& record) -> bool {
|
auto prev_unique_requirements = [&](Variant<ObjectStoreRecord, IndexRecord> const& record) -> bool {
|
||||||
// * If key is defined:
|
// * If key is defined:
|
||||||
if (key) {
|
if (key) {
|
||||||
// * The record’s key is less than or equal to key.
|
// * The record’s key is less than or equal to key.
|
||||||
|
@ -1736,13 +1736,13 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 9. While count is greater than 0:
|
// 9. While count is greater than 0:
|
||||||
Variant<Empty, Record, IndexRecord> found_record;
|
Variant<Empty, ObjectStoreRecord, IndexRecord> found_record;
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
// 1. Switch on direction:
|
// 1. Switch on direction:
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case Bindings::IDBCursorDirection::Next: {
|
case Bindings::IDBCursorDirection::Next: {
|
||||||
// Let found record be the first record in records which satisfy all of the following requirements:
|
// Let found record be the first record in records which satisfy all of the following requirements:
|
||||||
found_record = records.visit([&](auto content) -> Variant<Empty, Record, IndexRecord> {
|
found_record = records.visit([&](auto content) -> Variant<Empty, ObjectStoreRecord, IndexRecord> {
|
||||||
auto value = content.first_matching(next_requirements);
|
auto value = content.first_matching(next_requirements);
|
||||||
if (value.has_value())
|
if (value.has_value())
|
||||||
return *value;
|
return *value;
|
||||||
|
@ -1753,7 +1753,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
}
|
}
|
||||||
case Bindings::IDBCursorDirection::Nextunique: {
|
case Bindings::IDBCursorDirection::Nextunique: {
|
||||||
// Let found record be the first record in records which satisfy all of the following requirements:
|
// Let found record be the first record in records which satisfy all of the following requirements:
|
||||||
found_record = records.visit([&](auto content) -> Variant<Empty, Record, IndexRecord> {
|
found_record = records.visit([&](auto content) -> Variant<Empty, ObjectStoreRecord, IndexRecord> {
|
||||||
auto value = content.first_matching(next_unique_requirements);
|
auto value = content.first_matching(next_unique_requirements);
|
||||||
if (value.has_value())
|
if (value.has_value())
|
||||||
return *value;
|
return *value;
|
||||||
|
@ -1764,7 +1764,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
}
|
}
|
||||||
case Bindings::IDBCursorDirection::Prev: {
|
case Bindings::IDBCursorDirection::Prev: {
|
||||||
// Let found record be the last record in records which satisfy all of the following requirements:
|
// Let found record be the last record in records which satisfy all of the following requirements:
|
||||||
found_record = records.visit([&](auto content) -> Variant<Empty, Record, IndexRecord> {
|
found_record = records.visit([&](auto content) -> Variant<Empty, ObjectStoreRecord, IndexRecord> {
|
||||||
auto value = content.last_matching(prev_requirements);
|
auto value = content.last_matching(prev_requirements);
|
||||||
if (value.has_value())
|
if (value.has_value())
|
||||||
return *value;
|
return *value;
|
||||||
|
@ -1776,7 +1776,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
|
|
||||||
case Bindings::IDBCursorDirection::Prevunique: {
|
case Bindings::IDBCursorDirection::Prevunique: {
|
||||||
// Let temp record be the last record in records which satisfy all of the following requirements:
|
// Let temp record be the last record in records which satisfy all of the following requirements:
|
||||||
auto temp_record = records.visit([&](auto content) -> Variant<Empty, Record, IndexRecord> {
|
auto temp_record = records.visit([&](auto content) -> Variant<Empty, ObjectStoreRecord, IndexRecord> {
|
||||||
auto value = content.last_matching(prev_unique_requirements);
|
auto value = content.last_matching(prev_unique_requirements);
|
||||||
if (value.has_value())
|
if (value.has_value())
|
||||||
return *value;
|
return *value;
|
||||||
|
@ -1790,7 +1790,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
[](Empty) -> GC::Ref<Key> { VERIFY_NOT_REACHED(); },
|
[](Empty) -> GC::Ref<Key> { VERIFY_NOT_REACHED(); },
|
||||||
[](auto const& record) { return record.key; });
|
[](auto const& record) { return record.key; });
|
||||||
|
|
||||||
found_record = records.visit([&](auto content) -> Variant<Empty, Record, IndexRecord> {
|
found_record = records.visit([&](auto content) -> Variant<Empty, ObjectStoreRecord, IndexRecord> {
|
||||||
auto value = content.first_matching([&](auto const& content_record) {
|
auto value = content.first_matching([&](auto const& content_record) {
|
||||||
return Key::equals(content_record.key, temp_record_key);
|
return Key::equals(content_record.key, temp_record_key);
|
||||||
});
|
});
|
||||||
|
@ -1853,7 +1853,7 @@ GC::Ptr<IDBCursor> iterate_a_cursor(JS::Realm& realm, GC::Ref<IDBCursor> cursor,
|
||||||
// 1. Let serialized be found record’s value if source is an object store, or found record’s referenced value otherwise.
|
// 1. Let serialized be found record’s value if source is an object store, or found record’s referenced value otherwise.
|
||||||
auto serialized = source.visit(
|
auto serialized = source.visit(
|
||||||
[&](GC::Ref<ObjectStore>) {
|
[&](GC::Ref<ObjectStore>) {
|
||||||
return found_record.get<Record>().value;
|
return found_record.get<ObjectStoreRecord>().value;
|
||||||
},
|
},
|
||||||
[&](GC::Ref<Index> index) {
|
[&](GC::Ref<Index> index) {
|
||||||
return index->referenced_value(found_record.get<IndexRecord>());
|
return index->referenced_value(found_record.get<IndexRecord>());
|
||||||
|
|
|
@ -11,17 +11,12 @@
|
||||||
#include <LibJS/Heap/Cell.h>
|
#include <LibJS/Heap/Cell.h>
|
||||||
#include <LibJS/Runtime/Realm.h>
|
#include <LibJS/Runtime/Realm.h>
|
||||||
#include <LibWeb/IndexedDB/Internal/ObjectStore.h>
|
#include <LibWeb/IndexedDB/Internal/ObjectStore.h>
|
||||||
|
#include <LibWeb/IndexedDB/Internal/Record.h>
|
||||||
|
|
||||||
namespace Web::IndexedDB {
|
namespace Web::IndexedDB {
|
||||||
|
|
||||||
using KeyPath = Variant<String, Vector<String>>;
|
using KeyPath = Variant<String, Vector<String>>;
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#index-list-of-records
|
|
||||||
struct IndexRecord {
|
|
||||||
GC::Ref<Key> key;
|
|
||||||
GC::Ref<Key> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#index-construct
|
// https://w3c.github.io/IndexedDB/#index-construct
|
||||||
class Index : public JS::Cell {
|
class Index : public JS::Cell {
|
||||||
GC_CELL(Index, JS::Cell);
|
GC_CELL(Index, JS::Cell);
|
||||||
|
|
|
@ -57,7 +57,7 @@ bool ObjectStore::has_record_with_key(GC::Ref<Key> key)
|
||||||
return index != m_records.end();
|
return index != m_records.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectStore::store_a_record(Record const& record)
|
void ObjectStore::store_a_record(ObjectStoreRecord const& record)
|
||||||
{
|
{
|
||||||
m_records.append(record);
|
m_records.append(record);
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ u64 ObjectStore::count_records_in_range(GC::Ref<IDBKeyRange> range)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Record&> ObjectStore::first_in_range(GC::Ref<IDBKeyRange> range)
|
Optional<ObjectStoreRecord&> ObjectStore::first_in_range(GC::Ref<IDBKeyRange> range)
|
||||||
{
|
{
|
||||||
return m_records.first_matching([&](auto const& record) {
|
return m_records.first_matching([&](auto const& record) {
|
||||||
return range->is_in_range(record.key);
|
return range->is_in_range(record.key);
|
||||||
|
@ -89,9 +89,9 @@ void ObjectStore::clear_records()
|
||||||
m_records.clear();
|
m_records.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
GC::ConservativeVector<Record> ObjectStore::first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
|
GC::ConservativeVector<ObjectStoreRecord> ObjectStore::first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
|
||||||
{
|
{
|
||||||
GC::ConservativeVector<Record> records(range->heap());
|
GC::ConservativeVector<ObjectStoreRecord> records(range->heap());
|
||||||
for (auto const& record : m_records) {
|
for (auto const& record : m_records) {
|
||||||
if (range->is_in_range(record.key))
|
if (range->is_in_range(record.key))
|
||||||
records.append(record);
|
records.append(record);
|
||||||
|
|
|
@ -18,17 +18,12 @@
|
||||||
#include <LibWeb/IndexedDB/Internal/Database.h>
|
#include <LibWeb/IndexedDB/Internal/Database.h>
|
||||||
#include <LibWeb/IndexedDB/Internal/Index.h>
|
#include <LibWeb/IndexedDB/Internal/Index.h>
|
||||||
#include <LibWeb/IndexedDB/Internal/KeyGenerator.h>
|
#include <LibWeb/IndexedDB/Internal/KeyGenerator.h>
|
||||||
|
#include <LibWeb/IndexedDB/Internal/Record.h>
|
||||||
|
|
||||||
namespace Web::IndexedDB {
|
namespace Web::IndexedDB {
|
||||||
|
|
||||||
using KeyPath = Variant<String, Vector<String>>;
|
using KeyPath = Variant<String, Vector<String>>;
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#object-store-record
|
|
||||||
struct Record {
|
|
||||||
GC::Ref<Key> key;
|
|
||||||
HTML::SerializationRecord value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#object-store-construct
|
// https://w3c.github.io/IndexedDB/#object-store-construct
|
||||||
class ObjectStore : public JS::Cell {
|
class ObjectStore : public JS::Cell {
|
||||||
GC_CELL(ObjectStore, JS::Cell);
|
GC_CELL(ObjectStore, JS::Cell);
|
||||||
|
@ -48,15 +43,15 @@ public:
|
||||||
AK::HashMap<String, GC::Ref<Index>>& index_set() { return m_indexes; }
|
AK::HashMap<String, GC::Ref<Index>>& index_set() { return m_indexes; }
|
||||||
|
|
||||||
GC::Ref<Database> database() const { return m_database; }
|
GC::Ref<Database> database() const { return m_database; }
|
||||||
ReadonlySpan<Record> records() const { return m_records; }
|
ReadonlySpan<ObjectStoreRecord> records() const { return m_records; }
|
||||||
|
|
||||||
void remove_records_in_range(GC::Ref<IDBKeyRange> range);
|
void remove_records_in_range(GC::Ref<IDBKeyRange> range);
|
||||||
bool has_record_with_key(GC::Ref<Key> key);
|
bool has_record_with_key(GC::Ref<Key> key);
|
||||||
void store_a_record(Record const& record);
|
void store_a_record(ObjectStoreRecord const& record);
|
||||||
u64 count_records_in_range(GC::Ref<IDBKeyRange> range);
|
u64 count_records_in_range(GC::Ref<IDBKeyRange> range);
|
||||||
Optional<Record&> first_in_range(GC::Ref<IDBKeyRange> range);
|
Optional<ObjectStoreRecord&> first_in_range(GC::Ref<IDBKeyRange> range);
|
||||||
void clear_records();
|
void clear_records();
|
||||||
GC::ConservativeVector<Record> first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count);
|
GC::ConservativeVector<ObjectStoreRecord> first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void visit_edges(Visitor&) override;
|
virtual void visit_edges(Visitor&) override;
|
||||||
|
@ -80,7 +75,7 @@ private:
|
||||||
Optional<KeyGenerator> m_key_generator;
|
Optional<KeyGenerator> m_key_generator;
|
||||||
|
|
||||||
// An object store has a list of records
|
// An object store has a list of records
|
||||||
Vector<Record> m_records;
|
Vector<ObjectStoreRecord> m_records;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
27
Libraries/LibWeb/IndexedDB/Internal/Record.h
Normal file
27
Libraries/LibWeb/IndexedDB/Internal/Record.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, stelar7 <dudedbz@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGC/Ptr.h>
|
||||||
|
#include <LibWeb/HTML/StructuredSerializeTypes.h>
|
||||||
|
#include <LibWeb/IndexedDB/Internal/Key.h>
|
||||||
|
|
||||||
|
namespace Web::IndexedDB {
|
||||||
|
|
||||||
|
// https://w3c.github.io/IndexedDB/#object-store-record
|
||||||
|
struct ObjectStoreRecord {
|
||||||
|
GC::Ref<Key> key;
|
||||||
|
HTML::SerializationRecord value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://w3c.github.io/IndexedDB/#index-list-of-records
|
||||||
|
struct IndexRecord {
|
||||||
|
GC::Ref<Key> key;
|
||||||
|
GC::Ref<Key> value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue