script: Add generic root storage to StructuredCloneReader. (#36640)

This reduces the boilerplate necessary for adding new
serializable/transferable interfaces to the structured cloning code. We
always need to root the deserialized objects when performing a read
operation, but we don't actually need the concrete object types in the
majority of cases. By storing a list of rooted JS object values, we can
push generic reflector objects into it, and extract the types we need
(MessagePort) at the very end.

Testing: Existing WPT structured cloning tests will provide coverage.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-04-23 09:05:41 -04:00 committed by GitHub
parent 7c1e5918a8
commit 5d3cbc67ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 73 additions and 126 deletions

View file

@ -11,7 +11,7 @@ use base::id::{Index, NamespaceIndex, PipelineNamespaceId};
use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc; use crate::script_runtime::CanGc;
@ -65,13 +65,7 @@ where
/// Returns the field of [StructuredDataReader]/[StructuredDataWriter] that /// Returns the field of [StructuredDataReader]/[StructuredDataWriter] that
/// should be used to read/store serialized instances of this type. /// should be used to read/store serialized instances of this type.
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>; ) -> &'a mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
/// Returns the field of [StructuredDataReader] that should be used to store
/// deserialized instances of this type.
fn deserialized_storage(
reader: &mut StructuredDataReader,
) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>>;
} }

View file

