mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-31 13:19:05 +00:00
LibWeb: Implement convert_a_value_to_a_key for IndexedDB
This commit is contained in:
parent
34479e5664
commit
c43b93e6fa
Notes:
github-actions[bot]
2024-11-25 10:54:55 +00:00
Author: https://github.com/stelar7
Commit: c43b93e6fa
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2279
Reviewed-by: https://github.com/gmta
Reviewed-by: https://github.com/tcl3
2 changed files with 127 additions and 0 deletions
|
@ -4,6 +4,12 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
|
#include <LibJS/Runtime/Array.h>
|
||||||
|
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||||
|
#include <LibJS/Runtime/DataView.h>
|
||||||
|
#include <LibJS/Runtime/Date.h>
|
||||||
|
#include <LibJS/Runtime/TypedArray.h>
|
||||||
#include <LibJS/Runtime/VM.h>
|
#include <LibJS/Runtime/VM.h>
|
||||||
#include <LibWeb/DOM/EventDispatcher.h>
|
#include <LibWeb/DOM/EventDispatcher.h>
|
||||||
#include <LibWeb/HTML/EventNames.h>
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
|
@ -13,6 +19,7 @@
|
||||||
#include <LibWeb/IndexedDB/Internal/ConnectionQueueHandler.h>
|
#include <LibWeb/IndexedDB/Internal/ConnectionQueueHandler.h>
|
||||||
#include <LibWeb/IndexedDB/Internal/Database.h>
|
#include <LibWeb/IndexedDB/Internal/Database.h>
|
||||||
#include <LibWeb/StorageAPI/StorageKey.h>
|
#include <LibWeb/StorageAPI/StorageKey.h>
|
||||||
|
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||||
|
|
||||||
namespace Web::IndexedDB {
|
namespace Web::IndexedDB {
|
||||||
|
|
||||||
|
@ -141,4 +148,122 @@ bool fire_a_version_change_event(JS::Realm& realm, FlyString const& event_name,
|
||||||
return legacy_output_did_listeners_throw_flag;
|
return legacy_output_did_listeners_throw_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
// 1. If seen was not given, then let seen be a new empty set.
|
||||||
|
// NOTE: This is handled by the caller.
|
||||||
|
|
||||||
|
// 2. If seen contains input, then return invalid.
|
||||||
|
if (seen.contains_slow(input))
|
||||||
|
return Error::from_string_literal("Already seen key");
|
||||||
|
|
||||||
|
// 3. Jump to the appropriate step below:
|
||||||
|
|
||||||
|
// - If Type(input) is Number
|
||||||
|
if (input.is_number()) {
|
||||||
|
|
||||||
|
// 1. If input is NaN then return invalid.
|
||||||
|
if (input.is_nan())
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// - If input is a Date (has a [[DateValue]] internal slot)
|
||||||
|
if (input.is_object() && is<JS::Date>(input.as_object())) {
|
||||||
|
|
||||||
|
// 1. Let ms be the value of input’s [[DateValue]] internal slot.
|
||||||
|
auto& date = static_cast<JS::Date&>(input.as_object());
|
||||||
|
auto ms = date.date_value();
|
||||||
|
|
||||||
|
// 2. If ms is NaN then return invalid.
|
||||||
|
if (isnan(ms))
|
||||||
|
return Error::from_string_literal("NaN key");
|
||||||
|
|
||||||
|
// 3. Otherwise, return a new key with type date and value ms.
|
||||||
|
return Key::create_date(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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// - If input is a buffer source type
|
||||||
|
if (input.is_object() && (is<JS::TypedArrayBase>(input.as_object()) || is<JS::ArrayBuffer>(input.as_object()) || is<JS::DataView>(input.as_object()))) {
|
||||||
|
|
||||||
|
// 1. Let bytes be the result of getting a copy of the bytes held by the buffer source input. Rethrow any exceptions.
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - If input is an Array exotic object
|
||||||
|
if (input.is_object() && is<JS::Array>(input.as_object())) {
|
||||||
|
|
||||||
|
// 1. Let len be ? ToLength( ? Get(input, "length")).
|
||||||
|
auto maybe_length = length_of_array_like(realm.vm(), input.as_object());
|
||||||
|
if (maybe_length.is_error())
|
||||||
|
return Error::from_string_literal("Failed to get length of array-like object");
|
||||||
|
|
||||||
|
auto length = maybe_length.release_value();
|
||||||
|
|
||||||
|
// 2. Append input to seen.
|
||||||
|
seen.append(input);
|
||||||
|
|
||||||
|
// 3. Let keys be a new empty list.
|
||||||
|
Vector<Key> keys;
|
||||||
|
|
||||||
|
// 4. Let index be 0.
|
||||||
|
u64 index = 0;
|
||||||
|
|
||||||
|
// 5. While index is less than len:
|
||||||
|
while (index < length) {
|
||||||
|
// 1. Let hop be ? HasOwnProperty(input, index).
|
||||||
|
auto maybe_hop = input.as_object().has_own_property(index);
|
||||||
|
if (maybe_hop.is_error())
|
||||||
|
return Error::from_string_literal("Failed to check if array-like object has property");
|
||||||
|
|
||||||
|
auto hop = maybe_hop.release_value();
|
||||||
|
|
||||||
|
// 2. If hop is false, return invalid.
|
||||||
|
if (!hop)
|
||||||
|
return Error::from_string_literal("Array-like object has no property");
|
||||||
|
|
||||||
|
// 3. Let entry be ? Get(input, index).
|
||||||
|
auto maybe_entry = input.as_object().get(index);
|
||||||
|
if (maybe_entry.is_error())
|
||||||
|
return Error::from_string_literal("Failed to get property of array-like object");
|
||||||
|
|
||||||
|
// 4. Let key be the result of converting a value to a key with arguments entry and seen.
|
||||||
|
auto maybe_key = convert_a_value_to_a_key(realm, maybe_entry.release_value(), seen);
|
||||||
|
|
||||||
|
// 5. ReturnIfAbrupt(key).
|
||||||
|
// 6. If key is invalid abort these steps and return invalid.
|
||||||
|
if (maybe_key.is_error())
|
||||||
|
return maybe_key.release_error();
|
||||||
|
|
||||||
|
auto key = maybe_key.release_value();
|
||||||
|
|
||||||
|
// 7. Append key to keys.
|
||||||
|
keys.append(key);
|
||||||
|
|
||||||
|
// 8. Increase index by 1.
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Return a new array key with value keys.
|
||||||
|
return Key::create_array(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Otherwise
|
||||||
|
// 1. Return invalid.
|
||||||
|
return Error::from_string_literal("Unknown key type");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,13 @@
|
||||||
|
|
||||||
#include <LibJS/Runtime/Realm.h>
|
#include <LibJS/Runtime/Realm.h>
|
||||||
#include <LibWeb/IndexedDB/IDBRequest.h>
|
#include <LibWeb/IndexedDB/IDBRequest.h>
|
||||||
|
#include <LibWeb/IndexedDB/Internal/Key.h>
|
||||||
#include <LibWeb/StorageAPI/StorageKey.h>
|
#include <LibWeb/StorageAPI/StorageKey.h>
|
||||||
|
|
||||||
namespace Web::IndexedDB {
|
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> = {});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue