jsi_sys/ffi/
base.rs

1#[cxx::bridge]
2pub mod ffi {
3    #[namespace = "facebook::jsi"]
4    unsafe extern "C++" {
5        include!("jsi/jsi.h");
6        include!("wrapper.h");
7
8        pub type Buffer;
9
10        fn size(self: &Buffer) -> usize;
11        unsafe fn data(self: &Buffer) -> *const u8;
12
13        pub type StringBuffer;
14
15        pub type PreparedJavaScript;
16
17        #[namespace = "jsi_rs::ffi"]
18        pub type ConstPreparedJavaScript;
19
20        #[namespace = "jsi_rs::ffi"]
21        fn PreparedJavaScript_asConst(
22            js: &SharedPtr<PreparedJavaScript>,
23        ) -> SharedPtr<ConstPreparedJavaScript>;
24
25        pub type Instrumentation;
26        pub type Scope;
27        pub type JSIException;
28        pub type JSError;
29
30        pub type Runtime;
31
32        #[namespace = "jsi_rs::ffi"]
33        pub fn Runtime_evaluateJavaScript(
34            _self: Pin<&mut Runtime>,
35            buffer: &SharedPtr<Buffer>,
36            source_url: &str,
37        ) -> UniquePtr<JsiValue>;
38        #[namespace = "jsi_rs::ffi"]
39        pub fn Runtime_prepareJavaScript(
40            _self: Pin<&mut Runtime>,
41            buffer: &SharedPtr<Buffer>,
42            source_url: &str,
43        ) -> SharedPtr<ConstPreparedJavaScript>;
44        #[namespace = "jsi_rs::ffi"]
45        pub fn Runtime_evaluatePreparedJavaScript(
46            _self: Pin<&mut Runtime>,
47            js: &SharedPtr<ConstPreparedJavaScript>,
48        ) -> UniquePtr<JsiValue>;
49        #[cxx_name = "drainMicrotasks"]
50        pub fn drain_microtasks(self: Pin<&mut Runtime>, max_microtasks_hint: i32) -> bool;
51        #[namespace = "jsi_rs::ffi"]
52        pub fn Runtime_global(_self: Pin<&mut Runtime>) -> UniquePtr<JsiObject>;
53        #[namespace = "jsi_rs::ffi"]
54        pub fn Runtime_description(_self: Pin<&mut Runtime>) -> UniquePtr<CxxString>;
55        #[cxx_name = "isInspectable"]
56        pub fn is_inspectable(self: Pin<&mut Runtime>) -> bool;
57        pub fn instrumentation(self: Pin<&mut Runtime>) -> Pin<&mut Instrumentation>;
58
59        pub type HostObject;
60
61        #[namespace = "jsi_rs::ffi"]
62        pub fn HostObject_get(
63            _self: Pin<&mut HostObject>,
64            rt: Pin<&mut Runtime>,
65            name: &PropNameID,
66        ) -> UniquePtr<JsiValue>;
67        pub fn set(
68            self: Pin<&mut HostObject>,
69            rt: Pin<&mut Runtime>,
70            name: &PropNameID,
71            value: &JsiValue,
72        );
73        #[namespace = "jsi_rs::ffi"]
74        pub fn HostObject_getPropertyNames(
75            _self: Pin<&mut HostObject>,
76            rt: Pin<&mut Runtime>,
77        ) -> UniquePtr<CxxVector<PropNameID>>;
78
79        pub type Pointer;
80
81        pub type PropNameID;
82
83        #[namespace = "jsi_rs::ffi"]
84        pub fn PropNameID_forUtf8(rt: Pin<&mut Runtime>, str: &str) -> UniquePtr<PropNameID>;
85        #[namespace = "jsi_rs::ffi"]
86        pub fn PropNameID_forString(
87            rt: Pin<&mut Runtime>,
88            str: &JsiString,
89        ) -> UniquePtr<PropNameID>;
90        #[namespace = "jsi_rs::ffi"]
91        pub fn PropNameID_toUtf8(_self: &PropNameID, rt: Pin<&mut Runtime>)
92            -> UniquePtr<CxxString>;
93        #[namespace = "jsi_rs::ffi"]
94        pub fn PropNameID_compare(
95            rt: Pin<&mut Runtime>,
96            lhs: &PropNameID,
97            rhs: &PropNameID,
98        ) -> bool;
99        #[namespace = "jsi_rs::ffi"]
100        pub fn PropNameID_copy(_self: &PropNameID, rt: Pin<&mut Runtime>) -> UniquePtr<PropNameID>;
101
102        #[cxx_name = "Symbol"]
103        pub type JsiSymbol;
104        #[namespace = "jsi_rs::ffi"]
105        pub fn Symbol_compare(rt: Pin<&mut Runtime>, lhs: &JsiSymbol, rhs: &JsiSymbol) -> bool;
106        #[namespace = "jsi_rs::ffi"]
107        pub fn Symbol_toString(_self: &JsiSymbol, rt: Pin<&mut Runtime>) -> UniquePtr<CxxString>;
108
109        #[cxx_name = "String"]
110        pub type JsiString;
111        #[namespace = "jsi_rs::ffi"]
112        pub fn String_fromUtf8(rt: Pin<&mut Runtime>, str: &str) -> UniquePtr<JsiString>;
113        #[namespace = "jsi_rs::ffi"]
114        pub fn String_compare(rt: Pin<&mut Runtime>, lhs: &JsiString, rhs: &JsiString) -> bool;
115        #[namespace = "jsi_rs::ffi"]
116        pub fn String_toString(_self: &JsiString, rt: Pin<&mut Runtime>) -> UniquePtr<CxxString>;
117
118        #[cxx_name = "Object"]
119        pub type JsiObject;
120        #[namespace = "jsi_rs::ffi"]
121        pub fn Object_create(rt: Pin<&mut Runtime>) -> UniquePtr<JsiObject>;
122        #[namespace = "jsi_rs::ffi"]
123        pub fn Object_createFromHostObjectShared(
124            rt: Pin<&mut Runtime>,
125            ho: SharedPtr<HostObject>,
126        ) -> UniquePtr<JsiObject>;
127        #[namespace = "jsi_rs::ffi"]
128        pub fn Object_createFromHostObjectUnique(
129            rt: Pin<&mut Runtime>,
130            ho: UniquePtr<HostObject>,
131        ) -> UniquePtr<JsiObject>;
132        #[namespace = "jsi_rs::ffi"]
133        pub fn Object_compare(rt: Pin<&mut Runtime>, lhs: &JsiObject, rhs: &JsiObject) -> bool;
134        #[cxx_name = "instanceOf"]
135        pub fn instance_of(self: &JsiObject, rt: Pin<&mut Runtime>, ctor: &JsiFunction) -> bool;
136        #[namespace = "jsi_rs::ffi"]
137        pub fn Object_getProperty(
138            _self: &JsiObject,
139            rt: Pin<&mut Runtime>,
140            prop: &PropNameID,
141        ) -> UniquePtr<JsiValue>;
142        #[cxx_name = "hasProperty"]
143        pub fn has_property(self: &JsiObject, rt: Pin<&mut Runtime>, prop: &PropNameID) -> bool;
144        #[namespace = "jsi_rs::ffi"]
145        pub fn Object_setProperty(
146            _self: Pin<&mut JsiObject>,
147            rt: Pin<&mut Runtime>,
148            prop: &PropNameID,
149            value: &JsiValue,
150        );
151        #[cxx_name = "isArray"]
152        pub fn is_array(self: &JsiObject, rt: Pin<&mut Runtime>) -> bool;
153        #[cxx_name = "isArrayBuffer"]
154        pub fn is_array_buffer(self: &JsiObject, rt: Pin<&mut Runtime>) -> bool;
155        #[cxx_name = "isFunction"]
156        pub fn is_function(self: &JsiObject, rt: Pin<&mut Runtime>) -> bool;
157        // TODO: isHostObject after implementing Rust HostObject subclass
158        #[namespace = "jsi_rs::ffi"]
159        pub fn Object_asArray(
160            _self: &JsiObject,
161            rt: Pin<&mut Runtime>,
162        ) -> Result<UniquePtr<JsiArray>>;
163        // NOTICE: this method will assert if the object is not an array buffer;
164        // i'm not sure if that's the same as an exception or whether it will
165        // lead to UB
166        #[namespace = "jsi_rs::ffi"]
167        pub fn Object_asArrayBuffer(
168            _self: &JsiObject,
169            rt: Pin<&mut Runtime>,
170        ) -> Result<UniquePtr<JsiArrayBuffer>>;
171        #[namespace = "jsi_rs::ffi"]
172        pub fn Object_asFunction(
173            _self: &JsiObject,
174            rt: Pin<&mut Runtime>,
175        ) -> Result<UniquePtr<JsiFunction>>;
176        #[namespace = "jsi_rs::ffi"]
177        pub fn Object_asHostObject(
178            _self: &JsiObject,
179            rt: Pin<&mut Runtime>,
180        ) -> Result<SharedPtr<HostObject>>;
181        #[namespace = "jsi_rs::ffi"]
182        pub fn Object_getPropertyNames(
183            _self: Pin<&mut JsiObject>,
184            rt: Pin<&mut Runtime>,
185        ) -> UniquePtr<JsiArray>;
186
187        #[cxx_name = "WeakObject"]
188        pub type JsiWeakObject;
189        #[namespace = "jsi_rs::ffi"]
190        pub fn WeakObject_fromObject(
191            rt: Pin<&mut Runtime>,
192            object: &JsiObject,
193        ) -> UniquePtr<JsiWeakObject>;
194        #[namespace = "jsi_rs::ffi"]
195        pub fn WeakObject_lock(
196            _self: Pin<&mut JsiWeakObject>,
197            rt: Pin<&mut Runtime>,
198        ) -> UniquePtr<JsiValue>;
199
200        #[cxx_name = "Array"]
201        pub type JsiArray;
202        #[namespace = "jsi_rs::ffi"]
203        pub fn Array_createWithLength(rt: Pin<&mut Runtime>, length: usize) -> UniquePtr<JsiArray>;
204        #[namespace = "jsi_rs::ffi"]
205        pub fn Array_get(
206            _self: &JsiArray,
207            rt: Pin<&mut Runtime>,
208            index: usize,
209        ) -> UniquePtr<JsiValue>;
210        #[namespace = "jsi_rs::ffi"]
211        pub fn Array_set(
212            _self: Pin<&mut JsiArray>,
213            rt: Pin<&mut Runtime>,
214            index: usize,
215            value: &JsiValue,
216        );
217        pub fn length(self: &JsiArray, rt: Pin<&mut Runtime>) -> usize;
218
219        #[cxx_name = "ArrayBuffer"]
220        pub type JsiArrayBuffer;
221        pub unsafe fn data(self: &JsiArrayBuffer, rt: Pin<&mut Runtime>) -> *mut u8;
222        pub fn length(self: &JsiArrayBuffer, rt: Pin<&mut Runtime>) -> usize;
223
224        #[cxx_name = "Function"]
225        pub type JsiFunction;
226        #[namespace = "jsi_rs::ffi"]
227        pub fn Function_call(
228            _self: &JsiFunction,
229            rt: Pin<&mut Runtime>,
230            args: &CxxVector<JsiValue>,
231        ) -> Result<UniquePtr<JsiValue>>;
232        #[namespace = "jsi_rs::ffi"]
233        pub fn Function_callAsConstructor(
234            _self: &JsiFunction,
235            rt: Pin<&mut Runtime>,
236            args: &CxxVector<JsiValue>,
237        ) -> Result<UniquePtr<JsiValue>>;
238        #[namespace = "jsi_rs::ffi"]
239        pub fn Function_callWithThis(
240            _self: &JsiFunction,
241            rt: Pin<&mut Runtime>,
242            thisObj: &JsiObject,
243            args: &CxxVector<JsiValue>,
244        ) -> Result<UniquePtr<JsiValue>>;
245        #[namespace = "jsi_rs::ffi"]
246        pub unsafe fn Function_createFromHostFunction(
247            rt: Pin<&mut Runtime>,
248            name: &PropNameID,
249            param_count: u32,
250            closure: *mut c_void,
251        ) -> UniquePtr<JsiFunction>;
252        #[cxx_name = "isHostFunction"]
253        pub fn is_host_fn(self: &JsiFunction, rt: Pin<&mut Runtime>) -> bool;
254
255        #[cxx_name = "Value"]
256        pub type JsiValue;
257        #[namespace = "jsi_rs::ffi"]
258        pub fn Value_fromUndefined() -> UniquePtr<JsiValue>;
259        #[namespace = "jsi_rs::ffi"]
260        pub fn Value_fromNull() -> UniquePtr<JsiValue>;
261        #[namespace = "jsi_rs::ffi"]
262        pub fn Value_fromBool(b: bool) -> UniquePtr<JsiValue>;
263        #[namespace = "jsi_rs::ffi"]
264        pub fn Value_fromDouble(d: f64) -> UniquePtr<JsiValue>;
265        #[namespace = "jsi_rs::ffi"]
266        pub fn Value_fromInt(i: i32) -> UniquePtr<JsiValue>;
267        #[namespace = "jsi_rs::ffi"]
268        pub fn Value_fromString(
269            rt: Pin<&mut Runtime>,
270            s: UniquePtr<JsiString>,
271        ) -> UniquePtr<JsiValue>;
272        #[namespace = "jsi_rs::ffi"]
273        pub fn Value_fromObject(
274            rt: Pin<&mut Runtime>,
275            o: UniquePtr<JsiObject>,
276        ) -> UniquePtr<JsiValue>;
277        #[namespace = "jsi_rs::ffi"]
278        pub fn Value_fromSymbol(
279            rt: Pin<&mut Runtime>,
280            s: UniquePtr<JsiSymbol>,
281        ) -> UniquePtr<JsiValue>;
282        #[namespace = "jsi_rs::ffi"]
283        pub fn Value_copyFromString(rt: Pin<&mut Runtime>, s: &JsiString) -> UniquePtr<JsiValue>;
284        #[namespace = "jsi_rs::ffi"]
285        pub fn Value_copyFromObject(rt: Pin<&mut Runtime>, o: &JsiObject) -> UniquePtr<JsiValue>;
286        #[namespace = "jsi_rs::ffi"]
287        pub fn Value_copyFromSymbol(rt: Pin<&mut Runtime>, s: &JsiSymbol) -> UniquePtr<JsiValue>;
288        #[namespace = "jsi_rs::ffi"]
289        pub fn Value_fromJson(rt: Pin<&mut Runtime>, s: &str) -> UniquePtr<JsiValue>;
290        #[namespace = "jsi_rs::ffi"]
291        pub fn Value_compare(rt: Pin<&mut Runtime>, lhs: &JsiValue, rhs: &JsiValue) -> bool;
292        #[cxx_name = "isUndefined"]
293        pub fn is_undefined(self: &JsiValue) -> bool;
294        #[cxx_name = "isNull"]
295        pub fn is_null(self: &JsiValue) -> bool;
296        #[cxx_name = "isBool"]
297        pub fn is_bool(self: &JsiValue) -> bool;
298        #[cxx_name = "isNumber"]
299        pub fn is_number(self: &JsiValue) -> bool;
300        #[cxx_name = "isString"]
301        pub fn is_string(self: &JsiValue) -> bool;
302        #[cxx_name = "isSymbol"]
303        pub fn is_symbol(self: &JsiValue) -> bool;
304        #[cxx_name = "isObject"]
305        pub fn is_object(self: &JsiValue) -> bool;
306        #[cxx_name = "getBool"]
307        pub fn get_bool(self: &JsiValue) -> Result<bool>;
308        #[cxx_name = "asNumber"]
309        pub fn get_number(self: &JsiValue) -> Result<f64>;
310        #[namespace = "jsi_rs::ffi"]
311        pub fn Value_asString(
312            _self: &JsiValue,
313            rt: Pin<&mut Runtime>,
314        ) -> Result<UniquePtr<JsiString>>;
315        #[namespace = "jsi_rs::ffi"]
316        pub fn Value_asObject(
317            _self: &JsiValue,
318            rt: Pin<&mut Runtime>,
319        ) -> Result<UniquePtr<JsiObject>>;
320        #[namespace = "jsi_rs::ffi"]
321        pub fn Value_asSymbol(
322            _self: &JsiValue,
323            rt: Pin<&mut Runtime>,
324        ) -> Result<UniquePtr<JsiSymbol>>;
325        #[namespace = "jsi_rs::ffi"]
326        pub fn Value_toString(_self: &JsiValue, rt: Pin<&mut Runtime>) -> UniquePtr<JsiString>;
327        #[namespace = "jsi_rs::ffi"]
328        pub fn Value_copy(_self: &JsiValue, rt: Pin<&mut Runtime>) -> UniquePtr<JsiValue>;
329    }
330
331    impl UniquePtr<Runtime> {}
332
333
334    #[namespace = "facebook::react"]
335    unsafe extern "C++" {
336        pub type CallInvoker;
337    }
338
339    #[namespace = "jsi_rs::ffi"]
340    unsafe extern "C++" {
341        pub type c_void;
342
343        pub unsafe fn CallInvoker_invokeSync(_self: SharedPtr<CallInvoker>, closure: *mut c_void);
344        pub unsafe fn CallInvoker_invokeAsync(_self: SharedPtr<CallInvoker>, closure: *mut c_void);
345
346        pub fn create_value_vector() -> UniquePtr<CxxVector<JsiValue>>;
347        pub fn push_value_vector(vec: Pin<&mut CxxVector<JsiValue>>, item: UniquePtr<JsiValue>);
348        pub fn create_prop_name_vector() -> UniquePtr<CxxVector<PropNameID>>;
349        pub fn push_prop_name_vector(
350            vec: Pin<&mut CxxVector<PropNameID>>,
351            item: UniquePtr<PropNameID>,
352        );
353        pub fn pop_prop_name_vector(vec: Pin<&mut CxxVector<PropNameID>>) -> UniquePtr<PropNameID>;
354    }
355
356    #[namespace = "jsi_rs::ffi"]
357    extern "Rust" {
358        unsafe fn host_fn_trampoline(
359            rt: Pin<&mut Runtime>,
360            thisVal: &JsiValue,
361            args: *const JsiValue,
362            count: u32,
363            stride: usize,
364            closure: *mut c_void,
365        ) -> Result<UniquePtr<JsiValue>>;
366
367        unsafe fn call_invoker_trampoline(closure: *mut c_void) -> Result<()>;
368    }
369}
370
371pub use ffi::*;
372
373unsafe impl Sync for CallInvoker {}
374unsafe impl Send for CallInvoker {}
375
376pub type HostFunctionCallback<'rt> = Box<
377    dyn FnMut(
378            std::pin::Pin<&mut Runtime>,
379            &JsiValue,
380            &[&JsiValue],
381        ) -> Result<cxx::UniquePtr<JsiValue>, anyhow::Error>
382        + 'rt,
383>;
384
385unsafe fn host_fn_trampoline(
386    rt: std::pin::Pin<&mut Runtime>,
387    this: &JsiValue,
388    args: *const JsiValue,
389    count: u32,
390    stride: usize,
391    closure: *mut c_void,
392) -> anyhow::Result<cxx::UniquePtr<JsiValue>> {
393    let closure = closure as *mut HostFunctionCallback;
394    let mut closure = Box::from_raw(closure);
395
396    // Rust JsiValue type is just a marker type; its size according to Rust is
397    // zero so we cannot construct a slice of JsiValue; instead the size of each
398    // value is passed in from C++ and we do the pointer math ourselves
399
400    let mut args_refs = Vec::with_capacity(count as usize);
401
402    for i in 0..count {
403        let ptr = (args as usize + stride * i as usize) as *const JsiValue;
404        args_refs.push(&*ptr);
405    }
406
407    let res = closure(rt, this, &args_refs[..]);
408    Box::leak(closure);
409    res
410}
411
412pub type CallInvokerCallback<'rt> = Box<dyn FnOnce() -> anyhow::Result<()> + 'rt>;
413
414unsafe fn call_invoker_trampoline(closure: *mut c_void) -> anyhow::Result<()> {
415    let closure = Box::from_raw(closure as *mut CallInvokerCallback);
416    closure()
417}