/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! This module implements structured cloning, as defined by [HTML](https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data).

use std::collections::HashMap;
use std::ffi::CStr;
use std::os::raw;
use std::ptr;

use base::id::{
    BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, ImageBitmapId, Index,
    MessagePortId, NamespaceIndex, OffscreenCanvasId, PipelineNamespaceId, QuotaExceededErrorId,
};
use constellation_traits::{
    BlobImpl, DomException, DomMatrix, DomPoint, DomQuad, DomRect, MessagePortImpl,
    Serializable as SerializableInterface, SerializableImageBitmap, SerializableQuotaExceededError,
    StructuredSerializedData, TransferableOffscreenCanvas, Transferrable as TransferrableInterface,
    TransformStreamData,
};
use js::gc::RootedVec;
use js::glue::{
    CopyJSStructuredCloneData, GetLengthOfJSStructuredCloneData, WriteBytesToJSStructuredCloneData,
};
use js::jsapi::{
    CloneDataPolicy, HandleObject as RawHandleObject, Heap, JS_IsExceptionPending,
    JS_ReadUint32Pair, JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject,
    JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
    MutableHandleObject as RawMutableHandleObject, StructuredCloneScope, TransferableOwnership,
};
use js::jsval::UndefinedValue;
use js::rust::wrappers::{JS_ReadStructuredClone, JS_WriteStructuredClone};
use js::rust::{
    CustomAutoRooterGuard, HandleValue, JSAutoStructuredCloneBufferWrapper, MutableHandleValue,
};
use script_bindings::conversions::{IDLInterface, SafeToJSValConvertible};
use strum::IntoEnumIterator;

use crate::dom::bindings::conversions::root_from_object;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::serializable::{Serializable, StorageKey};
use crate::dom::bindings::transferable::Transferable;
use crate::dom::blob::Blob;
use crate::dom::dompoint::DOMPoint;
use crate::dom::dompointreadonly::DOMPointReadOnly;
use crate::dom::globalscope::GlobalScope;
use crate::dom::imagebitmap::ImageBitmap;
use crate::dom::messageport::MessagePort;
use crate::dom::offscreencanvas::OffscreenCanvas;
use crate::dom::readablestream::ReadableStream;
use crate::dom::types::{
    DOMException, DOMMatrix, DOMMatrixReadOnly, DOMQuad, DOMRect, DOMRectReadOnly,
    QuotaExceededError, TransformStream,
};
use crate::dom::writablestream::WritableStream;
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};

// TODO: Should we add Min and Max const to https://github.com/servo/rust-mozjs/blob/master/src/consts.rs?
// TODO: Determine for sure which value Min and Max should have.
// NOTE: Current values found at https://dxr.mozilla.org/mozilla-central/
// rev/ff04d410e74b69acfab17ef7e73e7397602d5a68/js/public/StructuredClone.h#323
#[repr(u32)]
pub(super) enum StructuredCloneTags {
    /// To support additional types, add new tags with values incremented from the last one before Max.
    Min = 0xFFFF8000,
    DomBlob = 0xFFFF8001,
    MessagePort = 0xFFFF8002,
    Principals = 0xFFFF8003,
    DomPointReadOnly = 0xFFFF8004,
    DomPoint = 0xFFFF8005,
    ReadableStream = 0xFFFF8006,
    DomException = 0xFFFF8007,
    WritableStream = 0xFFFF8008,
    TransformStream = 0xFFFF8009,
    ImageBitmap = 0xFFFF800A,
    OffscreenCanvas = 0xFFFF800B,
    QuotaExceededError = 0xFFFF800C,
    DomRect = 0xFFFF800D,
    DomRectReadOnly = 0xFFFF800E,
    DomQuad = 0xFFFF800F,
    DomMatrix = 0xFFFF8010,
    DomMatrixReadOnly = 0xFFFF8011,
    Max = 0xFFFFFFFF,
}

impl From<SerializableInterface> for StructuredCloneTags {
    fn from(v: SerializableInterface) -> Self {
        match v {
            SerializableInterface::Blob => StructuredCloneTags::DomBlob,
            SerializableInterface::DomPoint => StructuredCloneTags::DomPoint,
            SerializableInterface::DomPointReadOnly => StructuredCloneTags::DomPointReadOnly,
            SerializableInterface::DomRect => StructuredCloneTags::DomRect,
            SerializableInterface::DomRectReadOnly => StructuredCloneTags::DomRectReadOnly,
            SerializableInterface::DomQuad => StructuredCloneTags::DomQuad,
            SerializableInterface::DomMatrix => StructuredCloneTags::DomMatrix,
            SerializableInterface::DomMatrixReadOnly => StructuredCloneTags::DomMatrixReadOnly,
            SerializableInterface::DomException => StructuredCloneTags::DomException,
            SerializableInterface::ImageBitmap => StructuredCloneTags::ImageBitmap,
            SerializableInterface::QuotaExceededError => StructuredCloneTags::QuotaExceededError,
        }
    }
}

impl From<TransferrableInterface> for StructuredCloneTags {
    fn from(v: TransferrableInterface) -> Self {
        match v {
            TransferrableInterface::ImageBitmap => StructuredCloneTags::ImageBitmap,
            TransferrableInterface::MessagePort => StructuredCloneTags::MessagePort,
            TransferrableInterface::OffscreenCanvas => StructuredCloneTags::OffscreenCanvas,
            TransferrableInterface::ReadableStream => StructuredCloneTags::ReadableStream,
            TransferrableInterface::WritableStream => StructuredCloneTags::WritableStream,
            TransferrableInterface::TransformStream => StructuredCloneTags::TransformStream,
        }
    }
}

fn reader_for_type(
    val: SerializableInterface,
) -> unsafe fn(
    &GlobalScope,
    *mut JSStructuredCloneReader,
    &mut StructuredDataReader<'_>,
    CanGc,
) -> *mut JSObject {
    match val {
        SerializableInterface::Blob => read_object::<Blob>,
        SerializableInterface::DomPoint => read_object::<DOMPoint>,
        SerializableInterface::DomPointReadOnly => read_object::<DOMPointReadOnly>,
        SerializableInterface::DomRect => read_object::<DOMRect>,
        SerializableInterface::DomRectReadOnly => read_object::<DOMRectReadOnly>,
        SerializableInterface::DomQuad => read_object::<DOMQuad>,
        SerializableInterface::DomMatrix => read_object::<DOMMatrix>,
        SerializableInterface::DomMatrixReadOnly => read_object::<DOMMatrixReadOnly>,
        SerializableInterface::DomException => read_object::<DOMException>,
        SerializableInterface::ImageBitmap => read_object::<ImageBitmap>,
        SerializableInterface::QuotaExceededError => read_object::<QuotaExceededError>,
    }
}

unsafe fn read_object<T: Serializable>(
    owner: &GlobalScope,
    r: *mut JSStructuredCloneReader,
    sc_reader: &mut StructuredDataReader<'_>,
    can_gc: CanGc,
) -> *mut JSObject {
    let mut name_space: u32 = 0;
    let mut index: u32 = 0;
    unsafe {
        assert!(JS_ReadUint32Pair(
            r,
            &mut name_space as *mut u32,
            &mut index as *mut u32
        ));
    }
    let storage_key = StorageKey { index, name_space };

    // 1. Re-build the key for the storage location
    // of the serialized object.
    let id: NamespaceIndex<T::Index> = storage_key.into();

    // 2. Get the transferred object from its storage, using the key.
    let objects = T::serialized_storage(StructuredData::Reader(sc_reader));
    let objects_map = objects
        .as_mut()
        .expect("The SC holder does not have any relevant objects");
    let serialized = objects_map
        .remove(&id)
        .expect("No object to be deserialized found.");
    if objects_map.is_empty() {
        *objects = None;
    }

    if let Ok(obj) = T::deserialize(owner, serialized, can_gc) {
        let reflector = obj.reflector().get_jsobject().get();
        sc_reader.roots.push(Heap::boxed(reflector));
        return reflector;
    }
    warn!("Reading structured data failed in {:?}.", owner.get_url());
    ptr::null_mut()
}

unsafe fn write_object<T: Serializable>(
    interface: SerializableInterface,
    owner: &GlobalScope,
    object: &T,
    w: *mut JSStructuredCloneWriter,
    sc_writer: &mut StructuredDataWriter,
) -> bool {
    if let Ok((new_id, serialized)) = object.serialize() {
        let objects = T::serialized_storage(StructuredData::Writer(sc_writer))
            .get_or_insert_with(HashMap::new);
        objects.insert(new_id, serialized);
        let storage_key = StorageKey::new(new_id);

        unsafe {
            assert!(JS_WriteUint32Pair(
                w,
                StructuredCloneTags::from(interface) as u32,
                0
            ));
            assert!(JS_WriteUint32Pair(
                w,
                storage_key.name_space,
                storage_key.index
            ));
        }
        return true;
    }
    warn!("Writing structured data failed in {:?}.", owner.get_url());
    false
}

