From f36c4d88ffe5b5991f6426f764309822aefe6cd3 Mon Sep 17 00:00:00 2001 From: stelar7 Date: Fri, 11 Apr 2025 10:46:21 +0200 Subject: [PATCH] LibWeb/IDB: Implement convert_a_value_to_a_multi_entry_key --- .../LibWeb/IndexedDB/Internal/Algorithms.cpp | 55 +++++++++++++++++++ .../LibWeb/IndexedDB/Internal/Algorithms.h | 1 + 2 files changed, 56 insertions(+) diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp index ec1de4e3a12..c1533bc7ff7 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp @@ -800,4 +800,59 @@ WebIDL::ExceptionOr clone_in_realm(JS::Realm& target_realm, JS::Value return clone; } +// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-multientry-key +WebIDL::ExceptionOr>> convert_a_value_to_a_multi_entry_key(JS::Realm& realm, JS::Value value) +{ + // 1. If input is an Array exotic object, then: + if (value.is_object() && is(value.as_object())) { + + // 1. Let len be ? ToLength( ? Get(input, "length")). + auto len = TRY(length_of_array_like(realm.vm(), value.as_object())); + + // 2. Let seen be a new set containing only input. + Vector seen { value }; + + // 3. Let keys be a new empty list. + Vector> keys; + + // 4. Let index be 0. + u64 index = 0; + + // 5. While index is less than len: + while (index < len) { + + // 1. Let entry be Get(input, index). + auto maybe_entry = value.as_object().get(index); + + // 2. If entry is not an abrupt completion, then: + if (!maybe_entry.is_error()) { + + // 1. Let key be the result of converting a value to a key with arguments entry and seen. + auto completion_key = convert_a_value_to_a_key(realm, maybe_entry.release_value(), seen); + + // 2. If key is not invalid or an abrupt completion, and there is no item in keys equal to key, then append key to keys. + if (!completion_key.is_error()) { + auto maybe_key = completion_key.release_value(); + + if (!maybe_key.is_error()) { + auto key = maybe_key.release_value(); + + if (!keys.contains_slow(key)) + keys.append(key); + } + } + } + + // 3. Increase index by 1. + index++; + } + + // 6. Return a new array key with value set to keys. + return Key::create_array(realm, keys); + } + + // 2. Otherwise, return the result of converting a value to a key with argument input. Rethrow any exceptions. + return convert_a_value_to_a_key(realm, value); +} + } diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h index 980ec3366ad..9b0c505cc03 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h @@ -29,5 +29,6 @@ bool is_valid_key_path(KeyPath const&); GC::Ref create_a_sorted_name_list(JS::Realm&, Vector); void commit_a_transaction(JS::Realm&, GC::Ref); WebIDL::ExceptionOr clone_in_realm(JS::Realm&, JS::Value, GC::Ref); +WebIDL::ExceptionOr>> convert_a_value_to_a_multi_entry_key(JS::Realm&, JS::Value); }