Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 23 additions & 39 deletions components/script/dom/indexeddb/idbdatabase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ use std::cell::Cell;

use dom_struct::dom_struct;
use js::context::JSContext;
use profile_traits::generic_channel::channel;
use script_bindings::cell::DomRefCell;
use script_bindings::reflector::reflect_dom_object_with_cx;
use servo_base::generic_channel::{GenericSend, GenericSender};
use storage_traits::indexeddb::{IndexedDBThreadMsg, KeyPath, SyncOperation};
use storage_traits::indexeddb::{AsyncSchemaOperation, IndexedDBThreadMsg, KeyPath, SyncOperation};
use stylo_atoms::Atom;
use uuid::Uuid;

Expand Down Expand Up @@ -325,36 +324,29 @@ impl IDBDatabaseMethods<crate::DomTypeHolder> for IDBDatabase {
&transaction,
);

let (sender, receiver) = channel(self.global().time_profiler_chan().clone()).unwrap();

let key_paths = key_path.map(|p| match p {
StringOrStringSequence::String(s) => KeyPath::String(s.to_string()),
StringOrStringSequence::StringSequence(s) => {
KeyPath::Sequence(s.iter().map(|s| s.to_string()).collect())
},
});
let operation = SyncOperation::CreateObjectStore(
sender,
self.global().origin().immutable().clone(),
self.name.to_string(),
name.to_string(),
key_paths,

let operation = AsyncSchemaOperation::CreateObjectStore {
callback: transaction.create_abort_callback(),
key_path: key_paths,
auto_increment,
);
};

self.get_idb_thread()
.send(IndexedDBThreadMsg::Sync(operation))
.send(IndexedDBThreadMsg::AsyncSchemaOperation {
origin: self.global().origin().immutable().clone(),
database_name: self.name.to_string(),
store_name: name.to_string(),
operation,
transaction_serial_number: transaction.get_serial_number(),
})
.unwrap();

if receiver
.recv()
.expect("Could not receive object store creation status")
.is_err()
{
warn!("Object store creation failed in idb thread");
return Err(Error::InvalidState(None));
};

self.object_store_names.borrow_mut().push(name);
transaction.register_object_store_handle(&object_store.get_name(), &object_store);

Expand Down Expand Up @@ -390,27 +382,19 @@ impl IDBDatabaseMethods<crate::DomTypeHolder> for IDBDatabase {
// FIXME:(arihant2math) Remove from index set ...

// Step 7
let (sender, receiver) = channel(self.global().time_profiler_chan().clone()).unwrap();

let operation = SyncOperation::DeleteObjectStore(
sender,
self.global().origin().immutable().clone(),
self.name.to_string(),
String::from(name),
);

let operation = AsyncSchemaOperation::DeleteObjectStore {
callback: transaction.create_abort_callback(),
};
self.get_idb_thread()
.send(IndexedDBThreadMsg::Sync(operation))
.send(IndexedDBThreadMsg::AsyncSchemaOperation {
origin: self.global().origin().immutable().clone(),
database_name: self.name.to_string(),
store_name: name.to_string(),
operation,
transaction_serial_number: transaction.get_serial_number(),
})
.unwrap();

if receiver
.recv()
.expect("Could not receive object store deletion status")
.is_err()
{
warn!("Object store deletion failed in idb thread");
return Err(Error::InvalidState(None));
};
Ok(())
}

Expand Down
84 changes: 53 additions & 31 deletions components/script/dom/indexeddb/idbobjectstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use script_bindings::error::ErrorResult;
use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
use servo_base::generic_channel::{GenericSend, GenericSender};
use storage_traits::indexeddb::{
self, AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, IndexedDBKeyType,
IndexedDBThreadMsg, SyncOperation,
self, AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, AsyncSchemaOperation,
IndexedDBKeyType, IndexedDBThreadMsg,
};

