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