unsafe extern "C" fn read_callback(
    cx: *mut JSContext,
    r: *mut JSStructuredCloneReader,
    _policy: *const CloneDataPolicy,
    tag: u32,
    _data: u32,
    closure: *mut raw::c_void,
) -> *mut JSObject {
    assert!(
        tag < StructuredCloneTags::Max as u32,
        "tag should be lower than StructuredCloneTags::Max"
    );
    assert!(
        tag > StructuredCloneTags::Min as u32,
        "tag should be higher than StructuredCloneTags::Min"
    );

    unsafe {
        let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
        let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
        let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
        for serializable in SerializableInterface::iter() {
            if tag == StructuredCloneTags::from(serializable) as u32 {
                let reader = reader_for_type(serializable);
                return reader(&global, r, sc_reader, CanGc::note());
            }
        }
    }

    ptr::null_mut()
}

enum OperationError {
    InterfaceDoesNotMatch,
    Exception(Error),
}

unsafe fn try_serialize<T: Serializable + IDLInterface>(
    val: SerializableInterface,
    cx: *mut JSContext,
    object: RawHandleObject,
    global: &GlobalScope,
    w: *mut JSStructuredCloneWriter,
    writer: &mut StructuredDataWriter,
) -> Result<bool, OperationError> {
    let object = unsafe { root_from_object::<T>(*object, cx) };
    if let Ok(obj) = object {
        return unsafe { Ok(write_object(val, global, &*obj, w, writer)) };
    }
    Err(OperationError::InterfaceDoesNotMatch)
}

type SerializeOperation = unsafe fn(
    SerializableInterface,
    *mut JSContext,
    RawHandleObject,
    &GlobalScope,
    *mut JSStructuredCloneWriter,
    &mut StructuredDataWriter,
) -> Result<bool, OperationError>;

fn serialize_for_type(val: SerializableInterface) -> SerializeOperation {
    match val {
        SerializableInterface::Blob => try_serialize::<Blob>,
        SerializableInterface::DomPoint => try_serialize::<DOMPoint>,
        SerializableInterface::DomPointReadOnly => try_serialize::<DOMPointReadOnly>,
        SerializableInterface::DomRect => try_serialize::<DOMRect>,
        SerializableInterface::DomRectReadOnly => try_serialize::<DOMRectReadOnly>,
        SerializableInterface::DomQuad => try_serialize::<DOMQuad>,
        SerializableInterface::DomMatrix => try_serialize::<DOMMatrix>,
        SerializableInterface::DomMatrixReadOnly => try_serialize::<DOMMatrixReadOnly>,
        SerializableInterface::DomException => try_serialize::<DOMException>,
        SerializableInterface::ImageBitmap => try_serialize::<ImageBitmap>,
        SerializableInterface::QuotaExceededError => try_serialize::<QuotaExceededError>,
    }
}

unsafe extern "C" fn write_callback(
    cx: *mut JSContext,
    w: *mut JSStructuredCloneWriter,
    obj: RawHandleObject,
    _same_process_scope_required: *mut bool,
    closure: *mut raw::c_void,
) -> bool {
    unsafe {
        let sc_writer = &mut *(closure as *mut StructuredDataWriter);
        let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
        let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
        for serializable in SerializableInterface::iter() {
            let serializer = serialize_for_type(serializable);
            if let Ok(result) = serializer(serializable, cx, obj, &global, w, sc_writer) {
                return result;
            }
        }
    }
    false
}