use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::IDBCursorDirection;
Expand Down Expand Up @@ -602,16 +602,25 @@ impl IDBObjectStore {

/// The caller must ensure that the original index exists.
pub(crate) fn rename_index(&self, name: &DOMString, new_name: &DOMString) {
let rename_index_operation = SyncOperation::RenameIndex(
self.global().origin().immutable().clone(),
self.db_name.to_string(),
self.name.borrow().to_string(),
String::from(name.clone()),
String::from(new_name.clone()),
);
self.get_idb_thread()
.send(IndexedDBThreadMsg::Sync(rename_index_operation))
.unwrap();
let operation = AsyncSchemaOperation::RenameIndex {
callback: self.transaction.create_abort_callback(),
index_name: name.to_string(),
new_name: new_name.to_string(),
};

if self
.get_idb_thread()
.send(IndexedDBThreadMsg::AsyncSchemaOperation {
origin: self.global().origin().immutable().clone(),
database_name: self.db_name.to_string(),
store_name: self.name.borrow().clone().into(),
operation,
transaction_serial_number: self.transaction.get_serial_number(),
})
.is_err()
{
warn!("Could not send AsyncSchemaOperation");
}

// We also need to update the key in the index set
let index = self
Expand Down Expand Up @@ -1013,18 +1022,23 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
// Step 11. Let index be a new index in store.
// Set index’s name to name and key path to keyPath. If unique is set, set index’s unique flag.
// If multiEntry is set, set index’s multiEntry flag.
let create_index_operation = SyncOperation::CreateIndex(
self.global().origin().immutable().clone(),
self.db_name.to_string(),
self.name.borrow().to_string(),
name.to_string(),
key_path.clone().into(),
options.unique,
options.multiEntry,
);
let operation = AsyncSchemaOperation::CreateIndex {
callback: self.transaction.create_abort_callback(),
index_name: name.to_string(),
key_path: key_path.clone().into(),
unique: options.unique,
multi_entry: options.multiEntry,
};

if self
.get_idb_thread()
.send(IndexedDBThreadMsg::Sync(create_index_operation))
.send(IndexedDBThreadMsg::AsyncSchemaOperation {
origin: self.global().origin().immutable().clone(),
database_name: self.db_name.to_string(),
store_name: self.name.borrow().clone().into(),
operation,
transaction_serial_number: self.transaction.get_serial_number(),
})
.is_err()
{
return Err(Error::Operation(None));
Expand Down Expand Up @@ -1055,15 +1069,23 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
// Step 7. Remove index from this object store handle's index set.
self.index_set.borrow_mut().retain(|n, _| n != &name);
// Step 8. Destroy index.
let delete_index_operation = SyncOperation::DeleteIndex(
self.global().origin().immutable().clone(),
self.db_name.to_string(),
self.name.borrow().to_string(),
String::from(name),
);
self.get_idb_thread()
.send(IndexedDBThreadMsg::Sync(delete_index_operation))
.unwrap();
let operation = AsyncSchemaOperation::DeleteIndex {
callback: self.transaction.create_abort_callback(),
index_name: name.to_string(),
};
if self
.get_idb_thread()
.send(IndexedDBThreadMsg::AsyncSchemaOperation {
origin: self.global().origin().immutable().clone(),
database_name: self.db_name.to_string(),
store_name: self.name.borrow().clone().into(),
operation,
transaction_serial_number: self.transaction.get_serial_number(),
})
.is_err()
{
return Err(Error::Operation(None));
}
Ok(())
}

Expand Down
28 changes: 27 additions & 1 deletion components/script/dom/indexeddb/idbtransaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use script_bindings::reflector::reflect_dom_object_with_cx;
use servo_base::generic_channel::{GenericSend, GenericSender};
use servo_base::id::ScriptEventLoopId;
use storage_traits::indexeddb::{
IndexedDBIndex, IndexedDBThreadMsg, IndexedDBTxnMode, KeyPath, SyncOperation, TxnCompleteMsg,
BackendError, IndexedDBIndex, IndexedDBThreadMsg, IndexedDBTxnMode, KeyPath, SyncOperation,
TxnCompleteMsg,
};
use stylo_atoms::Atom;

Expand All @@ -41,6 +42,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::indexeddb::idbdatabase::IDBDatabase;
use crate::dom::indexeddb::idbobjectstore::{IDBObjectStore, IDBObjectStoreAbortState};
use crate::dom::indexeddb::idbrequest::IDBRequest;
use crate::indexeddb::map_backend_error_to_dom_error;

#[dom_struct]
pub struct IDBTransaction {
Expand Down Expand Up @@ -721,6 +723,30 @@ impl IDBTransaction {
object_store.key_generator_current_number,
))
}

pub(crate) fn create_abort_callback(&self) -> GenericCallback<BackendError> {
let trusted_transaction = Trusted::new(self);
let task_source = self
.global()
.task_manager()
.storage_task_source()
.to_sendable();
GenericCallback::new(
self.global().time_profiler_chan().clone(),
move |error: Result<BackendError, ipc_channel::IpcError>| {
let Ok(error) = error else {
return;
};
let trusted_transaction = trusted_transaction.clone();
task_source.queue(task!(delete_failed: move |cx| {
let transaction = trusted_transaction.root();
transaction.initiate_abort(cx, map_backend_error_to_dom_error(error));
transaction.request_backend_abort();
}));
},
)
.expect("Could not create GenericCallback")
}
}

impl IDBTransactionMethods<crate::DomTypeHolder> for IDBTransaction {
Expand Down
101 changes: 58 additions & 43 deletions components/shared/storage/indexeddb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,19 +359,70 @@ impl AsyncReadWriteOperation {
}
}

#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
pub enum AsyncSchemaOperation {
/// Creates a new index for the database
CreateIndex {
callback: GenericCallback<BackendError>,
index_name: String,
key_path: KeyPath,
unique: bool,
multi_entry: bool,
},
/// Rename an index
RenameIndex {
callback: GenericCallback<BackendError>,
index_name: String,
new_name: String,
},
/// Delete an index
DeleteIndex {
callback: GenericCallback<BackendError>,
index_name: String,
},
/// Creates a new store for the database
CreateObjectStore {
callback: GenericCallback<BackendError>,
key_path: Option<KeyPath>,
auto_increment: bool,
},
/// Delete an existing object store in the database
DeleteObjectStore {
callback: GenericCallback<BackendError>,
},
}

impl AsyncSchemaOperation {
pub fn notify_error(&self, error: BackendError) {
match self {
AsyncSchemaOperation::CreateIndex { .. } |
AsyncSchemaOperation::RenameIndex { .. } |
AsyncSchemaOperation::DeleteIndex { .. } => {},
AsyncSchemaOperation::CreateObjectStore { callback, .. } => {
let _ = callback.send(error);
},
AsyncSchemaOperation::DeleteObjectStore { callback, .. } => {
let _ = callback.send(error);
},
};
}
}

/// Operations that are not executed instantly, but rather added to a
/// queue that is eventually run.
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
pub enum AsyncOperation {
ReadOnly(AsyncReadOnlyOperation),
ReadWrite(AsyncReadWriteOperation),
Schema(AsyncSchemaOperation),
}

impl AsyncOperation {
pub fn notify_error(&self, error: BackendError) {
match self {
Self::ReadOnly(operation) => operation.notify_error(error),
Self::ReadWrite(operation) => operation.notify_error(error),
Self::Schema(operation) => operation.notify_error(error),
}
}
}
Expand Down Expand Up @@ -527,49 +578,6 @@ pub enum SyncOperation {
txn: u64,
},

/// Creates a new index for the database
CreateIndex(
ImmutableOrigin,
String, // Database
String, // Store
String, // Index name
KeyPath, // key path
bool, // unique flag
bool, // multientry flag
),
/// Rename an index
RenameIndex(
ImmutableOrigin,
String, // Database
String, // Store
String, // Index name
String, // New name
),
/// Delete an index
DeleteIndex(
ImmutableOrigin,
String, // Database
String, // Store
String, // Index name
),

/// Creates a new store for the database
CreateObjectStore(
GenericSender<BackendResult<CreateObjectResult>>,
ImmutableOrigin,
String, // Database
String, // Store
Option<KeyPath>, // Key Path
bool,
),

DeleteObjectStore(
GenericSender<BackendResult<()>>,
ImmutableOrigin,
String, // Database
String, // Store
),

CloseDatabase(
ImmutableOrigin,
Uuid,
Expand Down Expand Up @@ -639,6 +647,13 @@ pub enum IndexedDBThreadMsg {
IndexedDBTxnMode,
AsyncOperation,
),
AsyncSchemaOperation {
origin: ImmutableOrigin,
database_name: String,
store_name: String,
operation: AsyncSchemaOperation,
transaction_serial_number: u64,
},
EngineTxnBatchComplete {
origin: ImmutableOrigin,
db_name: String,
Expand Down
Loading
Loading