@ -16,13 +16,14 @@ use constellation_traits::{
BlobImpl, DomException, DomPoint, MessagePortImpl, Serializable as SerializableInterface, BlobImpl, DomException, DomPoint, MessagePortImpl, Serializable as SerializableInterface,
StructuredSerializedData, Transferrable as TransferrableInterface, StructuredSerializedData, Transferrable as TransferrableInterface,
}; };
use js::gc::RootedVec;
use js::glue::{ use js::glue::{
CopyJSStructuredCloneData, DeleteJSAutoStructuredCloneBuffer, GetLengthOfJSStructuredCloneData, CopyJSStructuredCloneData, DeleteJSAutoStructuredCloneBuffer, GetLengthOfJSStructuredCloneData,
NewJSAutoStructuredCloneBuffer, WriteBytesToJSStructuredCloneData, NewJSAutoStructuredCloneBuffer, WriteBytesToJSStructuredCloneData,
}; };
use js::jsapi::{ use js::jsapi::{
CloneDataPolicy, HandleObject as RawHandleObject, JS_ClearPendingException, JS_ReadUint32Pair, CloneDataPolicy, HandleObject as RawHandleObject, Heap, JS_ClearPendingException,
JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject, JS_ReadUint32Pair, JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject,
JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter, JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
MutableHandleObject as RawMutableHandleObject, StructuredCloneScope, TransferableOwnership, MutableHandleObject as RawMutableHandleObject, StructuredCloneScope, TransferableOwnership,
}; };
@ -93,7 +94,7 @@ fn reader_for_type(
) -> unsafe fn( ) -> unsafe fn(
&GlobalScope, &GlobalScope,
*mut JSStructuredCloneReader, *mut JSStructuredCloneReader,
&mut StructuredDataReader, &mut StructuredDataReader<'_>,
CanGc, CanGc,
) -> *mut JSObject { ) -> *mut JSObject {
match val { match val {
@ -107,7 +108,7 @@ fn reader_for_type(
unsafe fn read_object<T: Serializable>( unsafe fn read_object<T: Serializable>(
owner: &GlobalScope, owner: &GlobalScope,
r: *mut JSStructuredCloneReader, r: *mut JSStructuredCloneReader,
sc_reader: &mut StructuredDataReader, sc_reader: &mut StructuredDataReader<'_>,
can_gc: CanGc, can_gc: CanGc,
) -> *mut JSObject { ) -> *mut JSObject {
let mut name_space: u32 = 0; let mut name_space: u32 = 0;
@ -136,9 +137,8 @@ unsafe fn read_object<T: Serializable>(
} }
if let Ok(obj) = T::deserialize(owner, serialized, can_gc) { if let Ok(obj) = T::deserialize(owner, serialized, can_gc) {
let destination = T::deserialized_storage(sc_reader).get_or_insert_with(HashMap::new);
let reflector = obj.reflector().get_jsobject().get(); let reflector = obj.reflector().get_jsobject().get();
destination.insert(storage_key, obj); sc_reader.roots.push(Heap::boxed(reflector));
return reflector; return reflector;
} }
warn!("Reading structured data failed in {:?}.", owner.get_url()); warn!("Reading structured data failed in {:?}.", owner.get_url());
@ -191,7 +191,7 @@ unsafe extern "C" fn read_callback(
"tag should be higher than StructuredCloneTags::Min" "tag should be higher than StructuredCloneTags::Min"
); );
let sc_reader = &mut *(closure as *mut StructuredDataReader); let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx)); let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)); let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
for serializable in SerializableInterface::iter() { for serializable in SerializableInterface::iter() {
@ -259,7 +259,8 @@ unsafe extern "C" fn write_callback(
fn receiver_for_type( fn receiver_for_type(
val: TransferrableInterface, val: TransferrableInterface,
) -> fn(&GlobalScope, &mut StructuredDataReader, u64, RawMutableHandleObject) -> Result<(), ()> { ) -> fn(&GlobalScope, &mut StructuredDataReader<'_>, u64, RawMutableHandleObject) -> Result<(), ()>
{
match val { match val {
TransferrableInterface::MessagePort => receive_object::<MessagePort>, TransferrableInterface::MessagePort => receive_object::<MessagePort>,
TransferrableInterface::ReadableStream => receive_object::<ReadableStream>, TransferrableInterface::ReadableStream => receive_object::<ReadableStream>,
@ -269,7 +270,7 @@ fn receiver_for_type(
fn receive_object<T: Transferable>( fn receive_object<T: Transferable>(
owner: &GlobalScope, owner: &GlobalScope,
sc_reader: &mut StructuredDataReader, sc_reader: &mut StructuredDataReader<'_>,
extra_data: u64, extra_data: u64,
return_object: RawMutableHandleObject, return_object: RawMutableHandleObject,
) -> Result<(), ()> { ) -> Result<(), ()> {
@ -305,13 +306,12 @@ fn receive_object<T: Transferable>(
); );
}; };
if let Ok(received) = T::transfer_receive(owner, id, serialized) { let Ok(received) = T::transfer_receive(owner, id, serialized) else {
return_object.set(received.reflector().rootable().get()); return Err(());
let storage = T::deserialized_storage(sc_reader).get_or_insert_with(Vec::new); };
storage.push(received); return_object.set(received.reflector().rootable().get());
return Ok(()); sc_reader.roots.push(Heap::boxed(return_object.get()));
} Ok(())
Err(())
} }
unsafe extern "C" fn read_transfer_callback( unsafe extern "C" fn read_transfer_callback(
@ -324,7 +324,7 @@ unsafe extern "C" fn read_transfer_callback(
closure: *mut raw::c_void, closure: *mut raw::c_void,
return_object: RawMutableHandleObject, return_object: RawMutableHandleObject,
) -> bool { ) -> bool {
let sc_reader = &mut *(closure as *mut StructuredDataReader); let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx)); let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let owner = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)); let owner = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
@ -489,8 +489,8 @@ static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredClon
sabCloned: Some(sab_cloned_callback), sabCloned: Some(sab_cloned_callback),
}; };
pub(crate) enum StructuredData<'a> { pub(crate) enum StructuredData<'a, 'b> {
Reader(&'a mut StructuredDataReader), Reader(&'a mut StructuredDataReader<'b>),
Writer(&'a mut StructuredDataWriter), Writer(&'a mut StructuredDataWriter),
} }
@ -503,19 +503,11 @@ pub(crate) struct DOMErrorRecord {
/// Reader and writer structs for results from, and inputs to, structured-data read/write operations. /// Reader and writer structs for results from, and inputs to, structured-data read/write operations.
/// <https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data> /// <https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data>
#[repr(C)] #[repr(C)]
pub(crate) struct StructuredDataReader { pub(crate) struct StructuredDataReader<'a> {
/// A struct of error message. /// A struct of error message.
pub(crate) errors: DOMErrorRecord, errors: DOMErrorRecord,
/// A map of deserialized blobs, stored temporarily here to keep them rooted. /// Rooted copies of every deserialized object to ensure they are not garbage collected.
pub(crate) blobs: Option<HashMap<StorageKey, DomRoot<Blob>>>, roots: RootedVec<'a, Box<Heap<*mut JSObject>>>,
/// A map of deserialized points, stored temporarily here to keep them rooted.
pub(crate) points_read_only: Option<HashMap<StorageKey, DomRoot<DOMPointReadOnly>>>,
pub(crate) dom_points: Option<HashMap<StorageKey, DomRoot<DOMPoint>>>,
/// A map of deserialized exceptions, stored temporarily here to keep them rooted.
pub(crate) dom_exceptions: Option<HashMap<StorageKey, DomRoot<DOMException>>>,
/// A vec of transfer-received DOM ports,
/// to be made available to script through a message event.
pub(crate) message_ports: Option<Vec<DomRoot<MessagePort>>>,
/// A map of port implementations, /// A map of port implementations,
/// used as part of the "transfer-receiving" steps of ports, /// used as part of the "transfer-receiving" steps of ports,
/// to produce the DOM ports stored in `message_ports` above. /// to produce the DOM ports stored in `message_ports` above.
@ -528,12 +520,6 @@ pub(crate) struct StructuredDataReader {
pub(crate) points: Option<HashMap<DomPointId, DomPoint>>, pub(crate) points: Option<HashMap<DomPointId, DomPoint>>,
/// A map of serialized exceptions. /// A map of serialized exceptions.
pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>, pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>,
/// <https://streams.spec.whatwg.org/#rs-transfer>
pub(crate) readable_streams: Option<Vec<DomRoot<ReadableStream>>>,
/// <https://streams.spec.whatwg.org/#ws-transfer>
pub(crate) writable_streams: Option<Vec<DomRoot<WritableStream>>>,
} }
/// A data holder for transferred and serialized objects. /// A data holder for transferred and serialized objects.
@ -618,19 +604,14 @@ pub(crate) fn read(
) -> Fallible<Vec<DomRoot<MessagePort>>> { ) -> Fallible<Vec<DomRoot<MessagePort>>> {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(global); let _ac = enter_realm(global);
rooted_vec!(let mut roots);
let mut sc_reader = StructuredDataReader { let mut sc_reader = StructuredDataReader {
blobs: None, roots,
message_ports: None,
points_read_only: None,
dom_points: None,
dom_exceptions: None,
port_impls: data.ports.take(), port_impls: data.ports.take(),
blob_impls: data.blobs.take(), blob_impls: data.blobs.take(),
points: data.points.take(), points: data.points.take(),
exceptions: data.exceptions.take(), exceptions: data.exceptions.take(),
errors: DOMErrorRecord { message: None }, errors: DOMErrorRecord { message: None },
readable_streams: None,
writable_streams: None,
}; };
let sc_reader_ptr = &mut sc_reader as *mut _; let sc_reader_ptr = &mut sc_reader as *mut _;
unsafe { unsafe {
@ -666,8 +647,15 @@ pub(crate) fn read(
DeleteJSAutoStructuredCloneBuffer(scbuf); DeleteJSAutoStructuredCloneBuffer(scbuf);
let mut message_ports = vec![];
for reflector in sc_reader.roots.iter() {
let Ok(message_port) = root_from_object::<MessagePort>(reflector.get(), *cx) else {
continue;
};
message_ports.push(message_port);
}
// Any transfer-received port-impls should have been taken out. // Any transfer-received port-impls should have been taken out.
assert!(sc_reader.port_impls.is_none()); assert!(sc_reader.port_impls.is_none());
Ok(sc_reader.message_ports.take().unwrap_or_default()) Ok(message_ports)
} }
} }

View file

@ -12,7 +12,7 @@ use base::id::NamespaceIndex;
use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
pub(crate) trait Transferable: DomObject pub(crate) trait Transferable: DomObject
where where
@ -32,8 +32,7 @@ where
serialized: Self::Data, serialized: Self::Data,
) -> Result<DomRoot<Self>, ()>; ) -> Result<DomRoot<Self>, ()>;
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>; ) -> &'a mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>>;
} }