fn receiver_for_type(
    val: TransferrableInterface,
) -> fn(&GlobalScope, &mut StructuredDataReader<'_>, u64, RawMutableHandleObject) -> Result<(), ()>
{
    match val {
        TransferrableInterface::ImageBitmap => receive_object::<ImageBitmap>,
        TransferrableInterface::MessagePort => receive_object::<MessagePort>,
        TransferrableInterface::OffscreenCanvas => receive_object::<OffscreenCanvas>,
        TransferrableInterface::ReadableStream => receive_object::<ReadableStream>,
        TransferrableInterface::WritableStream => receive_object::<WritableStream>,
        TransferrableInterface::TransformStream => receive_object::<TransformStream>,
    }
}

fn receive_object<T: Transferable>(
    owner: &GlobalScope,
    sc_reader: &mut StructuredDataReader<'_>,
    extra_data: u64,
    return_object: RawMutableHandleObject,
) -> Result<(), ()> {
    // 1. Re-build the key for the storage location
    // of the transferred object.
    let big: [u8; 8] = extra_data.to_ne_bytes();
    let (name_space, index) = big.split_at(4);

    let namespace_id = PipelineNamespaceId(u32::from_ne_bytes(
        name_space
            .try_into()
            .expect("name_space to be a slice of four."),
    ));
    let id: NamespaceIndex<T::Index> = NamespaceIndex {
        namespace_id,
        index: Index::new(u32::from_ne_bytes(
            index.try_into().expect("index to be a slice of four."),
        ))
        .expect("Index to be non-zero"),
    };

    // 2. Get the transferred object from its storage, using the key.
    let storage = T::serialized_storage(StructuredData::Reader(sc_reader));
    let serialized = if let Some(objects) = storage.as_mut() {
        let object = objects.remove(&id).expect("Transferred port to be stored");
        if objects.is_empty() {
            *storage = None;
        }
        object
    } else {
        panic!(
            "An interface was transfer-received, yet the SC holder does not have any serialized objects"
        );
    };

    let Ok(received) = T::transfer_receive(owner, id, serialized) else {
        return Err(());
    };
    return_object.set(received.reflector().rootable().get());
    sc_reader.roots.push(Heap::boxed(return_object.get()));
    Ok(())
}

unsafe extern "C" fn read_transfer_callback(
    cx: *mut JSContext,
    _r: *mut JSStructuredCloneReader,
    _policy: *const CloneDataPolicy,
    tag: u32,
    _content: *mut raw::c_void,
    extra_data: u64,
    closure: *mut raw::c_void,
    return_object: RawMutableHandleObject,
) -> bool {
    let sc_reader = unsafe { &mut *(closure as *mut StructuredDataReader<'_>) };
    let in_realm_proof = unsafe { AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx)) };
    let owner = unsafe { GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)) };

    for transferrable in TransferrableInterface::iter() {
        if tag == StructuredCloneTags::from(transferrable) as u32 {
            let transfer_receiver = receiver_for_type(transferrable);
            if transfer_receiver(&owner, sc_reader, extra_data, return_object).is_ok() {
                return true;
            }
        }
    }
    false
}

unsafe fn try_transfer<T: Transferable + IDLInterface>(
    interface: TransferrableInterface,
    obj: RawHandleObject,
    cx: *mut JSContext,
    sc_writer: &mut StructuredDataWriter,
    tag: *mut u32,
    ownership: *mut TransferableOwnership,
    extra_data: *mut u64,
) -> Result<(), OperationError> {
    let object = unsafe { root_from_object::<T>(*obj, cx) };
    let Ok(object) = object else {
        return Err(OperationError::InterfaceDoesNotMatch);
    };

    unsafe { *tag = StructuredCloneTags::from(interface) as u32 };
    unsafe { *ownership = TransferableOwnership::SCTAG_TMO_CUSTOM };

    let (id, object) = object.transfer().map_err(OperationError::Exception)?;

    // 2. Store the transferred object at a given key.
    let objects =
        T::serialized_storage(StructuredData::Writer(sc_writer)).get_or_insert_with(HashMap::new);
    objects.insert(id, object);

    let index = id.index.0.get();

    let mut big: [u8; 8] = [0; 8];
    let name_space = id.namespace_id.0.to_ne_bytes();
    let index = index.to_ne_bytes();

    let (left, right) = big.split_at_mut(4);
    left.copy_from_slice(&name_space);
    right.copy_from_slice(&index);

    // 3. Return a u64 representation of the key where the object is stored.
    unsafe { *extra_data = u64::from_ne_bytes(big) };
    Ok(())
}

type TransferOperation = unsafe fn(
    TransferrableInterface,
    RawHandleObject,
    *mut JSContext,
    &mut StructuredDataWriter,
    *mut u32,
    *mut TransferableOwnership,
    *mut u64,
) -> Result<(), OperationError>;

