indexeddb: Serialize all cloned values when storing data. (#39081)

We were performing a structured clone but throwing away any serializable
DOM interfaces included in the result. We need to instead serialize the
full structured clone result so we can deserialize the DOM interfaces
when getting the data out of the object store.

Testing: Existing WPT coverage is sufficient.
Fixes: #38818
Fixed: #38842

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-09-03 08:06:14 -04:00 committed by GitHub
parent 6b208124dc
commit 433a461044
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 16 additions and 27 deletions

View file

@ -257,7 +257,10 @@ impl IDBObjectStore {
}
// Step 10. Let clone be a clone of value in targetRealm during transaction. Rethrow any exceptions.
let serialized_value = structuredclone::write(cx, value, None)?;
let cloned_value = structuredclone::write(cx, value, None)?;
let Ok(serialized_value) = bincode::serialize(&cloned_value) else {
return Err(Error::InvalidState);
};
let (sender, receiver) = indexed_db::create_channel(self.global());
@ -268,7 +271,7 @@ impl IDBObjectStore {
AsyncOperation::ReadWrite(AsyncReadWriteOperation::PutItem {
sender,
key: serialized_key,
value: serialized_value.serialized,
value: serialized_value,
should_overwrite: overwrite,
}),
receiver,

View file

@ -4,7 +4,6 @@
use std::cell::Cell;
use constellation_traits::StructuredSerializedData;
use dom_struct::dom_struct;
use ipc_channel::router::ROUTER;
use js::jsapi::Heap;
@ -117,14 +116,14 @@ impl RequestListener {
key_type_to_jsval(GlobalScope::get_cx(), &key, answer.handle_mut())
},
IdbResult::Data(serialized_data) => {
let data = StructuredSerializedData {
serialized: serialized_data,
..Default::default()
};
if structuredclone::read(&global, data, answer.handle_mut()).is_err() {
let result = bincode::deserialize(&serialized_data)
.map_err(|_| Error::Data)
.and_then(|data| structuredclone::read(&global, data, answer.handle_mut()));
if let Err(e) = result {
warn!("Error reading structuredclone data");
}
Self::handle_async_request_error(&global, cx, request, e);
return;
};
},
IdbResult::Count(count) => {
answer.handle_mut().set(DoubleValue(count as f64));

View file

@ -2,13 +2,13 @@
expected: ERROR
[blob-valid-after-abort.any.worker.html]
expected: CRASH
expected: TIMEOUT
[A blob can be read back after the transaction that added it was aborted.]
expected: TIMEOUT
[blob-valid-after-abort.any.html]
expected: CRASH
expected: TIMEOUT
[A blob can be read back after the transaction that added it was aborted.]
expected: TIMEOUT

View file

@ -1,10 +1,10 @@
[blob-valid-after-deletion.any.html]
expected: CRASH
expected: TIMEOUT
[Blobs stay alive after their records are deleted.]
expected: TIMEOUT
[blob-valid-after-deletion.any.worker.html]
expected: CRASH
expected: TIMEOUT
[Blobs stay alive after their records are deleted.]
expected: TIMEOUT

View file

@ -1,10 +0,0 @@
[blob-valid-before-commit.any.html]
expected: CRASH
[Blobs can be read back before their records are committed.]
expected: TIMEOUT
[blob-valid-before-commit.any.worker.html]
expected: CRASH
[Blobs can be read back before their records are committed.]
expected: TIMEOUT

View file

@ -16,9 +16,6 @@
[Deactivation of new transactions happens at end of invocation]
expected: FAIL
[New transactions are deactivated before next task]
expected: FAIL
[New transactions from microtask are deactivated before next task]
expected: FAIL