mirror of
https://github.com/servo/servo.git
synced 2025-09-30 00:29:14 +01:00
Switch indexeddb backend to sqlite and improve IPC messaging (#38187)
- Use sqlite instead of heed. (one indexed database = one sqlite database) - Implement the backend for indexes - Use keyranges where needed (as specified by the spec) - Implement `getKey` - Fix channel error messaging (led to a bunch of changes to how async requests are handled) Note: `components/net/indexeddb/engines/sqlite/serialize.rs` is unused; I can delete it if needed. Testing: Switching to sqlite eliminated many panics (exposing some new failures). Fixes: #38040 --------- Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
This commit is contained in:
parent
f4bbdf8010
commit
fc3feceee5
59 changed files with 2002 additions and 818 deletions
|
@ -26,7 +26,8 @@ use crate::dom::domstringlist::DOMStringList;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::idbrequest::IDBRequest;
|
||||
use crate::dom::idbtransaction::IDBTransaction;
|
||||
use crate::indexed_db::{convert_value_to_key, extract_key};
|
||||
use crate::indexed_db;
|
||||
use crate::indexed_db::{convert_value_to_key, convert_value_to_key_range, extract_key};
|
||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
|
@ -125,9 +126,43 @@ impl IDBObjectStore {
|
|||
.send(IndexedDBThreadMsg::Sync(operation))
|
||||
.unwrap();
|
||||
|
||||
receiver.recv().unwrap()
|
||||
// First unwrap for ipc
|
||||
// Second unwrap will never happen unless this db gets manually deleted somehow
|
||||
receiver.recv().unwrap().unwrap()
|
||||
}
|
||||
|
||||
// fn get_stored_key_path(&mut self) -> Option<KeyPath> {
|
||||
// let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||
//
|
||||
// let operation = SyncOperation::KeyPath(
|
||||
// sender,
|
||||
// self.global().origin().immutable().clone(),
|
||||
// self.db_name.to_string(),
|
||||
// self.name.borrow().to_string(),
|
||||
// );
|
||||
//
|
||||
// self.global()
|
||||
// .resource_threads()
|
||||
// .sender()
|
||||
// .send(IndexedDBThreadMsg::Sync(operation))
|
||||
// .unwrap();
|
||||
//
|
||||
// // First unwrap for ipc
|
||||
// // Second unwrap will never happen unless this db gets manually deleted somehow
|
||||
// let key_path = receiver.recv().unwrap().unwrap();
|
||||
// key_path.map(|p| {
|
||||
// // TODO: have separate storage for string sequence of len 1 and signle string
|
||||
// if p.len() == 1 {
|
||||
// KeyPath::String(DOMString::from_string(p[0].clone()))
|
||||
// } else {
|
||||
// let strings: Vec<_> = p.into_iter().map(|s| {
|
||||
// DOMString::from_string(s)
|
||||
// }).collect();
|
||||
// KeyPath::StringSequence(strings)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// https://www.w3.org/TR/IndexedDB-2/#object-store-in-line-keys
|
||||
fn uses_inline_keys(&self) -> bool {
|
||||
self.key_path.is_some()
|
||||
|
@ -200,30 +235,34 @@ impl IDBObjectStore {
|
|||
serialized_key = convert_value_to_key(cx, key, None)?;
|
||||
} else {
|
||||
// Step 11: We should use in-line keys instead
|
||||
if let Ok(kpk) = extract_key(
|
||||
cx,
|
||||
value,
|
||||
self.key_path.as_ref().expect("No key path"),
|
||||
None,
|
||||
) {
|
||||
if let Some(Ok(kpk)) = self
|
||||
.key_path
|
||||
.as_ref()
|
||||
.map(|p| extract_key(cx, value, p, None))
|
||||
{
|
||||
serialized_key = kpk;
|
||||
} else {
|
||||
// FIXME:(rasviitanen)
|
||||
// Check if store has a key generator
|
||||
// Check if we can inject a key
|
||||
return Err(Error::Data);
|
||||
if !self.has_key_generator() {
|
||||
return Err(Error::Data);
|
||||
}
|
||||
// FIXME:(arihant2math)
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
}
|
||||
|
||||
let serialized_value = structuredclone::write(cx, value, None)?;
|
||||
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadWrite(AsyncReadWriteOperation::PutItem(
|
||||
serialized_key,
|
||||
serialized_value.serialized,
|
||||
overwrite,
|
||||
)),
|
||||
AsyncOperation::ReadWrite(AsyncReadWriteOperation::PutItem {
|
||||
sender,
|
||||
key: serialized_key,
|
||||
value: serialized_value.serialized,
|
||||
should_overwrite: overwrite,
|
||||
}),
|
||||
receiver,
|
||||
None,
|
||||
can_gc,
|
||||
)
|
||||
|
@ -262,10 +301,12 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
|||
// TODO: Convert to key range instead
|
||||
let serialized_query = convert_value_to_key(cx, query, None);
|
||||
// Step 7
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadWrite(AsyncReadWriteOperation::RemoveItem(q)),
|
||||
AsyncOperation::ReadWrite(AsyncReadWriteOperation::RemoveItem { sender, key: q }),
|
||||
receiver,
|
||||
None,
|
||||
CanGc::note(),
|
||||
)
|
||||
|
@ -279,9 +320,12 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
|||
// TODO: Step 3
|
||||
// Steps 4-5
|
||||
self.check_readwrite_transaction_active()?;
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadWrite(AsyncReadWriteOperation::Clear),
|
||||
AsyncOperation::ReadWrite(AsyncReadWriteOperation::Clear(sender)),
|
||||
receiver,
|
||||
None,
|
||||
CanGc::note(),
|
||||
)
|
||||
|
@ -295,13 +339,17 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
|||
// Step 4
|
||||
self.check_transaction_active()?;
|
||||
// Step 5
|
||||
// TODO: Convert to key range instead
|
||||
let serialized_query = convert_value_to_key(cx, query, None);
|
||||
let serialized_query = convert_value_to_key_range(cx, query, None);
|
||||
// Step 6
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadOnly(AsyncReadOnlyOperation::GetItem(q)),
|
||||
AsyncOperation::ReadOnly(AsyncReadOnlyOperation::GetItem {
|
||||
sender,
|
||||
key_range: q,
|
||||
}),
|
||||
receiver,
|
||||
None,
|
||||
CanGc::note(),
|
||||
)
|
||||
|
@ -309,17 +357,29 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
|||
}
|
||||
|
||||
// https://www.w3.org/TR/IndexedDB-2/#dom-idbobjectstore-getkey
|
||||
// fn GetKey(&self, _cx: SafeJSContext, _query: HandleValue) -> DomRoot<IDBRequest> {
|
||||
// // Step 1: Unneeded, handled by self.check_transaction_active()
|
||||
// // TODO: Step 2
|
||||
// // TODO: Step 3
|
||||
// // Step 4
|
||||
// self.check_transaction_active()?;
|
||||
// // Step 5
|
||||
// // TODO: Convert to key range instead
|
||||
// let serialized_query = IDBObjectStore::convert_value_to_key(cx, query, None);
|
||||
// unimplemented!();
|
||||
// }
|
||||
fn GetKey(&self, cx: SafeJSContext, query: HandleValue) -> Result<DomRoot<IDBRequest>, Error> {
|
||||
// Step 1: Unneeded, handled by self.check_transaction_active()
|
||||
// TODO: Step 2
|
||||
// TODO: Step 3
|
||||
// Step 4
|
||||
self.check_transaction_active()?;
|
||||
// Step 5
|
||||
let serialized_query = convert_value_to_key_range(cx, query, None);
|
||||
// Step 6
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadOnly(AsyncReadOnlyOperation::GetKey {
|
||||
sender,
|
||||
key_range: q,
|
||||
}),
|
||||
receiver,
|
||||
None,
|
||||
CanGc::note(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/IndexedDB-2/#dom-idbobjectstore-getall
|
||||
// fn GetAll(
|
||||
|
@ -350,13 +410,18 @@ impl IDBObjectStoreMethods<crate::DomTypeHolder> for IDBObjectStore {
|
|||
self.check_transaction_active()?;
|
||||
|
||||
// Step 5
|
||||
let serialized_query = convert_value_to_key(cx, query, None);
|
||||
let serialized_query = convert_value_to_key_range(cx, query, None);
|
||||
|
||||
// Step 6
|
||||
let (sender, receiver) = indexed_db::create_channel(self.global());
|
||||
serialized_query.and_then(|q| {
|
||||
IDBRequest::execute_async(
|
||||
self,
|
||||
AsyncOperation::ReadOnly(AsyncReadOnlyOperation::Count(q)),
|
||||
AsyncOperation::ReadOnly(AsyncReadOnlyOperation::Count {
|
||||
sender,
|
||||
key_range: q,
|
||||
}),
|
||||
receiver,
|
||||
None,
|
||||
CanGc::note(),
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue