script: Ensure autoincrement and keypath are passed in correctly from IDBTransaction (#38738)

Previously, the correct autoincremented and keypath parameters were only
being passed if the object store is being created. This PR queries this
info from the backend and passes it onto the constructor in
IDBTransaction. Furthermore it exposes keypath and index_names from
IDBObjectStore, mainly for WPT.

Testing: WPT
Fixes: None

---------

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
This commit is contained in:
Ashwin Naren 2025-09-11 02:13:15 -07:00 committed by GitHub
parent 722b0de8d8
commit 97690b1cba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 84 additions and 170 deletions

View file

@ -8,12 +8,14 @@ use std::collections::HashMap;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use net_traits::IpcSend;
use net_traits::indexeddb_thread::{IndexedDBThreadMsg, SyncOperation};
use net_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation};
use profile_traits::ipc;
use script_bindings::codegen::GenericUnionTypes::StringOrStringSequence;
use stylo_atoms::Atom;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::DOMStringListBinding::DOMStringListMethods;
use crate::dom::bindings::codegen::Bindings::IDBDatabaseBinding::IDBObjectStoreParameters;
use crate::dom::bindings::codegen::Bindings::IDBTransactionBinding::{
IDBTransactionMethods, IDBTransactionMode,
};
@ -203,6 +205,52 @@ impl IDBTransaction {
fn get_idb_thread(&self) -> IpcSender<IndexedDBThreadMsg> {
self.global().resource_threads().sender()
}
fn object_store_parameters(
&self,
object_store_name: &DOMString,
) -> Option<IDBObjectStoreParameters> {
let global = self.global();
let idb_sender = global.resource_threads().sender();
let (sender, receiver) =
ipc::channel(global.time_profiler_chan().clone()).expect("failed to create channel");
let origin = global.origin().immutable().clone();
let db_name = self.db.get_name().to_string();
let object_store_name = object_store_name.to_string();
let operation = SyncOperation::HasKeyGenerator(
sender,
origin.clone(),
db_name.clone(),
object_store_name.clone(),
);
let _ = idb_sender.send(IndexedDBThreadMsg::Sync(operation));
// First unwrap for ipc
// Second unwrap will never happen unless this db gets manually deleted somehow
let auto_increment = receiver.recv().ok()?.ok()?;
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).ok()?;
let operation = SyncOperation::KeyPath(sender, origin, db_name, object_store_name);
let _ = idb_sender.send(IndexedDBThreadMsg::Sync(operation));
// First unwrap for ipc
// Second unwrap will never happen unless this db gets manually deleted somehow
let key_path = receiver.recv().unwrap().ok()?;
let key_path = key_path.map(|key_path| match key_path {
KeyPath::String(s) => StringOrStringSequence::String(DOMString::from_string(s)),
KeyPath::Sequence(seq) => StringOrStringSequence::StringSequence(
seq.into_iter().map(DOMString::from_string).collect(),
),
});
Some(IDBObjectStoreParameters {
autoIncrement: auto_increment,
keyPath: key_path,
})
}
}
impl IDBTransactionMethods<crate::DomTypeHolder> for IDBTransaction {
@ -213,7 +261,7 @@ impl IDBTransactionMethods<crate::DomTypeHolder> for IDBTransaction {
// https://www.w3.org/TR/IndexedDB-2/#dom-idbtransaction-objectstore
fn ObjectStore(&self, name: DOMString) -> Fallible<DomRoot<IDBObjectStore>> {
// Step 1: Handle the case where transaction has finised
// Step 1: If transaction has finished, throw an "InvalidStateError" DOMException.
if self.finished.get() {
return Err(Error::InvalidState);
}
@ -228,12 +276,12 @@ impl IDBTransactionMethods<crate::DomTypeHolder> for IDBTransaction {
// returns the same IDBObjectStore instance.
let mut store_handles = self.store_handles.borrow_mut();
let store = store_handles.entry(name.to_string()).or_insert_with(|| {
// TODO: get key path from backend
let parameters = self.object_store_parameters(&name);
let store = IDBObjectStore::new(
&self.global(),
self.db.get_name(),
name,
None,
parameters.as_ref(),
CanGc::note(),
self,
);