wry_bindgen_core/
runtime.rs1use alloc::boxed::Box;
12use core::ops::{Deref, DerefMut};
13
14use wry_bindgen_runtime::wire::Runtime as RuntimeState;
15use wry_bindgen_runtime::wire::{DecodedData, EncodedData, JsRef, ObjectHandle};
16
17use crate::BatchableResult;
18
19struct CheckedOutObject<T: 'static> {
24 handle: ObjectHandle,
25 value: Option<T>,
26}
27
28impl<T: 'static> CheckedOutObject<T> {
29 fn checkout(rt: &mut Runtime, handle: ObjectHandle) -> Self {
33 let value = rt.take_object::<T>(handle).expect("invalid handle");
34 Self {
35 handle,
36 value: Some(value),
37 }
38 }
39
40 fn get(&self) -> &T {
41 self.value.as_ref().expect("checked-out object missing")
42 }
43
44 fn get_mut(&mut self) -> &mut T {
45 self.value.as_mut().expect("checked-out object missing")
46 }
47}
48
49impl<T> Deref for CheckedOutObject<T> {
50 type Target = T;
51
52 fn deref(&self) -> &Self::Target {
53 self.get()
54 }
55}
56
57impl<T> DerefMut for CheckedOutObject<T> {
58 fn deref_mut(&mut self) -> &mut Self::Target {
59 self.get_mut()
60 }
61}
62
63impl<T: 'static> Drop for CheckedOutObject<T> {
64 fn drop(&mut self) {
65 if let Some(value) = self.value.take() {
66 with_runtime(|rt| rt.reinsert_object(self.handle, value));
67 }
68 }
69}
70
71pub struct Runtime<'a> {
73 backend: &'a mut RuntimeState,
74}
75
76impl Runtime<'_> {
77 pub fn insert_object<T: 'static>(&mut self, obj: T) -> ObjectHandle {
79 self.backend.insert_object_box(Box::new(obj))
80 }
81
82 fn take_object<T: 'static>(&mut self, handle: ObjectHandle) -> Option<T> {
83 self.backend
84 .take_object_box(handle)
85 .map(|obj| *obj.downcast::<T>().expect("object type mismatch"))
86 }
87
88 pub fn object<T: 'static>(
90 &mut self,
91 handle: ObjectHandle,
92 ) -> impl DerefMut<Target = T> + use<T> {
93 CheckedOutObject::checkout(self, handle)
94 }
95
96 pub fn remove_object<T: 'static>(&mut self, handle: ObjectHandle) -> Option<T> {
98 self.backend
99 .remove_object_untyped(handle)
100 .map(|obj| *obj.downcast::<T>().expect("object type mismatch"))
101 }
102
103 fn reinsert_object<T: 'static>(&mut self, handle: ObjectHandle, obj: T) {
104 self.backend.reinsert_object_box(handle, Box::new(obj));
105 }
106
107 pub(crate) fn next_placeholder_ref(&mut self) -> JsRef {
112 self.backend.next_placeholder_ref()
113 }
114}
115
116pub fn with_runtime<R>(f: impl FnOnce(&mut Runtime) -> R) -> R {
121 wry_bindgen_runtime::wire::with_runtime(|backend| f(&mut Runtime { backend }))
122}
123
124pub(crate) fn with_backend<R>(f: impl FnOnce(&mut RuntimeState) -> R) -> R {
125 wry_bindgen_runtime::wire::with_runtime(f)
126}
127
128pub(crate) fn run_js_sync<R: BatchableResult + 'static>(
133 fn_id: u32,
134 add_args: impl FnOnce(&mut EncodedData),
135) -> R {
136 wry_bindgen_runtime::wire::run_js_sync(
137 fn_id,
138 add_args,
139 |backend| R::try_placeholder(&mut Runtime { backend }),
140 |mut data: DecodedData<'_>| R::decode(&mut data).expect("Failed to decode return value"),
141 )
142}