diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp index b080d285cc5..c14fcf806c4 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp @@ -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 -ErrorOr convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector seen) +ErrorOr> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector seen) { // 1. If seen was not given, then let seen be a new empty set. // NOTE: This is handled by the caller. @@ -185,7 +185,7 @@ ErrorOr convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector< return Error::from_string_literal("NaN key"); // 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) @@ -200,14 +200,14 @@ ErrorOr convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector< return Error::from_string_literal("NaN key"); // 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 (input.is_string()) { // 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 @@ -217,7 +217,7 @@ ErrorOr 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())); // 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 @@ -234,7 +234,7 @@ ErrorOr convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector< seen.append(input); // 3. Let keys be a new empty list. - Vector keys; + Vector> keys; // 4. Let index be 0. u64 index = 0; @@ -275,7 +275,7 @@ ErrorOr convert_a_value_to_a_key(JS::Realm& realm, JS::Value input, Vector< } // 6. Return a new array key with value keys. - return Key::create_array(keys); + return Key::create_array(realm, keys); } // - Otherwise diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h index ae235611ed4..c5803b906d8 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h @@ -15,7 +15,7 @@ namespace Web::IndexedDB { WebIDL::ExceptionOr> open_a_database_connection(JS::Realm&, StorageAPI::StorageKey, String, Optional, GC::Ref); bool fire_a_version_change_event(JS::Realm&, FlyString const&, GC::Ref, u64, Optional); -ErrorOr convert_a_value_to_a_key(JS::Realm&, JS::Value, Vector = {}); +ErrorOr> convert_a_value_to_a_key(JS::Realm&, JS::Value, Vector = {}); void close_a_database_connection(IDBDatabase&, bool forced = false); void upgrade_a_database(JS::Realm&, GC::Ref, u64, GC::Ref); WebIDL::ExceptionOr delete_a_database(JS::Realm&, StorageAPI::StorageKey, String, GC::Ref); diff --git a/Libraries/LibWeb/IndexedDB/Internal/Key.cpp b/Libraries/LibWeb/IndexedDB/Internal/Key.cpp index 8fe25457386..df054d1c90c 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Key.cpp +++ b/Libraries/LibWeb/IndexedDB/Internal/Key.cpp @@ -10,14 +10,23 @@ namespace Web::IndexedDB { +GC_DEFINE_ALLOCATOR(Key); + +Key::~Key() = default; + +GC::Ref Key::create(JS::Realm& realm, KeyType key, KeyValue value) +{ + return realm.create(key, value); +} + // https://w3c.github.io/IndexedDB/#compare-two-keys -i8 Key::compare_two_keys(Key a, Key b) +i8 Key::compare_two_keys(GC::Ref a, GC::Ref b) { // 1. Let ta be the type of a. - auto ta = a.type(); + auto ta = a->type(); // 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: if (ta != tb) { @@ -57,10 +66,10 @@ i8 Key::compare_two_keys(Key a, Key b) } // 4. Let va be the value of a. - auto va = a.value(); + auto va = a->value(); // 5. Let vb be the value of b. - auto vb = b.value(); + auto vb = b->value(); // 6. Switch on ta: switch (ta) { @@ -116,8 +125,8 @@ i8 Key::compare_two_keys(Key a, Key b) } // array case KeyType::Array: { - auto a_value = va.get>(); - auto b_value = vb.get>(); + auto a_value = va.get>>(); + auto b_value = vb.get>>(); // 1. Let length be the lesser of va’s size and vb’s 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: while (i < length) { // 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. if (c != 0) diff --git a/Libraries/LibWeb/IndexedDB/Internal/Key.h b/Libraries/LibWeb/IndexedDB/Internal/Key.h index 1f80e28bd36..288a7485ee5 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Key.h +++ b/Libraries/LibWeb/IndexedDB/Internal/Key.h @@ -10,11 +10,25 @@ #include #include #include +#include +#include +#include +#include namespace Web::IndexedDB { // 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>>; + // A key has an associated type which is one of: number, date, string, binary, or array. enum KeyType { Number, @@ -24,24 +38,23 @@ class Key { 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>; - public: + [[nodiscard]] static GC::Ref create(JS::Realm&, KeyType, KeyValue); + virtual ~Key(); + [[nodiscard]] KeyType type() { return m_type; } [[nodiscard]] KeyValue value() { return m_value; } - [[nodiscard]] static Key create_number(double value) { return Key(Number, value); } - [[nodiscard]] static Key create_date(double value) { return Key(Date, value); } - [[nodiscard]] static Key create_string(AK::String const& value) { return Key(String, value); } - [[nodiscard]] static Key create_binary(ByteBuffer const& value) { return Key(Binary, value); } - [[nodiscard]] static Key create_array(Vector const& value) { return Key(Array, value); } + [[nodiscard]] static GC::Ref create_number(JS::Realm& realm, double value) { return create(realm, Number, value); } + [[nodiscard]] static GC::Ref create_date(JS::Realm& realm, double value) { return create(realm, Date, value); } + [[nodiscard]] static GC::Ref create_string(JS::Realm& realm, AK::String const& value) { return create(realm, String, value); } + [[nodiscard]] static GC::Ref create_binary(JS::Realm& realm, ByteBuffer const& value) { return create(realm, Binary, value); } + [[nodiscard]] static GC::Ref create_array(JS::Realm& realm, Vector> 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 a, GC::Ref b); + [[nodiscard]] static bool equals(GC::Ref a, GC::Ref b) { return compare_two_keys(a, b) == 0; } + [[nodiscard]] static bool less_than(GC::Ref a, GC::Ref b) { return compare_two_keys(a, b) < 0; } + [[nodiscard]] static bool greater_than(GC::Ref a, GC::Ref b) { return compare_two_keys(a, b) > 0; } private: Key(KeyType type, KeyValue value)