diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp index 8033a803db9..43dc098db5d 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -37,6 +38,12 @@ namespace Web::IndexedDB { +#if defined(AK_COMPILER_CLANG) +# define MAX_KEY_GENERATOR_VALUE AK::exp2(53.) +#else +constexpr double const MAX_KEY_GENERATOR_VALUE { __builtin_exp2(53) }; +#endif + // https://w3c.github.io/IndexedDB/#open-a-database-connection WebIDL::ExceptionOr> open_a_database_connection(JS::Realm& realm, StorageAPI::StorageKey storage_key, String name, Optional maybe_version, GC::Ref request) { @@ -1208,4 +1215,24 @@ GC::Ref asynchronously_execute_a_request(JS::Realm& realm, IDBReques return request; } +// https://w3c.github.io/IndexedDB/#generate-a-key +ErrorOr generate_a_key(GC::Ref store) +{ + // 1. Let generator be store’s key generator. + auto generator = store->key_generator().value(); + + // 2. Let key be generator’s current number. + auto key = generator.current_number(); + + // 3. If key is greater than 2^53 (9007199254740992), then return failure. + if (key > static_cast(MAX_KEY_GENERATOR_VALUE)) + return Error::from_string_literal("Key is greater than 2^53"); + + // 4. Increase generator’s current number by 1. + generator.increment(1); + + // 5. Return key. + return key; +} + } diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h index c1e01aabed4..9b16ede3d9d 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h @@ -36,5 +36,6 @@ bool check_that_a_key_could_be_injected_into_a_value(JS::Realm&, JS::Value, KeyP void fire_an_error_event(JS::Realm&, GC::Ref); void fire_a_success_event(JS::Realm&, GC::Ref); GC::Ref asynchronously_execute_a_request(JS::Realm&, IDBRequestSource, GC::Ref()>>, GC::Ptr = nullptr); +ErrorOr generate_a_key(GC::Ref); } diff --git a/Libraries/LibWeb/IndexedDB/Internal/KeyGenerator.h b/Libraries/LibWeb/IndexedDB/Internal/KeyGenerator.h index 5f7449a44cc..dd1fb5518cf 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/KeyGenerator.h +++ b/Libraries/LibWeb/IndexedDB/Internal/KeyGenerator.h @@ -13,13 +13,16 @@ namespace Web::IndexedDB { // https://w3c.github.io/IndexedDB/#key-generator-construct class KeyGenerator { public: + [[nodiscard]] u64 current_number() const { return m_current_number; } + void increment(u64 amount) { m_current_number += amount; } + void set(u64 value) { m_current_number = value; } + private: // A key generator has a current number. // The current number is always a positive integer less than or equal to 2^53 (9007199254740992) + 1. // The initial value of a key generator's current number is 1, set when the associated object store is created. // The current number is incremented as keys are generated, and may be updated to a specific value by using explicit keys. - // FIXME: Implement support for KeyGenerator in ObjectStore. - [[maybe_unused]] u64 current_number { 1 }; + u64 m_current_number { 1 }; }; }