mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-22 09:18:55 +00:00
LibWeb/IDB: Implement create_a_request_to_retrieve_multiple_items
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
This commit is contained in:
parent
2557e85407
commit
fde5dc7491
Notes:
github-actions[bot]
2025-08-27 14:14:36 +00:00
Author: https://github.com/stelar7
Commit: fde5dc7491
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5385
Reviewed-by: https://github.com/gmta ✅
4 changed files with 117 additions and 291 deletions
|
@ -206,135 +206,17 @@ WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBIndex::get_key(JS::Value query)
|
|||
// https://w3c.github.io/IndexedDB/#dom-idbindex-getall
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBIndex::get_all(Optional<JS::Value> query_or_options, Optional<WebIDL::UnsignedLong> count)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. Let transaction be this’s transaction.
|
||||
auto transaction = this->transaction();
|
||||
|
||||
// 2. Let index be this’s index.
|
||||
auto index = this->index();
|
||||
|
||||
// FIXME: 3. If index or index’s object store has been deleted, throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while getting all"_utf16);
|
||||
|
||||
// 5. Let range be a key range.
|
||||
GC::Ptr<IDBKeyRange> range;
|
||||
|
||||
// 6. Let direction be a cursor direction.
|
||||
Bindings::IDBCursorDirection direction = Bindings::IDBCursorDirection::Next;
|
||||
|
||||
// 7. If running is a potentially valid key range with query_or_options is true, then:
|
||||
if (is_a_potentially_valid_key_range(realm, *query_or_options)) {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, query_or_options));
|
||||
|
||||
// 2. Set direction to "next".
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
}
|
||||
|
||||
// 8. Else:
|
||||
else {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options["query"]. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, TRY(query_or_options->get(vm, "query"_utf16))));
|
||||
|
||||
// 2. Set count to query_or_options["count"].
|
||||
count = TRY(TRY(query_or_options->get(vm, "count"_utf16)).to_u32(vm));
|
||||
|
||||
// 3. Set direction to query_or_options["direction"].
|
||||
auto direction_value = TRY(TRY(query_or_options->get(vm, "direction"_utf16)).to_string(vm));
|
||||
if (direction_value == "next"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
} else if (direction_value == "nextunique"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Nextunique;
|
||||
} else if (direction_value == "prev"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Prev;
|
||||
} else if (direction_value == "prevunique"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Prevunique;
|
||||
} else {
|
||||
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid direction value"_string };
|
||||
}
|
||||
}
|
||||
|
||||
// 9. Let operation be an algorithm to run retrieve multiple items from an index with the current Realm record, index, range, "value", direction and count if given.
|
||||
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [&realm, index, range, direction, count] -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_index(realm, index, GC::Ref(*range), RecordKind::Value, direction, count);
|
||||
});
|
||||
|
||||
// 10. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
auto result = asynchronously_execute_a_request(realm, GC::Ref(*this), operation);
|
||||
dbgln_if(IDB_DEBUG, "Executing request for get all with uuid {}", result->uuid());
|
||||
return result;
|
||||
// 1. Return the result of creating a request to retrieve multiple items with the current Realm record, this,
|
||||
// "value", queryOrOptions, and count if given. Rethrow any exceptions.
|
||||
return create_a_request_to_retrieve_multiple_items(realm(), GC::Ref(*this), RecordKind::Value, *query_or_options, count);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/IndexedDB/#dom-idbindex-getallkeys
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBIndex::get_all_keys(Optional<JS::Value> query_or_options, Optional<WebIDL::UnsignedLong> count)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. Let transaction be this’s transaction.
|
||||
auto transaction = this->transaction();
|
||||
|
||||
// 2. Let index be this’s index.
|
||||
auto index = this->index();
|
||||
|
||||
// FIXME: 3. If index or index’s object store has been deleted, throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while getting all keys"_utf16);
|
||||
|
||||
// 5. Let range be a key range.
|
||||
GC::Ptr<IDBKeyRange> range;
|
||||
|
||||
// 6. Let direction be a cursor direction.
|
||||
Bindings::IDBCursorDirection direction = Bindings::IDBCursorDirection::Next;
|
||||
|
||||
// 7. If running is a potentially valid key range with query_or_options is true, then:
|
||||
if (is_a_potentially_valid_key_range(realm, *query_or_options)) {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, query_or_options));
|
||||
|
||||
// 2. Set direction to "next".
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
}
|
||||
|
||||
// 8. Else:
|
||||
else {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options["query"]. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, TRY(query_or_options->get(vm, "query"_utf16))));
|
||||
|
||||
// 2. Set count to query_or_options["count"].
|
||||
count = TRY(TRY(query_or_options->get(vm, "count"_utf16)).to_u32(vm));
|
||||
|
||||
// 3. Set direction to query_or_options["direction"].
|
||||
auto direction_value = TRY(TRY(query_or_options->get(vm, "direction"_utf16)).to_string(vm));
|
||||
if (direction_value == "next"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
} else if (direction_value == "nextunique"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Nextunique;
|
||||
} else if (direction_value == "prev"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Prev;
|
||||
} else if (direction_value == "prevunique"_string) {
|
||||
direction = Bindings::IDBCursorDirection::Prevunique;
|
||||
} else {
|
||||
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid direction value"_string };
|
||||
}
|
||||
}
|
||||
|
||||
// 9. Let operation be an algorithm to run retrieve multiple items from an index with the current Realm record, index, range, "key", direction and count if given.
|
||||
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [&realm, index, range, direction, count] -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_index(realm, index, GC::Ref(*range), RecordKind::Key, direction, count);
|
||||
});
|
||||
|
||||
// 10. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
auto result = asynchronously_execute_a_request(realm, GC::Ref(*this), operation);
|
||||
dbgln_if(IDB_DEBUG, "Executing request for get all keys with uuid {}", result->uuid());
|
||||
return result;
|
||||
// 1. Return the result of creating a request to retrieve multiple items with the current Realm record, this, "key",
|
||||
// queryOrOptions, and count if given. Rethrow any exceptions.
|
||||
return create_a_request_to_retrieve_multiple_items(realm(), GC::Ref(*this), RecordKind::Key, *query_or_options, count);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/IndexedDB/#dom-idbindex-count
|
||||
|
@ -409,30 +291,15 @@ WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBIndex::open_key_cursor(JS::Value que
|
|||
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBIndex::get_all_records(IDBGetAllOptions const& options)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
// 1. Return the result of creating a request to retrieve multiple items with the current Realm record, this,
|
||||
// "record", and options. Rethrow any exceptions.
|
||||
|
||||
// 1. Let transaction be this’s transaction.
|
||||
auto transaction = this->transaction();
|
||||
auto converted_options = JS::Object::create(realm(), nullptr);
|
||||
MUST(converted_options->create_data_property("query"_utf16, options.query));
|
||||
MUST(converted_options->create_data_property("count"_utf16, options.count.has_value() ? JS::Value(options.count.value()) : JS::js_undefined()));
|
||||
MUST(converted_options->create_data_property("direction"_utf16, JS::PrimitiveString::create(realm().vm(), idl_enum_to_string(options.direction))));
|
||||
|
||||
// 2. Let index be this’s index.
|
||||
auto index = this->index();
|
||||
|
||||
// FIXME: 3. If index or index’s object store has been deleted, then throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while getting all records"_utf16);
|
||||
|
||||
// 5. Let range be the result of converting a value to a key range with options["query"]. Rethrow any exceptions.
|
||||
auto range = TRY(convert_a_value_to_a_key_range(realm, options.query));
|
||||
|
||||
// 6. Let operation be an algorithm to run retrieve multiple items from an index with the current Realm record, index, range, "record", options["direction"], and options["count"] if given.
|
||||
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [&realm, index, range, options]() -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_index(realm, index, GC::Ref(*range), RecordKind::Record, options.direction, options.count);
|
||||
});
|
||||
|
||||
// 7. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
return asynchronously_execute_a_request(realm, GC::Ref(*this), operation);
|
||||
return create_a_request_to_retrieve_multiple_items(realm(), GC::Ref(*this), RecordKind::Record, converted_options, {});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -562,68 +562,9 @@ WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBObjectStore::get_key(JS::Value query
|
|||
// https://w3c.github.io/IndexedDB/#dom-idbobjectstore-getall
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBObjectStore::get_all(Optional<JS::Value> query_or_options, Optional<WebIDL::UnsignedLong> count)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. Let transaction be this’s transaction.
|
||||
auto transaction = this->transaction();
|
||||
|
||||
// 2. Let store be this’s object store.
|
||||
auto store = this->store();
|
||||
|
||||
// FIXME: 3. If store has been deleted, throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while getting all"_utf16);
|
||||
|
||||
// 5. Let range be a key range.
|
||||
GC::Ptr<IDBKeyRange> range;
|
||||
|
||||
// 6. Let direction be a cursor direction.
|
||||
Bindings::IDBCursorDirection direction = Bindings::IDBCursorDirection::Next;
|
||||
|
||||
// 7. If running is a potentially valid key range with query_or_options is true, then:
|
||||
if (is_a_potentially_valid_key_range(realm, *query_or_options)) {
|
||||
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, query_or_options));
|
||||
|
||||
// 2. Set direction to "next".
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
}
|
||||
|
||||
// 8. Else:
|
||||
else {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options["query"]. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, TRY(query_or_options->get(vm, "query"_utf16))));
|
||||
|
||||
// 2. Set count to query_or_options["count"].
|
||||
count = TRY(TRY(query_or_options->get(vm, "count"_utf16)).to_u32(vm));
|
||||
|
||||
// 3. Set direction to query_or_options["direction"].
|
||||
auto direction_value = TRY(TRY(query_or_options->get(vm, "direction"_utf16)).to_string(vm));
|
||||
if (direction_value == "next")
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
else if (direction_value == "nextunique")
|
||||
direction = Bindings::IDBCursorDirection::Nextunique;
|
||||
else if (direction_value == "prev")
|
||||
direction = Bindings::IDBCursorDirection::Prev;
|
||||
else if (direction_value == "prevunique")
|
||||
direction = Bindings::IDBCursorDirection::Prevunique;
|
||||
else
|
||||
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid direction value"_string };
|
||||
}
|
||||
|
||||
// 9. Let operation be an algorithm to run retrieve multiple items from an object store with the current Realm record, store, range, "value", direction, and count if given.
|
||||
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [&realm, store, range, direction, count] -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_object_store(realm, store, GC::Ref(*range), RecordKind::Value, direction, count);
|
||||
});
|
||||
|
||||
// 10. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
auto result = asynchronously_execute_a_request(realm, GC::Ref(*this), operation);
|
||||
dbgln_if(IDB_DEBUG, "Executing request for get all with uuid {}", result->uuid());
|
||||
return result;
|
||||
// 1. Return the result of creating a request to retrieve multiple items with the current Realm record, this,
|
||||
// "value", queryOrOptions, and count if given. Rethrow any exceptions.
|
||||
return create_a_request_to_retrieve_multiple_items(realm(), GC::Ref(*this), RecordKind::Value, *query_or_options, count);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/IndexedDB/#dom-idbobjectstore-openkeycursor
|
||||
|
@ -668,95 +609,23 @@ WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBObjectStore::open_key_cursor(JS::Val
|
|||
// https://w3c.github.io/IndexedDB/#dom-idbobjectstore-getallkeys
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBObjectStore::get_all_keys(Optional<JS::Value> query_or_options, Optional<WebIDL::UnsignedLong> count)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. Let transaction be this’s transaction.
|
||||
auto transaction = this->transaction();
|
||||
|
||||
// 2. Let store be this’s object store.
|
||||
auto store = this->store();
|
||||
|
||||
// FIXME: 3. If store has been deleted, throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while getting all keys"_utf16);
|
||||
|
||||
// 5. Let range be a key range.
|
||||
GC::Ptr<IDBKeyRange> range;
|
||||
|
||||
// 6. Let direction be a cursor direction.
|
||||
Bindings::IDBCursorDirection direction = Bindings::IDBCursorDirection::Next;
|
||||
|
||||
// 7. If running is a potentially valid key range with query_or_options is true, then:
|
||||
if (is_a_potentially_valid_key_range(realm, *query_or_options)) {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, query_or_options));
|
||||
|
||||
// 2. Set direction to "next".
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
}
|
||||
|
||||
// 8. Else:
|
||||
else {
|
||||
// 1. Set range to the result of converting a value to a key range with query_or_options["query"]. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, TRY(query_or_options->get(vm, "query"_utf16))));
|
||||
|
||||
// 2. Set count to query_or_options["count"].
|
||||
count = TRY(TRY(query_or_options->get(vm, "count"_utf16)).to_u32(vm));
|
||||
|
||||
// 3. Set direction to query_or_options["direction"].
|
||||
auto direction_value = TRY(TRY(query_or_options->get(vm, "direction"_utf16)).to_string(vm));
|
||||
if (direction_value == "next")
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
else if (direction_value == "nextunique")
|
||||
direction = Bindings::IDBCursorDirection::Nextunique;
|
||||
else if (direction_value == "prev")
|
||||
direction = Bindings::IDBCursorDirection::Prev;
|
||||
else if (direction_value == "prevunique")
|
||||
direction = Bindings::IDBCursorDirection::Prevunique;
|
||||
else
|
||||
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid direction value"_string };
|
||||
}
|
||||
|
||||
// 9. Let operation be an algorithm to run retrieve multiple items from an object store with the current Realm record, store, range, "key", direction, and count if given.
|
||||
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [&realm, store, range, direction, count] -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_object_store(realm, store, GC::Ref(*range), RecordKind::Key, direction, count);
|
||||
});
|
||||
|
||||
// 10. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
auto result = asynchronously_execute_a_request(realm, GC::Ref(*this), operation);
|
||||
dbgln_if(IDB_DEBUG, "Executing request for get all keys with uuid {}", result->uuid());
|
||||
return result;
|
||||
// 1. Return the result of creating a request to retrieve multiple items with the current Realm record, this, "key",
|
||||
// queryOrOptions, and count if given. Rethrow any exceptions.
|
||||
return create_a_request_to_retrieve_multiple_items(realm(), GC::Ref(*this), RecordKind::Key, *query_or_options, count);
|
||||
}
|
||||
|
||||
// https://pr-preview.s3.amazonaws.com/w3c/IndexedDB/pull/461.html#dom-idbobjectstore-getallrecords
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> IDBObjectStore::get_all_records(IDBGetAllOptions const& options)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
// 1. Return the result of creating a request to retrieve multiple items with the current Realm record, this,
|
||||
// "record", and options. Rethrow any exceptions.
|
||||
|
||||
// 1. Let transaction be this’s transaction.
|
||||
auto transaction = this->transaction();
|
||||
auto converted_options = JS::Object::create(realm(), nullptr);
|
||||
MUST(converted_options->create_data_property("query"_utf16_fly_string, options.query));
|
||||
MUST(converted_options->create_data_property("count"_utf16_fly_string, options.count.has_value() ? JS::Value(options.count.value()) : JS::js_undefined()));
|
||||
MUST(converted_options->create_data_property("direction"_utf16_fly_string, JS::PrimitiveString::create(realm().vm(), idl_enum_to_string(options.direction))));
|
||||
|
||||
// 2. Let store be this’s object store.
|
||||
auto store = this->store();
|
||||
|
||||
// FIXME: 3. If store has been deleted, throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while getting all records"_utf16);
|
||||
|
||||
// 5. Let range be the result of converting a value to a key range with options["query"]. Rethrow any exceptions.
|
||||
auto range = TRY(convert_a_value_to_a_key_range(realm, options.query));
|
||||
|
||||
// 6. Let operation be an algorithm to run retrieve multiple items from an object store with the current Realm record, store, range, "record", options["direction"], and options["count"] if given.
|
||||
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [&realm, store, range, options] -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_object_store(realm, store, range, RecordKind::Record, options.direction, options.count);
|
||||
});
|
||||
|
||||
// 7. Return the result (an IDBRequest) of running asynchronously execute a request with this and operation.
|
||||
return asynchronously_execute_a_request(realm, GC::Ref(*this), operation);
|
||||
return create_a_request_to_retrieve_multiple_items(realm(), GC::Ref(*this), RecordKind::Record, converted_options, {});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2186,6 +2186,7 @@ bool is_a_potentially_valid_key_range(JS::Realm& realm, JS::Value value)
|
|||
return false;
|
||||
}
|
||||
|
||||
// https://pr-preview.s3.amazonaws.com/w3c/IndexedDB/pull/461.html#retrieve-multiple-items-from-an-index
|
||||
GC::Ref<JS::Array> retrieve_multiple_items_from_an_index(JS::Realm& target_realm, GC::Ref<Index> index, GC::Ref<IDBKeyRange> range, RecordKind kind, Bindings::IDBCursorDirection direction, Optional<WebIDL::UnsignedLong> count)
|
||||
{
|
||||
// 1. If count is not given or is 0 (zero), let count be infinity.
|
||||
|
@ -2329,4 +2330,92 @@ GC::Ref<JS::Array> retrieve_multiple_items_from_an_index(JS::Realm& target_realm
|
|||
return list;
|
||||
}
|
||||
|
||||
// https://pr-preview.s3.amazonaws.com/w3c/IndexedDB/pull/461.html#create-a-request-to-retrieve-multiple-items
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> create_a_request_to_retrieve_multiple_items(JS::Realm& realm, IDBRequestSource source_handle, RecordKind kind, JS::Value query_or_options, Optional<WebIDL::UnsignedLong> count)
|
||||
{
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. Let source be an index or an object store from sourceHandle.
|
||||
// If sourceHandle is an index handle, then source is the index handle’s associated index.
|
||||
// Otherwise, source is the object store handle’s associated object store.
|
||||
auto source = source_handle.visit(
|
||||
[](Empty) -> Variant<GC::Ref<ObjectStore>, GC::Ref<Index>> { VERIFY_NOT_REACHED(); },
|
||||
[](GC::Ref<IDBCursor>) -> Variant<GC::Ref<ObjectStore>, GC::Ref<Index>> { VERIFY_NOT_REACHED(); },
|
||||
[](GC::Ref<IDBIndex> index) -> Variant<GC::Ref<ObjectStore>, GC::Ref<Index>> { return index->index(); },
|
||||
[](GC::Ref<IDBObjectStore> object_store) -> Variant<GC::Ref<ObjectStore>, GC::Ref<Index>> { return object_store->store(); });
|
||||
|
||||
// FIXME: 2. If source has been deleted, throw an "InvalidStateError" DOMException.
|
||||
// FIXME: 3. If source is an index and source’s object store has been deleted, throw an "InvalidStateError" DOMException.
|
||||
|
||||
// 4. Let transaction be sourceHandle’s transaction.
|
||||
auto transaction = source_handle.visit(
|
||||
[](Empty) -> GC::Ref<IDBTransaction> { VERIFY_NOT_REACHED(); },
|
||||
[](GC::Ref<IDBCursor>) -> GC::Ref<IDBTransaction> { VERIFY_NOT_REACHED(); },
|
||||
[](GC::Ref<IDBIndex> index) -> GC::Ref<IDBTransaction> { return index->transaction(); },
|
||||
[](GC::Ref<IDBObjectStore> object_store) -> GC::Ref<IDBTransaction> { return object_store->transaction(); });
|
||||
|
||||
// 5. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException.
|
||||
if (!transaction->is_active())
|
||||
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while creating retrieve multiple items request"_utf16);
|
||||
|
||||
// 6. Let range be a key range.
|
||||
GC::Ptr<IDBKeyRange> range;
|
||||
|
||||
// 7. Let direction be a cursor direction.
|
||||
Bindings::IDBCursorDirection direction;
|
||||
|
||||
// 8. If running is a potentially valid key range with queryOrOptions is true, then:
|
||||
if (is_a_potentially_valid_key_range(realm, query_or_options)) {
|
||||
// 1. Set range to the result of converting a value to a key range with queryOrOptions. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, query_or_options));
|
||||
|
||||
// 2. Set direction to "next".
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
}
|
||||
|
||||
// 9. Else:
|
||||
else {
|
||||
// 1. Set range to the result of converting a value to a key range with queryOrOptions["query"]. Rethrow any exceptions.
|
||||
range = TRY(convert_a_value_to_a_key_range(realm, TRY(query_or_options.get(vm, "query"_utf16))));
|
||||
|
||||
// 2. Set count to query_or_options["count"].
|
||||
count = TRY(TRY(query_or_options.get(vm, "count"_utf16)).to_u32(vm));
|
||||
|
||||
// 3. Set direction to query_or_options["direction"].
|
||||
auto direction_value = TRY(TRY(query_or_options.get(vm, "direction"_utf16)).to_string(vm));
|
||||
if (direction_value == "next")
|
||||
direction = Bindings::IDBCursorDirection::Next;
|
||||
else if (direction_value == "nextunique")
|
||||
direction = Bindings::IDBCursorDirection::Nextunique;
|
||||
else if (direction_value == "prev")
|
||||
direction = Bindings::IDBCursorDirection::Prev;
|
||||
else if (direction_value == "prevunique")
|
||||
direction = Bindings::IDBCursorDirection::Prevunique;
|
||||
else
|
||||
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid direction value"_string };
|
||||
}
|
||||
|
||||
// 10. Let operation be an algorithm to run.
|
||||
auto operation = source.visit(
|
||||
// 11. If source is an index, set operation to retrieve multiple items from an index with targetRealm, source, range, kind, direction, and count if given.
|
||||
[&](GC::Ref<Index> index) {
|
||||
return GC::create_function(realm.heap(),
|
||||
[&realm, index, range, kind, direction, count]() -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_index(realm, index, GC::Ref(*range), kind, direction, count);
|
||||
});
|
||||
},
|
||||
// 12. Else set operation to retrieve multiple items from an object store with targetRealm, source, range, kind, direction, and count if given.
|
||||
[&](GC::Ref<ObjectStore> object_store) {
|
||||
return GC::create_function(realm.heap(),
|
||||
[&realm, object_store, range, kind, direction, count]() -> WebIDL::ExceptionOr<JS::Value> {
|
||||
return retrieve_multiple_items_from_an_object_store(realm, object_store, GC::Ref(*range), kind, direction, count);
|
||||
});
|
||||
});
|
||||
|
||||
// 13. Return the result (an IDBRequest) of running asynchronously execute a request with sourceHandle and operation.
|
||||
auto result = asynchronously_execute_a_request(realm, source_handle, operation);
|
||||
dbgln_if(IDB_DEBUG, "Executing request for creating retrieve multiple items request with uuid {}", result->uuid());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,5 +68,6 @@ bool cleanup_indexed_database_transactions(GC::Ref<HTML::EventLoop>);
|
|||
bool is_a_potentially_valid_key_range(JS::Realm&, JS::Value);
|
||||
GC::Ref<JS::Array> retrieve_multiple_items_from_an_object_store(JS::Realm&, GC::Ref<ObjectStore>, GC::Ref<IDBKeyRange>, RecordKind, Bindings::IDBCursorDirection, Optional<WebIDL::UnsignedLong>);
|
||||
GC::Ref<JS::Array> retrieve_multiple_items_from_an_index(JS::Realm&, GC::Ref<Index>, GC::Ref<IDBKeyRange>, RecordKind, Bindings::IDBCursorDirection, Optional<WebIDL::UnsignedLong>);
|
||||
WebIDL::ExceptionOr<GC::Ref<IDBRequest>> create_a_request_to_retrieve_multiple_items(JS::Realm&, IDBRequestSource, RecordKind, JS::Value, Optional<WebIDL::UnsignedLong>);
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue