bare_rust/
lib.rs

1use std::ffi::{c_void, CString};
2use std::ptr;
3use std::result;
4use std::slice;
5use std::string;
6
7pub use bare_rust_ffi as ffi;
8
9use ffi::*;
10
11macro_rules! assert_status {
12    ($status:expr, $message:expr) => {
13        assert!($status == 0, $message);
14    };
15}
16
17macro_rules! check_status {
18    ($env:expr, $status:expr) => {
19        if $status == JS_PENDING_EXCEPTION {
20            return Err($env.pending_exception());
21        } else {
22            assert_status!($status, "Uncaught JavaScript exception");
23        }
24    };
25}
26
27type Result<T> = result::Result<T, Value>;
28
29#[derive(Debug)]
30pub struct Env {
31    ptr: *mut js_env_t,
32}
33
34impl Env {
35    pub fn is_exception_pending(&self) -> bool {
36        let mut result = false;
37
38        unsafe {
39            js_is_exception_pending(self.ptr, &mut result);
40        }
41
42        result
43    }
44
45    pub fn pending_exception(&self) -> Value {
46        let mut ptr: *mut js_value_t = ptr::null_mut();
47
48        unsafe {
49            js_get_and_clear_last_exception(self.ptr, &mut ptr);
50        }
51
52        Value { env: self.ptr, ptr }
53    }
54}
55
56impl From<*mut js_env_t> for Env {
57    fn from(ptr: *mut js_env_t) -> Self {
58        Self { ptr }
59    }
60}
61
62#[derive(Debug)]
63pub struct Scope {
64    env: *mut js_env_t,
65    ptr: *mut js_handle_scope_t,
66}
67
68impl Scope {
69    pub fn new(env: &Env) -> Self {
70        let mut ptr: *mut js_handle_scope_t = ptr::null_mut();
71
72        unsafe {
73            js_open_handle_scope(env.ptr, &mut ptr);
74        }
75
76        Self { env: env.ptr, ptr }
77    }
78}
79
80impl Drop for Scope {
81    fn drop(&mut self) {
82        unsafe {
83            js_close_handle_scope(self.env, self.ptr);
84        }
85    }
86}
87
88#[derive(Debug)]
89pub struct EscapableScope {
90    env: *mut js_env_t,
91    ptr: *mut js_escapable_handle_scope_t,
92}
93
94impl EscapableScope {
95    pub fn new(env: &Env) -> Self {
96        let mut ptr: *mut js_escapable_handle_scope_t = ptr::null_mut();
97
98        unsafe {
99            js_open_escapable_handle_scope(env.ptr, &mut ptr);
100        }
101
102        Self { env: env.ptr, ptr }
103    }
104
105    pub fn escape<T>(self, escapee: T) -> Value
106    where
107        T: Into<Value>,
108    {
109        let mut ptr: *mut js_value_t = ptr::null_mut();
110
111        unsafe {
112            js_escape_handle(self.env, self.ptr, escapee.into().ptr, &mut ptr);
113        }
114
115        Value { env: self.env, ptr }
116    }
117}
118
119impl Drop for EscapableScope {
120    fn drop(&mut self) {
121        unsafe {
122            js_close_escapable_handle_scope(self.env, self.ptr);
123        }
124    }
125}
126
127#[derive(Debug)]
128pub struct Ref {
129    env: *mut js_env_t,
130    ptr: *mut js_ref_t,
131}
132
133impl Ref {
134    pub fn new<T>(env: &Env, value: T) -> Self
135    where
136        T: Into<Value>,
137    {
138        let mut ptr: *mut js_ref_t = ptr::null_mut();
139
140        unsafe {
141            js_create_reference(env.ptr, value.into().ptr, 1, &mut ptr);
142        }
143
144        Ref { env: env.ptr, ptr }
145    }
146
147    pub fn get<T>(&self) -> T
148    where
149        T: From<Value>,
150    {
151        let mut ptr: *mut js_value_t = ptr::null_mut();
152
153        unsafe {
154            js_get_reference_value(self.env, self.ptr, &mut ptr);
155        }
156
157        Value { env: self.env, ptr }.into()
158    }
159}
160
161impl Drop for Ref {
162    fn drop(&mut self) {
163        unsafe {
164            js_delete_reference(self.env, self.ptr);
165        }
166    }
167}
168
169impl From<Ref> for Value {
170    fn from(reference: Ref) -> Self {
171        reference.get()
172    }
173}
174
175#[derive(Debug)]
176pub struct WeakRef {
177    env: *mut js_env_t,
178    ptr: *mut js_ref_t,
179}
180
181impl WeakRef {
182    pub fn new<T>(env: &Env, value: T) -> Self
183    where
184        T: Into<Value>,
185    {
186        let mut ptr: *mut js_ref_t = ptr::null_mut();
187
188        unsafe {
189            js_create_reference(env.ptr, value.into().ptr, 0, &mut ptr);
190        }
191
192        WeakRef { env: env.ptr, ptr }
193    }
194
195    pub fn get<T>(&self) -> Option<T>
196    where
197        T: From<Value>,
198    {
199        let mut ptr: *mut js_value_t = ptr::null_mut();
200
201        unsafe {
202            js_get_reference_value(self.env, self.ptr, &mut ptr);
203        }
204
205        if ptr.is_null() {
206            None
207        } else {
208            Some(Value { env: self.env, ptr }.into())
209        }
210    }
211}
212
213impl Drop for WeakRef {
214    fn drop(&mut self) {
215        unsafe {
216            js_delete_reference(self.env, self.ptr);
217        }
218    }
219}
220
221#[derive(Debug)]
222pub struct Value {
223    env: *mut js_env_t,
224    ptr: *mut js_value_t,
225}
226
227impl From<Value> for *mut js_value_t {
228    fn from(value: Value) -> Self {
229        value.ptr
230    }
231}
232
233macro_rules! value_conversions {
234    ($type: ident) => {
235        impl From<$type> for *mut js_value_t {
236            fn from(value: $type) -> Self {
237                value.0.ptr
238            }
239        }
240
241        impl From<$type> for Value {
242            fn from(value: $type) -> Self {
243                value.0
244            }
245        }
246
247        impl From<Value> for $type {
248            fn from(value: Value) -> Self {
249                Self(value)
250            }
251        }
252    };
253}
254
255#[derive(Debug)]
256pub struct Undefined(Value);
257
258impl Undefined {
259    pub fn new(env: &Env) -> Self {
260        let mut ptr: *mut js_value_t = ptr::null_mut();
261
262        unsafe {
263            js_get_undefined(env.ptr, &mut ptr);
264        }
265
266        Self(Value { env: env.ptr, ptr })
267    }
268}
269
270value_conversions!(Undefined);
271
272#[derive(Debug)]
273pub struct Null(Value);
274
275impl Null {
276    pub fn new(env: &Env) -> Self {
277        let mut ptr: *mut js_value_t = ptr::null_mut();
278
279        unsafe {
280            js_get_null(env.ptr, &mut ptr);
281        }
282
283        Self(Value { env: env.ptr, ptr })
284    }
285}
286
287value_conversions!(Null);
288
289#[derive(Debug)]
290pub struct Boolean(Value);
291
292impl Boolean {
293    pub fn new(env: &Env, value: bool) -> Self {
294        let mut ptr: *mut js_value_t = ptr::null_mut();
295
296        unsafe {
297            js_get_boolean(env.ptr, value, &mut ptr);
298        }
299
300        Self(Value { env: env.ptr, ptr })
301    }
302}
303
304value_conversions!(Boolean);
305
306impl From<Boolean> for bool {
307    fn from(boolean: Boolean) -> Self {
308        let mut value = false;
309
310        unsafe {
311            js_get_value_bool(boolean.0.env, boolean.0.ptr, &mut value);
312        }
313
314        value
315    }
316}
317
318#[derive(Debug)]
319pub struct Number(Value);
320
321impl Number {
322    pub fn with_i32(env: &Env, value: i32) -> Self {
323        let mut ptr: *mut js_value_t = ptr::null_mut();
324
325        unsafe {
326            js_create_int32(env.ptr, value, &mut ptr);
327        }
328
329        Self(Value { env: env.ptr, ptr })
330    }
331
332    pub fn with_u32(env: &Env, value: u32) -> Self {
333        let mut ptr: *mut js_value_t = ptr::null_mut();
334
335        unsafe {
336            js_create_uint32(env.ptr, value, &mut ptr);
337        }
338
339        Self(Value { env: env.ptr, ptr })
340    }
341
342    pub fn with_i64(env: &Env, value: i64) -> Self {
343        let mut ptr: *mut js_value_t = ptr::null_mut();
344
345        unsafe {
346            js_create_int64(env.ptr, value, &mut ptr);
347        }
348
349        Self(Value { env: env.ptr, ptr })
350    }
351
352    pub fn with_f64(env: &Env, value: f64) -> Self {
353        let mut ptr: *mut js_value_t = ptr::null_mut();
354
355        unsafe {
356            js_create_double(env.ptr, value, &mut ptr);
357        }
358
359        Self(Value { env: env.ptr, ptr })
360    }
361}
362
363value_conversions!(Number);
364
365impl From<Number> for i32 {
366    fn from(number: Number) -> Self {
367        let mut value = 0;
368
369        unsafe {
370            js_get_value_int32(number.0.env, number.0.ptr, &mut value);
371        }
372
373        value
374    }
375}
376
377impl From<Number> for u32 {
378    fn from(number: Number) -> Self {
379        let mut value = 0;
380
381        unsafe {
382            js_get_value_uint32(number.0.env, number.0.ptr, &mut value);
383        }
384
385        value
386    }
387}
388
389impl From<Number> for i64 {
390    fn from(number: Number) -> Self {
391        let mut value = 0;
392
393        unsafe {
394            js_get_value_int64(number.0.env, number.0.ptr, &mut value);
395        }
396
397        value
398    }
399}
400
401impl From<Number> for f64 {
402    fn from(number: Number) -> Self {
403        let mut value = 0.0;
404
405        unsafe {
406            js_get_value_double(number.0.env, number.0.ptr, &mut value);
407        }
408
409        value
410    }
411}
412
413#[derive(Debug)]
414pub struct BigInt(Value);
415
416impl BigInt {
417    pub fn with_i64(env: &Env, value: i64) -> Self {
418        let mut ptr: *mut js_value_t = ptr::null_mut();
419
420        unsafe {
421            js_create_bigint_int64(env.ptr, value, &mut ptr);
422        }
423
424        Self(Value { env: env.ptr, ptr })
425    }
426
427    pub fn with_u64(env: &Env, value: u64) -> Self {
428        let mut ptr: *mut js_value_t = ptr::null_mut();
429
430        unsafe {
431            js_create_bigint_uint64(env.ptr, value, &mut ptr);
432        }
433
434        Self(Value { env: env.ptr, ptr })
435    }
436}
437
438value_conversions!(BigInt);
439
440impl From<BigInt> for i64 {
441    fn from(bigint: BigInt) -> Self {
442        let mut value = 0;
443
444        unsafe {
445            js_get_value_bigint_int64(bigint.0.env, bigint.0.ptr, &mut value, ptr::null_mut());
446        }
447
448        value
449    }
450}
451
452impl From<BigInt> for u64 {
453    fn from(bigint: BigInt) -> Self {
454        let mut value = 0;
455
456        unsafe {
457            js_get_value_bigint_uint64(bigint.0.env, bigint.0.ptr, &mut value, ptr::null_mut());
458        }
459
460        value
461    }
462}
463
464#[derive(Debug)]
465pub struct Name(Value);
466
467value_conversions!(Name);
468
469impl From<String> for Name {
470    fn from(string: String) -> Self {
471        Name(string.0)
472    }
473}
474
475impl From<Symbol> for Name {
476    fn from(symbol: Symbol) -> Self {
477        Name(symbol.0)
478    }
479}
480
481#[derive(Debug)]
482pub struct Symbol(Value);
483
484impl Symbol {
485    pub fn new(env: &Env, description: &str) -> Result<Self> {
486        let description = String::new(env, description)?;
487
488        let mut ptr: *mut js_value_t = ptr::null_mut();
489
490        let status = unsafe { js_create_symbol(env.ptr, description.0.ptr, &mut ptr) };
491
492        check_status!(env, status);
493
494        Ok(Self(Value { env: env.ptr, ptr }))
495    }
496}
497
498value_conversions!(Symbol);
499
500#[derive(Debug)]
501pub struct String(Value);
502
503impl String {
504    pub fn new(env: &Env, value: &str) -> Result<Self> {
505        let mut ptr: *mut js_value_t = ptr::null_mut();
506
507        let status = unsafe {
508            js_create_string_utf8(
509                env.ptr,
510                value.as_ptr().cast(),
511                value.len() as usize,
512                &mut ptr,
513            )
514        };
515
516        check_status!(env, status);
517
518        Ok(Self(Value { env: env.ptr, ptr }))
519    }
520
521    pub fn to_bytes(&self) -> Vec<u8> {
522        let mut len = 0;
523
524        unsafe {
525            js_get_value_string_utf8(self.0.env, self.0.ptr, ptr::null_mut(), 0, &mut len);
526        }
527
528        let mut result = Vec::new();
529
530        result.resize(len, 0);
531
532        unsafe {
533            js_get_value_string_utf8(self.0.env, self.0.ptr, result.as_mut_ptr(), len, &mut len);
534        }
535
536        result
537    }
538}
539
540value_conversions!(String);
541
542impl From<String> for string::String {
543    fn from(string: String) -> Self {
544        unsafe { string::String::from_utf8_unchecked(string.to_bytes()) }
545    }
546}
547
548#[derive(Debug)]
549pub struct Object(Value);
550
551impl Object {
552    pub fn new(env: &Env) -> Result<Self> {
553        let mut ptr: *mut js_value_t = ptr::null_mut();
554
555        let status = unsafe { js_create_object(env.ptr, &mut ptr) };
556
557        check_status!(env, status);
558
559        Ok(Self(Value { env: env.ptr, ptr }))
560    }
561
562    pub fn get_property<N, T>(&self, name: N) -> Result<T>
563    where
564        N: Into<Name>,
565        T: From<Value>,
566    {
567        let env = Env::from(self.0.env);
568
569        let mut ptr: *mut js_value_t = ptr::null_mut();
570
571        let status =
572            unsafe { js_get_property(self.0.env, self.0.ptr, name.into().0.ptr, &mut ptr) };
573
574        check_status!(env, status);
575
576        Ok(Value { env: env.ptr, ptr }.into())
577    }
578
579    pub fn get_named_property<T>(&self, name: &str) -> Result<T>
580    where
581        T: From<Value>,
582    {
583        let env = Env::from(self.0.env);
584
585        let key = CString::new(name).unwrap();
586
587        let mut ptr: *mut js_value_t = ptr::null_mut();
588
589        let status =
590            unsafe { js_get_named_property(self.0.env, self.0.ptr, key.as_ptr(), &mut ptr) };
591
592        check_status!(env, status);
593
594        Ok(Value { env: env.ptr, ptr }.into())
595    }
596
597    pub fn get_element<T>(&self, index: u32) -> Result<T>
598    where
599        T: From<Value>,
600    {
601        let env = Env::from(self.0.env);
602
603        let mut ptr: *mut js_value_t = ptr::null_mut();
604
605        let status = unsafe { js_get_element(self.0.env, self.0.ptr, index, &mut ptr) };
606
607        check_status!(env, status);
608
609        Ok(Value { env: env.ptr, ptr }.into())
610    }
611
612    pub fn has_property<N>(&self, name: N) -> Result<bool>
613    where
614        N: Into<Name>,
615    {
616        let env = Env::from(self.0.env);
617
618        let mut result = false;
619
620        let status =
621            unsafe { js_has_property(self.0.env, self.0.ptr, name.into().0.ptr, &mut result) };
622
623        check_status!(env, status);
624
625        Ok(result)
626    }
627
628    pub fn has_own_property<N>(&self, name: N) -> Result<bool>
629    where
630        N: Into<Name>,
631    {
632        let env = Env::from(self.0.env);
633
634        let mut result = false;
635
636        let status =
637            unsafe { js_has_own_property(self.0.env, self.0.ptr, name.into().0.ptr, &mut result) };
638
639        check_status!(env, status);
640
641        Ok(result)
642    }
643
644    pub fn has_named_property(&self, name: &str) -> Result<bool> {
645        let env = Env::from(self.0.env);
646
647        let key = CString::new(name).unwrap();
648
649        let mut result = false;
650
651        let status =
652            unsafe { js_has_named_property(self.0.env, self.0.ptr, key.as_ptr(), &mut result) };
653
654        check_status!(env, status);
655
656        Ok(result)
657    }
658
659    pub fn has_element(&self, index: u32) -> Result<bool> {
660        let env = Env::from(self.0.env);
661
662        let mut result = false;
663
664        let status = unsafe { js_has_element(self.0.env, self.0.ptr, index, &mut result) };
665
666        check_status!(env, status);
667
668        Ok(result)
669    }
670
671    pub fn set_property<N, T>(&mut self, name: N, value: T) -> Result<()>
672    where
673        N: Into<Name>,
674        T: Into<Value>,
675    {
676        let env = Env::from(self.0.env);
677
678        let status =
679            unsafe { js_set_property(self.0.env, self.0.ptr, name.into().0.ptr, value.into().ptr) };
680
681        check_status!(env, status);
682
683        Ok(())
684    }
685
686    pub fn set_named_property<T>(&mut self, name: &str, value: T) -> Result<()>
687    where
688        T: Into<Value>,
689    {
690        let env = Env::from(self.0.env);
691
692        let key = CString::new(name).unwrap();
693
694        let status = unsafe {
695            js_set_named_property(self.0.env, self.0.ptr, key.as_ptr(), value.into().ptr)
696        };
697
698        check_status!(env, status);
699
700        Ok(())
701    }
702
703    pub fn set_element<T>(&mut self, index: u32, value: T) -> Result<()>
704    where
705        T: Into<Value>,
706    {
707        let env = Env::from(self.0.env);
708
709        let status = unsafe { js_set_element(self.0.env, self.0.ptr, index, value.into().ptr) };
710
711        check_status!(env, status);
712
713        Ok(())
714    }
715
716    pub fn delete_property<N>(&self, name: N) -> Result<bool>
717    where
718        N: Into<Name>,
719    {
720        let env = Env::from(self.0.env);
721
722        let mut result = false;
723
724        let status =
725            unsafe { js_delete_property(self.0.env, self.0.ptr, name.into().0.ptr, &mut result) };
726
727        check_status!(env, status);
728
729        Ok(result)
730    }
731
732    pub fn delete_named_property(&self, name: &str) -> Result<bool> {
733        let env = Env::from(self.0.env);
734
735        let key = CString::new(name).unwrap();
736
737        let mut result = false;
738
739        let status =
740            unsafe { js_delete_named_property(self.0.env, self.0.ptr, key.as_ptr(), &mut result) };
741
742        check_status!(env, status);
743
744        Ok(result)
745    }
746
747    pub fn delete_element(&self, index: u32) -> Result<bool> {
748        let env = Env::from(self.0.env);
749
750        let mut result = false;
751
752        let status = unsafe { js_delete_element(self.0.env, self.0.ptr, index, &mut result) };
753
754        check_status!(env, status);
755
756        Ok(result)
757    }
758}
759
760value_conversions!(Object);
761
762#[derive(Debug)]
763pub struct Array(Value);
764
765impl Array {
766    pub fn new(env: &Env, len: usize) -> Result<Self> {
767        let mut ptr: *mut js_value_t = ptr::null_mut();
768
769        let status = unsafe { js_create_array_with_length(env.ptr, len, &mut ptr) };
770
771        check_status!(env, status);
772
773        Ok(Self(Value { env: env.ptr, ptr }))
774    }
775
776    pub fn len(&self) -> u32 {
777        let mut len = 0;
778
779        unsafe {
780            js_get_array_length(self.0.env, self.0.ptr, &mut len);
781        }
782
783        len
784    }
785
786    pub fn get<T>(&self, index: u32) -> Result<T>
787    where
788        T: From<Value>,
789    {
790        let env = Env::from(self.0.env);
791
792        let mut ptr: *mut js_value_t = ptr::null_mut();
793
794        let status = unsafe { js_get_element(self.0.env, self.0.ptr, index, &mut ptr) };
795
796        check_status!(env, status);
797
798        Ok(Value { env: env.ptr, ptr }.into())
799    }
800
801    pub fn set<T>(&mut self, index: u32, value: T) -> Result<()>
802    where
803        T: Into<Value>,
804    {
805        let env = Env::from(self.0.env);
806
807        let status = unsafe { js_set_element(self.0.env, self.0.ptr, index, value.into().ptr) };
808
809        check_status!(env, status);
810
811        Ok(())
812    }
813}
814
815value_conversions!(Array);
816
817#[derive(Debug)]
818pub struct Callback {
819    env: *mut js_env_t,
820    args: Vec<*mut js_value_t>,
821    receiver: *mut js_value_t,
822}
823
824impl Callback {
825    pub fn arg<T>(&self, i: usize) -> Option<T>
826    where
827        T: From<Value>,
828    {
829        if i < self.args.len() {
830            Some(self.arg_unchecked(i))
831        } else {
832            None
833        }
834    }
835
836    pub fn arg_unchecked<T>(&self, i: usize) -> T
837    where
838        T: From<Value>,
839    {
840        Value {
841            env: self.env,
842            ptr: self.args[i],
843        }
844        .into()
845    }
846
847    pub fn receiver<T>(&self) -> T
848    where
849        T: From<Value>,
850    {
851        Value {
852            env: self.env,
853            ptr: self.receiver,
854        }
855        .into()
856    }
857}
858
859#[derive(Debug)]
860pub struct Function(Value);
861
862impl Function {
863    pub fn new<F>(env: &Env, function: F) -> Result<Self>
864    where
865        F: FnMut(&Env, &Callback) -> Result<Value>,
866    {
867        let mut function = function;
868
869        let closure: Box<dyn FnMut(&Env, &Callback) -> *mut js_value_t> =
870            Box::new(move |env, info| match function(env, info) {
871                Ok(result) => result.into(),
872                Err(error) => {
873                    unsafe {
874                        js_throw(env.ptr, error.into());
875                    }
876
877                    ptr::null_mut()
878                }
879            });
880
881        let data = Box::into_raw(Box::new(closure)) as *mut _;
882
883        let mut ptr: *mut js_value_t = ptr::null_mut();
884
885        let status = unsafe {
886            js_create_function(
887                env.ptr,
888                ptr::null_mut(),
889                0,
890                Some(Function::call),
891                data,
892                &mut ptr,
893            )
894        };
895
896        check_status!(env, status);
897
898        unsafe {
899            js_add_finalizer(
900                env.ptr,
901                ptr,
902                data,
903                Some(Function::drop),
904                ptr::null_mut(),
905                ptr::null_mut(),
906            );
907        }
908
909        Ok(Self(Value { env: env.ptr, ptr }))
910    }
911
912    extern "C" fn call(env: *mut js_env_t, info: *mut js_callback_info_t) -> *mut js_value_t {
913        let mut len: usize = 0;
914        let mut receiver: *mut js_value_t = ptr::null_mut();
915        let mut data: *mut c_void = ptr::null_mut();
916
917        unsafe {
918            js_get_callback_info(
919                env,
920                info,
921                &mut len,
922                ptr::null_mut(),
923                &mut receiver,
924                &mut data,
925            );
926        }
927
928        let mut args = Vec::new();
929
930        if len > 0 {
931            args.resize(len, ptr::null_mut());
932
933            unsafe {
934                js_get_callback_info(
935                    env,
936                    info,
937                    &mut len,
938                    args.as_mut_ptr(),
939                    ptr::null_mut(),
940                    ptr::null_mut(),
941                );
942            }
943        }
944
945        let closure =
946            unsafe { &mut *(data as *mut Box<dyn FnMut(&Env, &Callback) -> *mut js_value_t>) };
947
948        closure(
949            &Env::from(env),
950            &Callback {
951                env,
952                args,
953                receiver,
954            },
955        )
956    }
957
958    extern "C" fn drop(_: *mut js_env_t, data: *mut c_void, _: *mut c_void) -> () {
959        unsafe {
960            drop(Box::from_raw(data));
961        }
962    }
963}
964
965value_conversions!(Function);
966
967#[derive(Debug)]
968pub struct External(Value);
969
970impl External {
971    pub fn new<T>(env: &Env, value: T) -> Result<Self> {
972        let data = Box::into_raw(Box::new(value)) as *mut _;
973
974        let mut ptr: *mut js_value_t = ptr::null_mut();
975
976        let status = unsafe {
977            js_create_external(
978                env.ptr,
979                data,
980                Some(External::drop),
981                ptr::null_mut(),
982                &mut ptr,
983            )
984        };
985
986        check_status!(env, status);
987
988        Ok(Self(Value { env: env.ptr, ptr }))
989    }
990
991    extern "C" fn drop(_: *mut js_env_t, data: *mut c_void, _: *mut c_void) -> () {
992        unsafe {
993            drop(Box::from_raw(data));
994        }
995    }
996}
997
998value_conversions!(External);
999
1000impl<T> AsRef<T> for External {
1001    fn as_ref(&self) -> &T {
1002        let mut ptr: *mut c_void = ptr::null_mut();
1003
1004        unsafe {
1005            js_get_value_external(self.0.env, self.0.ptr, &mut ptr);
1006        }
1007
1008        unsafe { &*(ptr as *const T) }
1009    }
1010}
1011
1012impl<T> AsMut<T> for External {
1013    fn as_mut(&mut self) -> &mut T {
1014        let mut ptr: *mut c_void = ptr::null_mut();
1015
1016        unsafe {
1017            js_get_value_external(self.0.env, self.0.ptr, &mut ptr);
1018        }
1019
1020        unsafe { &mut *(ptr as *mut T) }
1021    }
1022}
1023
1024#[derive(Debug)]
1025pub struct ArrayBuffer(Value);
1026
1027impl ArrayBuffer {
1028    pub fn new(env: &Env, len: usize) -> Result<Self> {
1029        let mut ptr: *mut js_value_t = ptr::null_mut();
1030
1031        let status = unsafe { js_create_arraybuffer(env.ptr, len, ptr::null_mut(), &mut ptr) };
1032
1033        check_status!(env, status);
1034
1035        Ok(Self(Value { env: env.ptr, ptr }))
1036    }
1037
1038    pub fn as_slice(&self) -> &[u8] {
1039        let mut len: usize = 0;
1040        let mut data: *mut c_void = ptr::null_mut();
1041
1042        unsafe {
1043            js_get_arraybuffer_info(self.0.env, self.0.ptr, &mut data, &mut len);
1044        }
1045
1046        unsafe { slice::from_raw_parts(data as *const u8, len) }
1047    }
1048
1049    pub fn as_mut_slice(&mut self) -> &mut [u8] {
1050        let mut len: usize = 0;
1051        let mut data: *mut c_void = ptr::null_mut();
1052
1053        unsafe {
1054            js_get_arraybuffer_info(self.0.env, self.0.ptr, &mut data, &mut len);
1055        }
1056
1057        unsafe { slice::from_raw_parts_mut(data as *mut u8, len) }
1058    }
1059
1060    pub fn to_vec(&self) -> Vec<u8> {
1061        self.as_slice().to_vec()
1062    }
1063
1064    pub fn copy_from_slice(&mut self, slice: &[u8]) {
1065        self.as_mut_slice().copy_from_slice(slice)
1066    }
1067
1068    pub fn clone_from_slice(&mut self, slice: &[u8]) {
1069        self.as_mut_slice().clone_from_slice(slice)
1070    }
1071}
1072
1073value_conversions!(ArrayBuffer);
1074
1075pub trait TypedArray<T> {
1076    fn as_slice(&self) -> &[T];
1077
1078    fn as_mut_slice(&mut self) -> &mut [T];
1079
1080    fn to_vec(&self) -> Vec<T>
1081    where
1082        T: Clone,
1083    {
1084        self.as_slice().to_vec()
1085    }
1086
1087    fn copy_from_slice(&mut self, slice: &[T])
1088    where
1089        T: Copy,
1090    {
1091        self.as_mut_slice().copy_from_slice(slice)
1092    }
1093
1094    fn clone_from_slice(&mut self, slice: &[T])
1095    where
1096        T: Clone,
1097    {
1098        self.as_mut_slice().clone_from_slice(slice)
1099    }
1100}
1101
1102macro_rules! define_typedarray {
1103    ($name:ident, $type:ident, $kind:ident) => {
1104        #[derive(Debug)]
1105        pub struct $name(Value);
1106
1107        impl $name {
1108            pub fn new(env: &Env, len: usize) -> Result<Self> {
1109                let arraybuffer = ArrayBuffer::new(env, len * size_of::<$type>())?;
1110
1111                let mut ptr: *mut js_value_t = ptr::null_mut();
1112
1113                let status = unsafe {
1114                    js_create_typedarray(
1115                        env.ptr,
1116                        js_typedarray_type_t::$kind,
1117                        len,
1118                        arraybuffer.0.ptr,
1119                        0,
1120                        &mut ptr,
1121                    )
1122                };
1123
1124                check_status!(env, status);
1125
1126                Ok(Self(Value { env: env.ptr, ptr }))
1127            }
1128
1129            pub fn with_slice(env: &Env, slice: &[$type]) -> Result<Self> {
1130                let mut typedarray = $name::new(env, slice.len())?;
1131
1132                typedarray.copy_from_slice(slice);
1133
1134                Ok(typedarray)
1135            }
1136        }
1137
1138        impl TypedArray<$type> for $name {
1139            fn as_slice(&self) -> &[$type] {
1140                let mut len: usize = 0;
1141                let mut data: *mut c_void = ptr::null_mut();
1142
1143                unsafe {
1144                    js_get_typedarray_info(
1145                        self.0.env,
1146                        self.0.ptr,
1147                        ptr::null_mut(),
1148                        &mut data,
1149                        &mut len,
1150                        ptr::null_mut(),
1151                        ptr::null_mut(),
1152                    );
1153                }
1154
1155                unsafe { slice::from_raw_parts(data as *const $type, len) }
1156            }
1157
1158            fn as_mut_slice(&mut self) -> &mut [$type] {
1159                let mut len: usize = 0;
1160                let mut data: *mut c_void = ptr::null_mut();
1161
1162                unsafe {
1163                    js_get_typedarray_info(
1164                        self.0.env,
1165                        self.0.ptr,
1166                        ptr::null_mut(),
1167                        &mut data,
1168                        &mut len,
1169                        ptr::null_mut(),
1170                        ptr::null_mut(),
1171                    );
1172                }
1173
1174                unsafe { slice::from_raw_parts_mut(data as *mut $type, len) }
1175            }
1176        }
1177
1178        value_conversions!($name);
1179    };
1180}
1181
1182define_typedarray!(Int8Array, i8, js_int8array);
1183define_typedarray!(Uint8Array, u8, js_uint8array);
1184define_typedarray!(Uint8ClampedArray, u8, js_uint8clampedarray);
1185define_typedarray!(Int16Array, i16, js_int16array);
1186define_typedarray!(Uint16Array, u16, js_uint16array);
1187define_typedarray!(Int32Array, i32, js_int32array);
1188define_typedarray!(Uint32Array, u32, js_uint32array);
1189define_typedarray!(Float32Array, f32, js_float32array);
1190define_typedarray!(Float64Array, f64, js_float64array);
1191define_typedarray!(BigInt64Array, i32, js_bigint64array);
1192define_typedarray!(BigUint64Array, u32, js_biguint64array);
1193
1194macro_rules! define_error {
1195    ($name:ident, $create:ident) => {
1196        #[derive(Debug)]
1197        pub struct $name(Value);
1198
1199        impl $name {
1200            pub fn new(env: &Env, message: &str) -> Self {
1201                let message = String::new(env, message).unwrap();
1202
1203                let mut ptr: *mut js_value_t = std::ptr::null_mut();
1204
1205                unsafe {
1206                    $create(env.ptr, std::ptr::null_mut(), message.0.ptr, &mut ptr);
1207                }
1208
1209                Self(Value { env: env.ptr, ptr })
1210            }
1211        }
1212
1213        value_conversions!($name);
1214    };
1215}
1216
1217define_error!(Error, js_create_error);
1218define_error!(TypeError, js_create_type_error);
1219define_error!(RangeError, js_create_range_error);
1220define_error!(SyntaxError, js_create_syntax_error);
1221define_error!(ReferenceError, js_create_reference_error);
1222
1223#[macro_export]
1224macro_rules! bare_exports {
1225    ($name:ident, $exports:expr) => {
1226        #[unsafe(no_mangle)]
1227        pub unsafe extern "C" fn $name(
1228            env: *mut $crate::ffi::js_env_t,
1229            _: *mut $crate::ffi::js_value_t,
1230        ) -> *mut $crate::ffi::js_value_t {
1231            let result: Result<$crate::Value, $crate::Value> = $exports(crate::Env::from(env));
1232
1233            match result {
1234                Ok(result) => result.into(),
1235                Err(error) => {
1236                    unsafe {
1237                        $crate::ffi::js_throw(env, error.into());
1238                    }
1239
1240                    std::ptr::null_mut()
1241                }
1242            }
1243        }
1244    };
1245}
1246
1247#[macro_export]
1248macro_rules! bare_module {
1249    ($exports:expr) => {
1250        $crate::bare_exports!(bare_register_module_v0, $exports);
1251    };
1252}