fn transfer_for_type(val: TransferrableInterface) -> TransferOperation {
    match val {
        TransferrableInterface::ImageBitmap => try_transfer::<ImageBitmap>,
        TransferrableInterface::MessagePort => try_transfer::<MessagePort>,
        TransferrableInterface::OffscreenCanvas => try_transfer::<OffscreenCanvas>,
        TransferrableInterface::ReadableStream => try_transfer::<ReadableStream>,
        TransferrableInterface::WritableStream => try_transfer::<WritableStream>,
        TransferrableInterface::TransformStream => try_transfer::<TransformStream>,
    }
}

/// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
unsafe extern "C" fn write_transfer_callback(
    cx: *mut JSContext,
    obj: RawHandleObject,
    closure: *mut raw::c_void,
    tag: *mut u32,
    ownership: *mut TransferableOwnership,
    _content: *mut *mut raw::c_void,
    extra_data: *mut u64,
) -> bool {
    let sc_writer = unsafe { &mut *(closure as *mut StructuredDataWriter) };
    for transferable in TransferrableInterface::iter() {
        let try_transfer = transfer_for_type(transferable);

        let transfer_result =
            unsafe { try_transfer(transferable, obj, cx, sc_writer, tag, ownership, extra_data) };
        match transfer_result {
            Err(error) => match error {
                OperationError::InterfaceDoesNotMatch => {},
                OperationError::Exception(error) => {
                    sc_writer.error = Some(error);
                    return false;
                },
            },
            Ok(..) => return true,
        }
    }

    false
}

unsafe extern "C" fn free_transfer_callback(
    _tag: u32,
    _ownership: TransferableOwnership,
    _content: *mut raw::c_void,
    _extra_data: u64,
    _closure: *mut raw::c_void,
) {
}

unsafe fn can_transfer_for_type(
    transferable: TransferrableInterface,
    obj: RawHandleObject,
    cx: *mut JSContext,
) -> Result<bool, ()> {
    unsafe fn can_transfer<T: Transferable + IDLInterface>(
        obj: RawHandleObject,
        cx: *mut JSContext,
    ) -> Result<bool, ()> {
        unsafe { root_from_object::<T>(*obj, cx).map(|o| Transferable::can_transfer(&*o)) }
    }

    unsafe {
        match transferable {
            TransferrableInterface::ImageBitmap => can_transfer::<ImageBitmap>(obj, cx),
            TransferrableInterface::MessagePort => can_transfer::<MessagePort>(obj, cx),
            TransferrableInterface::OffscreenCanvas => can_transfer::<OffscreenCanvas>(obj, cx),
            TransferrableInterface::ReadableStream => can_transfer::<ReadableStream>(obj, cx),
            TransferrableInterface::WritableStream => can_transfer::<WritableStream>(obj, cx),
            TransferrableInterface::TransformStream => can_transfer::<TransformStream>(obj, cx),
        }
    }
}

unsafe extern "C" fn can_transfer_callback(
    cx: *mut JSContext,
    obj: RawHandleObject,
    _same_process_scope_required: *mut bool,
    _closure: *mut raw::c_void,
) -> bool {
    for transferable in TransferrableInterface::iter() {
        let can_transfer = unsafe { can_transfer_for_type(transferable, obj, cx) };
        if let Ok(can_transfer) = can_transfer {
            return can_transfer;
        }
    }
    false
}

unsafe extern "C" fn report_error_callback(
    _cx: *mut JSContext,
    _errorid: u32,
    closure: *mut raw::c_void,
    error_message: *const ::std::os::raw::c_char,
) {
    let msg_result = unsafe { CStr::from_ptr(error_message).to_str().map(str::to_string) };

    if let Ok(msg) = msg_result {
        let error = unsafe { &mut *(closure as *mut Option<Error>) };

        if error.is_none() {
            *error = Some(Error::DataClone(Some(msg)));
        }
    }
}

unsafe extern "C" fn sab_cloned_callback(
    _cx: *mut JSContext,
    _receiving: bool,
    _closure: *mut ::std::os::raw::c_void,
) -> bool {
    false
}

static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredCloneCallbacks {
    read: Some(read_callback),
    write: Some(write_callback),
    reportError: Some(report_error_callback),
    readTransfer: Some(read_transfer_callback),
    writeTransfer: Some(write_transfer_callback),
    freeTransfer: Some(free_transfer_callback),
    canTransfer: Some(can_transfer_callback),
    sabCloned: Some(sab_cloned_callback),
};