View file

@ -24,9 +24,9 @@ use crate::dom::bindings::codegen::UnionTypes::ArrayBufferOrArrayBufferViewOrBlo
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::serializable::{Serializable, StorageKey}; use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::readablestream::ReadableStream; use crate::dom::readablestream::ReadableStream;
@ -119,18 +119,14 @@ impl Serializable for Blob {
Ok(deserialized_blob) Ok(deserialized_blob)
} }
fn serialized_storage(reader: StructuredData<'_>) -> &mut Option<HashMap<BlobId, Self::Data>> { fn serialized_storage<'a>(
reader: StructuredData<'a, '_>,
) -> &'a mut Option<HashMap<BlobId, Self::Data>> {
match reader { match reader {
StructuredData::Reader(r) => &mut r.blob_impls, StructuredData::Reader(r) => &mut r.blob_impls,
StructuredData::Writer(w) => &mut w.blobs, StructuredData::Writer(w) => &mut w.blobs,
} }
} }
fn deserialized_storage(
data: &mut StructuredDataReader,
) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
&mut data.blobs
}
} }
/// Extract bytes from BlobParts, used by Blob and File constructor /// Extract bytes from BlobParts, used by Blob and File constructor

View file

@ -17,9 +17,9 @@ use crate::dom::bindings::reflector::{
Reflector, reflect_dom_object, reflect_dom_object_with_proto, Reflector, reflect_dom_object, reflect_dom_object_with_proto,
}; };
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::serializable::{Serializable, StorageKey}; use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc; use crate::script_runtime::CanGc;
@ -252,18 +252,12 @@ impl Serializable for DOMException {
)) ))
} }
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<DomExceptionId, Self::Data>> { ) -> &'a mut Option<HashMap<DomExceptionId, Self::Data>> {
match data { match data {
StructuredData::Reader(reader) => &mut reader.exceptions, StructuredData::Reader(reader) => &mut reader.exceptions,
StructuredData::Writer(writer) => &mut writer.exceptions, StructuredData::Writer(writer) => &mut writer.exceptions,
} }
} }
fn deserialized_storage(
reader: &mut StructuredDataReader,
) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
&mut reader.dom_exceptions
}
} }

