mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 09:12:13 -05:00
LibWeb: Turn IDB internal Key into a GC type
This commit is contained in:
parent
5b9d18b462
commit
47b8a015a7
Notes:
github-actions[bot]
2025-01-14 22:47:44 +00:00
Author: https://github.com/stelar7 Commit: https://github.com/LadybirdBrowser/ladybird/commit/47b8a015a78 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3190 Reviewed-by: https://github.com/Lubrsi Reviewed-by: https://github.com/gmta ✅
4 changed files with 52 additions and 30 deletions
|
@ -166,7 +166,7 @@ bool fire_a_version_change_event(JS::Realm& realm, FlyString const& event_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#convert-value-to-key
|
// https://w3c.github.io/IndexedDB/#convert-value-to-key
|
||||||
ErrorOr<Key> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<JS::Value> seen)
|
ErrorOr<GC::Ref<Key>> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<JS::Value> seen)
|
||||||
{
|
{
|
||||||
// 1. If seen was not given, then let seen be a new empty set.
|
// 1. If seen was not given, then let seen be a new empty set.
|
||||||
// NOTE: This is handled by the caller.
|
// NOTE: This is handled by the caller.
|
||||||
|
@ -185,7 +185,7 @@ ErrorOr<Key> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<
|
||||||
return Error::from_string_literal("NaN key");
|
return Error::from_string_literal("NaN key");
|
||||||
|
|
||||||
// 2. Otherwise, return a new key with type number and value input.
|
// 2. Otherwise, return a new key with type number and value input.
|
||||||
return Key::create_number(input.as_double());
|
return Key::create_number(realm, input.as_double());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - If input is a Date (has a [[DateValue]] internal slot)
|
// - If input is a Date (has a [[DateValue]] internal slot)
|
||||||
|
@ -200,14 +200,14 @@ ErrorOr<Key> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<
|
||||||
return Error::from_string_literal("NaN key");
|
return Error::from_string_literal("NaN key");
|
||||||
|
|
||||||
// 3. Otherwise, return a new key with type date and value ms.
|
// 3. Otherwise, return a new key with type date and value ms.
|
||||||
return Key::create_date(ms);
|
return Key::create_date(realm, ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - If Type(input) is String
|
// - If Type(input) is String
|
||||||
if (input.is_string()) {
|
if (input.is_string()) {
|
||||||
|
|
||||||
// 1. Return a new key with type string and value input.
|
// 1. Return a new key with type string and value input.
|
||||||
return Key::create_string(input.as_string().utf8_string());
|
return Key::create_string(realm, input.as_string().utf8_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - If input is a buffer source type
|
// - If input is a buffer source type
|
||||||
|
@ -217,7 +217,7 @@ ErrorOr<Key> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<
|
||||||
auto data_buffer = TRY(WebIDL::get_buffer_source_copy(input.as_object()));
|
auto data_buffer = TRY(WebIDL::get_buffer_source_copy(input.as_object()));
|
||||||
|
|
||||||
// 2. Return a new key with type binary and value bytes.
|
// 2. Return a new key with type binary and value bytes.
|
||||||
return Key::create_binary(data_buffer);
|
return Key::create_binary(realm, data_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - If input is an Array exotic object
|
// - If input is an Array exotic object
|
||||||
|
@ -234,7 +234,7 @@ ErrorOr<Key> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<
|
||||||
seen.append(input);
|
seen.append(input);
|
||||||
|
|
||||||
// 3. Let keys be a new empty list.
|
// 3. Let keys be a new empty list.
|
||||||
Vector<Key> keys;
|
Vector<GC::Root<Key>> keys;
|
||||||
|
|
||||||
// 4. Let index be 0.
|
// 4. Let index be 0.
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
|
@ -275,7 +275,7 @@ ErrorOr<Key> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector<
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Return a new array key with value keys.
|
// 6. Return a new array key with value keys.
|
||||||
return Key::create_array(keys);
|
return Key::create_array(realm, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - Otherwise
|
// - Otherwise
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Web::IndexedDB {
|
||||||
|
|
||||||
WebIDL::ExceptionOr<GC::Ref<IDBDatabase>> open_a_database_connection(JS::Realm&, StorageAPI::StorageKey, String, Optional<u64>, GC::Ref<IDBRequest>);
|
WebIDL::ExceptionOr<GC::Ref<IDBDatabase>> open_a_database_connection(JS::Realm&, StorageAPI::StorageKey, String, Optional<u64>, GC::Ref<IDBRequest>);
|
||||||
bool fire_a_version_change_event(JS::Realm&, FlyString const&, GC::Ref<DOM::EventTarget>, u64, Optional<u64>);
|
bool fire_a_version_change_event(JS::Realm&, FlyString const&, GC::Ref<DOM::EventTarget>, u64, Optional<u64>);
|
||||||
ErrorOr<Key> convert_a_value_to_a_key(JS::Realm&, JS::Value, Vector<JS::Value> = {});
|
ErrorOr<GC::Ref<Key>> convert_a_value_to_a_key(JS::Realm&, JS::Value, Vector<JS::Value> = {});
|
||||||
void close_a_database_connection(IDBDatabase&, bool forced = false);
|
void close_a_database_connection(IDBDatabase&, bool forced = false);
|
||||||
void upgrade_a_database(JS::Realm&, GC::Ref<IDBDatabase>, u64, GC::Ref<IDBRequest>);
|
void upgrade_a_database(JS::Realm&, GC::Ref<IDBDatabase>, u64, GC::Ref<IDBRequest>);
|
||||||
WebIDL::ExceptionOr<u64> delete_a_database(JS::Realm&, StorageAPI::StorageKey, String, GC::Ref<IDBRequest>);
|
WebIDL::ExceptionOr<u64> delete_a_database(JS::Realm&, StorageAPI::StorageKey, String, GC::Ref<IDBRequest>);
|
||||||
|
|
|
@ -10,14 +10,23 @@
|
||||||
|
|
||||||
namespace Web::IndexedDB {
|
namespace Web::IndexedDB {
|
||||||
|
|
||||||
|
GC_DEFINE_ALLOCATOR(Key);
|
||||||
|
|
||||||
|
Key::~Key() = default;
|
||||||
|
|
||||||
|
GC::Ref<Key> Key::create(JS::Realm& realm, KeyType key, KeyValue value)
|
||||||
|
{
|
||||||
|
return realm.create<Key>(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#compare-two-keys
|
// https://w3c.github.io/IndexedDB/#compare-two-keys
|
||||||
i8 Key::compare_two_keys(Key a, Key b)
|
i8 Key::compare_two_keys(GC::Ref<Key> a, GC::Ref<Key> b)
|
||||||
{
|
{
|
||||||
// 1. Let ta be the type of a.
|
// 1. Let ta be the type of a.
|
||||||
auto ta = a.type();
|
auto ta = a->type();
|
||||||
|
|
||||||
// 2. Let tb be the type of b.
|
// 2. Let tb be the type of b.
|
||||||
auto tb = b.type();
|
auto tb = b->type();
|
||||||
|
|
||||||
// 3. If ta does not equal tb, then run these steps:
|
// 3. If ta does not equal tb, then run these steps:
|
||||||
if (ta != tb) {
|
if (ta != tb) {
|
||||||
|
@ -57,10 +66,10 @@ i8 Key::compare_two_keys(Key a, Key b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Let va be the value of a.
|
// 4. Let va be the value of a.
|
||||||
auto va = a.value();
|
auto va = a->value();
|
||||||
|
|
||||||
// 5. Let vb be the value of b.
|
// 5. Let vb be the value of b.
|
||||||
auto vb = b.value();
|
auto vb = b->value();
|
||||||
|
|
||||||
// 6. Switch on ta:
|
// 6. Switch on ta:
|
||||||
switch (ta) {
|
switch (ta) {
|
||||||
|
@ -116,8 +125,8 @@ i8 Key::compare_two_keys(Key a, Key b)
|
||||||
}
|
}
|
||||||
// array
|
// array
|
||||||
case KeyType::Array: {
|
case KeyType::Array: {
|
||||||
auto a_value = va.get<Vector<Key>>();
|
auto a_value = va.get<Vector<GC::Root<Key>>>();
|
||||||
auto b_value = vb.get<Vector<Key>>();
|
auto b_value = vb.get<Vector<GC::Root<Key>>>();
|
||||||
|
|
||||||
// 1. Let length be the lesser of va’s size and vb’s size.
|
// 1. Let length be the lesser of va’s size and vb’s size.
|
||||||
auto length = min(a_value.size(), b_value.size());
|
auto length = min(a_value.size(), b_value.size());
|
||||||
|
@ -128,7 +137,7 @@ i8 Key::compare_two_keys(Key a, Key b)
|
||||||
// 3. While i is less than length, then:
|
// 3. While i is less than length, then:
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
// 1. Let c be the result of recursively comparing two keys with va[i] and vb[i].
|
// 1. Let c be the result of recursively comparing two keys with va[i] and vb[i].
|
||||||
auto c = compare_two_keys(a_value[i], b_value[i]);
|
auto c = compare_two_keys(*a_value[i], *b_value[i]);
|
||||||
|
|
||||||
// 2. If c is not 0, return c.
|
// 2. If c is not 0, return c.
|
||||||
if (c != 0)
|
if (c != 0)
|
||||||
|
|
|
@ -10,11 +10,25 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Variant.h>
|
#include <AK/Variant.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibGC/Ptr.h>
|
||||||
|
#include <LibJS/Heap/Cell.h>
|
||||||
|
#include <LibJS/Runtime/Realm.h>
|
||||||
|
#include <LibWeb/Bindings/PlatformObject.h>
|
||||||
|
|
||||||
namespace Web::IndexedDB {
|
namespace Web::IndexedDB {
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#key-construct
|
// https://w3c.github.io/IndexedDB/#key-construct
|
||||||
class Key {
|
class Key : public JS::Cell {
|
||||||
|
GC_CELL(Key, JS::Cell);
|
||||||
|
GC_DECLARE_ALLOCATOR(Key);
|
||||||
|
|
||||||
|
// A key also has an associated value, which will be either:
|
||||||
|
// * an unrestricted double if type is number or date,
|
||||||
|
// * a DOMString if type is string,
|
||||||
|
// * a byte sequence if type is binary,
|
||||||
|
// * a list of other keys if type is array.
|
||||||
|
using KeyValue = Variant<double, AK::String, ByteBuffer, Vector<GC::Root<Key>>>;
|
||||||
|
|
||||||
// A key has an associated type which is one of: number, date, string, binary, or array.
|
// A key has an associated type which is one of: number, date, string, binary, or array.
|
||||||
enum KeyType {
|
enum KeyType {
|
||||||
Number,
|
Number,
|
||||||
|
@ -24,24 +38,23 @@ class Key {
|
||||||
Array,
|
Array,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A key also has an associated value, which will be either:
|
|
||||||
// * an unrestricted double if type is number or date,
|
|
||||||
// * a DOMString if type is string,
|
|
||||||
// * a byte sequence if type is binary,
|
|
||||||
// * a list of other keys if type is array.
|
|
||||||
using KeyValue = Variant<double, AK::String, ByteBuffer, Vector<Key>>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
[[nodiscard]] static GC::Ref<Key> create(JS::Realm&, KeyType, KeyValue);
|
||||||
|
virtual ~Key();
|
||||||
|
|
||||||
[[nodiscard]] KeyType type() { return m_type; }
|
[[nodiscard]] KeyType type() { return m_type; }
|
||||||
[[nodiscard]] KeyValue value() { return m_value; }
|
[[nodiscard]] KeyValue value() { return m_value; }
|
||||||
|
|
||||||
[[nodiscard]] static Key create_number(double value) { return Key(Number, value); }
|
[[nodiscard]] static GC::Ref<Key> create_number(JS::Realm& realm, double value) { return create(realm, Number, value); }
|
||||||
[[nodiscard]] static Key create_date(double value) { return Key(Date, value); }
|
[[nodiscard]] static GC::Ref<Key> create_date(JS::Realm& realm, double value) { return create(realm, Date, value); }
|
||||||
[[nodiscard]] static Key create_string(AK::String const& value) { return Key(String, value); }
|
[[nodiscard]] static GC::Ref<Key> create_string(JS::Realm& realm, AK::String const& value) { return create(realm, String, value); }
|
||||||
[[nodiscard]] static Key create_binary(ByteBuffer const& value) { return Key(Binary, value); }
|
[[nodiscard]] static GC::Ref<Key> create_binary(JS::Realm& realm, ByteBuffer const& value) { return create(realm, Binary, value); }
|
||||||
[[nodiscard]] static Key create_array(Vector<Key> const& value) { return Key(Array, value); }
|
[[nodiscard]] static GC::Ref<Key> create_array(JS::Realm& realm, Vector<GC::Root<Key>> const& value) { return create(realm, Array, value); }
|
||||||
|
|
||||||
[[nodiscard]] static i8 compare_two_keys(Key a, Key b);
|
[[nodiscard]] static i8 compare_two_keys(GC::Ref<Key> a, GC::Ref<Key> b);
|
||||||
|
[[nodiscard]] static bool equals(GC::Ref<Key> a, GC::Ref<Key> b) { return compare_two_keys(a, b) == 0; }
|
||||||
|
[[nodiscard]] static bool less_than(GC::Ref<Key> a, GC::Ref<Key> b) { return compare_two_keys(a, b) < 0; }
|
||||||
|
[[nodiscard]] static bool greater_than(GC::Ref<Key> a, GC::Ref<Key> b) { return compare_two_keys(a, b) > 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Key(KeyType type, KeyValue value)
|
Key(KeyType type, KeyValue value)
|
||||||
|
|
Loading…
Reference in a new issue