pub(crate) enum StructuredData<'a, 'b> {
    Reader(&'a mut StructuredDataReader<'b>),
    Writer(&'a mut StructuredDataWriter),
}

/// 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>
#[repr(C)]
pub(crate) struct StructuredDataReader<'a> {
    /// A error record.
    error: Option<Error>,
    /// Rooted copies of every deserialized object to ensure they are not garbage collected.
    roots: RootedVec<'a, Box<Heap<*mut JSObject>>>,
    /// A map of port implementations,
    /// used as part of the "transfer-receiving" steps of ports,
    /// to produce the DOM ports stored in `message_ports` above.
    pub(crate) port_impls: Option<HashMap<MessagePortId, MessagePortImpl>>,
    /// A map of transform stream implementations,
    pub(crate) transform_streams_port_impls: Option<HashMap<MessagePortId, TransformStreamData>>,
    /// A map of blob implementations,
    /// used as part of the "deserialize" steps of blobs,
    /// to produce the DOM blobs stored in `blobs` above.
    pub(crate) blob_impls: Option<HashMap<BlobId, BlobImpl>>,
    /// A map of serialized points.
    pub(crate) points: Option<HashMap<DomPointId, DomPoint>>,
    /// A map of serialized rects.
    pub(crate) rects: Option<HashMap<DomRectId, DomRect>>,
    /// A map of serialized quads.
    pub(crate) quads: Option<HashMap<DomQuadId, DomQuad>>,
    /// A map of serialized matrices.
    pub(crate) matrices: Option<HashMap<DomMatrixId, DomMatrix>>,
    /// A map of serialized exceptions.
    pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>,
    /// A map of serialized quota exceeded errors.
    pub(crate) quota_exceeded_errors:
        Option<HashMap<QuotaExceededErrorId, SerializableQuotaExceededError>>,
    // A map of serialized image bitmaps.
    pub(crate) image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>,
    /// A map of transferred image bitmaps.
    pub(crate) transferred_image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>,
    /// A map of transferred offscreen canvases.
    pub(crate) offscreen_canvases: Option<HashMap<OffscreenCanvasId, TransferableOffscreenCanvas>>,
}

/// A data holder for transferred and serialized objects.
#[derive(Default)]
#[repr(C)]
pub(crate) struct StructuredDataWriter {
    /// Error record.
    pub(crate) error: Option<Error>,
    /// Transferred ports.
    pub(crate) ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
    /// Transferred transform streams.
    pub(crate) transform_streams_port: Option<HashMap<MessagePortId, TransformStreamData>>,
    /// Serialized points.
    pub(crate) points: Option<HashMap<DomPointId, DomPoint>>,
    /// Serialized rects.
    pub(crate) rects: Option<HashMap<DomRectId, DomRect>>,
    /// Serialized quads.
    pub(crate) quads: Option<HashMap<DomQuadId, DomQuad>>,
    /// Serialized matrices.
    pub(crate) matrices: Option<HashMap<DomMatrixId, DomMatrix>>,
    /// Serialized exceptions.
    pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>,
    /// Serialized quota exceeded errors.
    pub(crate) quota_exceeded_errors:
        Option<HashMap<QuotaExceededErrorId, SerializableQuotaExceededError>>,
    /// Serialized blobs.
    pub(crate) blobs: Option<HashMap<BlobId, BlobImpl>>,
    /// Serialized image bitmaps.
    pub(crate) image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>,
    /// Transferred image bitmaps.
    pub(crate) transferred_image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>,
    /// Transferred offscreen canvases.
    pub(crate) offscreen_canvases: Option<HashMap<OffscreenCanvasId, TransferableOffscreenCanvas>>,
}