View file

@ -14,8 +14,8 @@ use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointRe
use crate::dom::bindings::error::Fallible; use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::reflect_dom_object_with_proto; use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::serializable::{Serializable, StorageKey}; use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods}; use crate::dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc; use crate::script_runtime::CanGc;
@ -163,18 +163,12 @@ impl Serializable for DOMPoint {
)) ))
} }
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<DomPointId, Self::Data>> { ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
match data { match data {
StructuredData::Reader(reader) => &mut reader.points, StructuredData::Reader(reader) => &mut reader.points,
StructuredData::Writer(writer) => &mut writer.points, StructuredData::Writer(writer) => &mut writer.points,
} }
} }
fn deserialized_storage(
reader: &mut StructuredDataReader,
) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
&mut reader.dom_points
}
} }

View file

@ -15,8 +15,8 @@ use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointRe
use crate::dom::bindings::error::Fallible; use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto}; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::serializable::{Serializable, StorageKey}; use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc; use crate::script_runtime::CanGc;
@ -172,18 +172,12 @@ impl Serializable for DOMPointReadOnly {
)) ))
} }
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<DomPointId, Self::Data>> { ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
match data { match data {
StructuredData::Reader(r) => &mut r.points, StructuredData::Reader(r) => &mut r.points,
StructuredData::Writer(w) => &mut w.points, StructuredData::Writer(w) => &mut w.points,
} }
} }
fn deserialized_storage(
reader: &mut StructuredDataReader,
) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
&mut reader.points_read_only
}
} }

View file

@ -23,7 +23,7 @@ use crate::dom::bindings::error::{Error, ErrorResult, ErrorToJsval};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object}; use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::structuredclone::{self, StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::{self, StructuredData};
use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::bindings::transferable::Transferable; use crate::dom::bindings::transferable::Transferable;
use crate::dom::bindings::utils::set_dictionary_property; use crate::dom::bindings::utils::set_dictionary_property;
@ -268,18 +268,14 @@ impl Transferable for MessagePort {
Ok(transferred_port) Ok(transferred_port)
} }
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<MessagePortId, Self::Data>> { ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data { match data {
StructuredData::Reader(r) => &mut r.port_impls, StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports, StructuredData::Writer(w) => &mut w.ports,
} }
} }
fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
&mut reader.message_ports
}
} }
impl MessagePortMethods<crate::DomTypeHolder> for MessagePort { impl MessagePortMethods<crate::DomTypeHolder> for MessagePort {

View file

@ -59,7 +59,7 @@ use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler}; use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::bindings::transferable::Transferable; use crate::dom::bindings::transferable::Transferable;
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use super::bindings::buffer_source::HeapBufferSource; use super::bindings::buffer_source::HeapBufferSource;
use super::bindings::codegen::Bindings::ReadableStreamBYOBReaderBinding::ReadableStreamBYOBReaderReadOptions; use super::bindings::codegen::Bindings::ReadableStreamBYOBReaderBinding::ReadableStreamBYOBReaderReadOptions;
@ -2247,16 +2247,12 @@ impl Transferable for ReadableStream {
} }
/// Note: we are relying on the port transfer, so the data returned here are related to the port. /// Note: we are relying on the port transfer, so the data returned here are related to the port.
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<MessagePortId, Self::Data>> { ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data { match data {
StructuredData::Reader(r) => &mut r.port_impls, StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports, StructuredData::Writer(w) => &mut w.ports,
} }
} }
fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
&mut reader.readable_streams
}
} }

View file

@ -27,7 +27,7 @@ use crate::dom::bindings::conversions::ConversionResult;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader}; use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::bindings::transferable::Transferable; use crate::dom::bindings::transferable::Transferable;
use crate::dom::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm}; use crate::dom::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
use crate::dom::domexception::{DOMErrorName, DOMException}; use crate::dom::domexception::{DOMErrorName, DOMException};
@ -1182,16 +1182,12 @@ impl Transferable for WritableStream {
} }
/// Note: we are relying on the port transfer, so the data returned here are related to the port. /// Note: we are relying on the port transfer, so the data returned here are related to the port.
fn serialized_storage( fn serialized_storage<'a>(
data: StructuredData<'_>, data: StructuredData<'a, '_>,
) -> &mut Option<HashMap<MessagePortId, Self::Data>> { ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data { match data {
StructuredData::Reader(r) => &mut r.port_impls, StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports, StructuredData::Writer(w) => &mut w.ports,
} }
} }
fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
&mut reader.writable_streams
}
} }