use super::{
GeneralizedAutoDropDartPersistentHandle, GeneralizedDartHandle, GeneralizedDartHandleBox,
};
use crate::dart_opaque::action::DartHandlerPortAction;
use crate::for_generated::{box_from_leak_ptr, new_leak_box_ptr};
use crate::generalized_isolate::Channel;
use crate::generalized_isolate::IntoDart;
use crate::misc::logs::log_warn_or_println;
use crate::platform_types::{handle_to_message_port, SendableMessagePortHandle};
#[cfg(target_family = "wasm")]
use wasm_bindgen::prelude::*;
#[derive(Debug)]
pub(super) struct DartOpaqueNonClone {
persistent_handle: Option<GeneralizedDartHandleBox<GeneralizedAutoDropDartPersistentHandle>>,
dart_handler_port: SendableMessagePortHandle,
}
impl DartOpaqueNonClone {
pub(super) fn new(
handle: GeneralizedDartHandle,
dart_handler_port: SendableMessagePortHandle,
) -> Self {
let auto_drop_persistent_handle =
GeneralizedAutoDropDartPersistentHandle::new_from_non_persistent_handle(handle);
Self {
persistent_handle: Some(GeneralizedDartHandleBox::new(auto_drop_persistent_handle)),
dart_handler_port,
}
}
pub(super) fn into_inner(mut self) -> GeneralizedAutoDropDartPersistentHandle {
if !(self.persistent_handle.as_ref().unwrap()).check_context() {
panic!("DartOpaque can only be used on the creation thread");
}
self.persistent_handle.take().unwrap().into_inner()
}
pub(super) fn create_dart_handle(&self) -> GeneralizedDartHandle {
(self.persistent_handle.as_ref().unwrap().as_ref()).create_dart_handle()
}
pub(crate) fn dart_handler_port(&self) -> &SendableMessagePortHandle {
&self.dart_handler_port
}
}
impl Drop for DartOpaqueNonClone {
fn drop(&mut self) {
if let Some(persistent_handle) = self.persistent_handle.take() {
if !persistent_handle.check_context() {
drop_thread_box_persistent_handle_via_port(
persistent_handle,
&self.dart_handler_port,
)
}
}
}
}
fn drop_thread_box_persistent_handle_via_port(
persistent_handle: GeneralizedDartHandleBox<GeneralizedAutoDropDartPersistentHandle>,
dart_handler_port: &SendableMessagePortHandle,
) {
let channel = Channel::new(handle_to_message_port(dart_handler_port));
let ptr = new_leak_box_ptr(persistent_handle) as usize;
let msg = [
DartHandlerPortAction::DartOpaqueDrop.into_dart(),
ptr.into_dart(),
];
if !channel.post(msg) {
log_warn_or_println(
"Drop DartOpaque after closing the port, thus the object will be leaked forever.",
);
};
}
#[cfg(not(target_family = "wasm"))]
#[no_mangle]
pub unsafe extern "C" fn frb_dart_opaque_drop_thread_box_persistent_handle(ptr: usize) {
frb_dart_opaque_drop_thread_box_persistent_handle_inner(ptr)
}
#[cfg(target_family = "wasm")]
#[wasm_bindgen]
pub unsafe extern "C" fn frb_dart_opaque_drop_thread_box_persistent_handle(ptr: usize) {
frb_dart_opaque_drop_thread_box_persistent_handle_inner(ptr)
}
unsafe fn frb_dart_opaque_drop_thread_box_persistent_handle_inner(ptr: usize) {
let value: GeneralizedDartHandleBox<GeneralizedAutoDropDartPersistentHandle> =
*box_from_leak_ptr(ptr as _);
drop(value);
}