/// Writes a structured clone. Returns a `DataClone` error if that fails.
pub(crate) fn write(
    cx: SafeJSContext,
    message: HandleValue,
    transfer: Option<CustomAutoRooterGuard<Vec<*mut JSObject>>>,
) -> Fallible<StructuredSerializedData> {
    unsafe {
        rooted!(in(*cx) let mut val = UndefinedValue());
        if let Some(transfer) = transfer {
            transfer.safe_to_jsval(cx, val.handle_mut());
        }
        let mut sc_writer = StructuredDataWriter::default();
        let sc_writer_ptr = &mut sc_writer as *mut _;

        let scbuf = JSAutoStructuredCloneBufferWrapper::new(
            StructuredCloneScope::DifferentProcess,
            &STRUCTURED_CLONE_CALLBACKS,
        );
        let scdata = &mut ((*scbuf.as_raw_ptr()).data_);
        let policy = CloneDataPolicy {
            allowIntraClusterClonableSharedObjects_: false,
            allowSharedMemoryObjects_: false,
        };
        let result = JS_WriteStructuredClone(
            *cx,
            message,
            scdata,
            StructuredCloneScope::DifferentProcess,
            &policy,
            &STRUCTURED_CLONE_CALLBACKS,
            sc_writer_ptr as *mut raw::c_void,
            val.handle(),
        );
        if !result {
            let error = if JS_IsExceptionPending(*cx) {
                Error::JSFailed
            } else {
                sc_writer.error.unwrap_or(Error::DataClone(None))
            };

            return Err(error);
        }

        let nbytes = GetLengthOfJSStructuredCloneData(scdata);
        let mut data = Vec::with_capacity(nbytes);
        CopyJSStructuredCloneData(scdata, data.as_mut_ptr());
        data.set_len(nbytes);

        let data = StructuredSerializedData {
            serialized: data,
            ports: sc_writer.ports.take(),
            transform_streams: sc_writer.transform_streams_port.take(),
            points: sc_writer.points.take(),
            rects: sc_writer.rects.take(),
            quads: sc_writer.quads.take(),
            matrices: sc_writer.matrices.take(),
            exceptions: sc_writer.exceptions.take(),
            quota_exceeded_errors: sc_writer.quota_exceeded_errors.take(),
            blobs: sc_writer.blobs.take(),
            image_bitmaps: sc_writer.image_bitmaps.take(),
            transferred_image_bitmaps: sc_writer.transferred_image_bitmaps.take(),
            offscreen_canvases: sc_writer.offscreen_canvases.take(),
        };

        Ok(data)
    }
}

/// Read structured serialized data, possibly containing transferred objects.
/// Returns a vec of rooted transfer-received ports, or an error.
pub(crate) fn read(
    global: &GlobalScope,
    mut data: StructuredSerializedData,
    rval: MutableHandleValue,
) -> Fallible<Vec<DomRoot<MessagePort>>> {
    let cx = GlobalScope::get_cx();
    let _ac = enter_realm(global);
    rooted_vec!(let mut roots);
    let mut sc_reader = StructuredDataReader {
        error: None,
        roots,
        port_impls: data.ports.take(),
        transform_streams_port_impls: data.transform_streams.take(),
        blob_impls: data.blobs.take(),
        points: data.points.take(),
        rects: data.rects.take(),
        quads: data.quads.take(),
        matrices: data.matrices.take(),
        exceptions: data.exceptions.take(),
        quota_exceeded_errors: data.quota_exceeded_errors.take(),
        image_bitmaps: data.image_bitmaps.take(),
        transferred_image_bitmaps: data.transferred_image_bitmaps.take(),
        offscreen_canvases: data.offscreen_canvases.take(),
    };
    let sc_reader_ptr = &mut sc_reader as *mut _;
    unsafe {
        let scbuf = JSAutoStructuredCloneBufferWrapper::new(
            StructuredCloneScope::DifferentProcess,
            &STRUCTURED_CLONE_CALLBACKS,
        );
        let scdata = &mut ((*scbuf.as_raw_ptr()).data_);

        WriteBytesToJSStructuredCloneData(
            data.serialized.as_mut_ptr() as *const u8,
            data.serialized.len(),
            scdata,
        );

        let result = JS_ReadStructuredClone(
            *cx,
            scdata,
            JS_STRUCTURED_CLONE_VERSION,
            StructuredCloneScope::DifferentProcess,
            rval,
            &CloneDataPolicy {
                allowIntraClusterClonableSharedObjects_: false,
                allowSharedMemoryObjects_: false,
            },
            &STRUCTURED_CLONE_CALLBACKS,
            sc_reader_ptr as *mut raw::c_void,
        );
        if !result {
            let error = if JS_IsExceptionPending(*cx) {
                Error::JSFailed
            } else {
                sc_reader.error.unwrap_or(Error::DataClone(None))
            };

            return Err(error);
        }

        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.
        assert!(sc_reader.port_impls.is_none());
        Ok(message_ports)
    }
}
