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 ArrayBuffer(Value);
969
970impl ArrayBuffer {
971 pub fn new(env: &Env, len: usize) -> Result<Self> {
972 let mut ptr: *mut js_value_t = ptr::null_mut();
973
974 let status = unsafe { js_create_arraybuffer(env.ptr, len, ptr::null_mut(), &mut ptr) };
975
976 check_status!(env, status);
977
978 Ok(Self(Value { env: env.ptr, ptr }))
979 }
980
981 pub fn as_slice(&self) -> &[u8] {
982 let mut len: usize = 0;
983 let mut data: *mut c_void = ptr::null_mut();
984
985 unsafe {
986 js_get_arraybuffer_info(self.0.env, self.0.ptr, &mut data, &mut len);
987 }
988
989 unsafe { slice::from_raw_parts(data as *const u8, len) }
990 }
991
992 pub fn as_mut_slice(&mut self) -> &mut [u8] {
993 let mut len: usize = 0;
994 let mut data: *mut c_void = ptr::null_mut();
995
996 unsafe {
997 js_get_arraybuffer_info(self.0.env, self.0.ptr, &mut data, &mut len);
998 }
999
1000 unsafe { slice::from_raw_parts_mut(data as *mut u8, len) }
1001 }
1002
1003 pub fn to_vec(&self) -> Vec<u8> {
1004 self.as_slice().to_vec()
1005 }
1006
1007 pub fn copy_from_slice(&mut self, slice: &[u8]) {
1008 self.as_mut_slice().copy_from_slice(slice)
1009 }
1010
1011 pub fn clone_from_slice(&mut self, slice: &[u8]) {
1012 self.as_mut_slice().clone_from_slice(slice)
1013 }
1014}
1015
1016value_conversions!(ArrayBuffer);
1017
1018pub trait TypedArray<T> {
1019 fn as_slice(&self) -> &[T];
1020
1021 fn as_mut_slice(&mut self) -> &mut [T];
1022
1023 fn to_vec(&self) -> Vec<T>
1024 where
1025 T: Clone,
1026 {
1027 self.as_slice().to_vec()
1028 }
1029
1030 fn copy_from_slice(&mut self, slice: &[T])
1031 where
1032 T: Copy,
1033 {
1034 self.as_mut_slice().copy_from_slice(slice)
1035 }
1036
1037 fn clone_from_slice(&mut self, slice: &[T])
1038 where
1039 T: Clone,
1040 {
1041 self.as_mut_slice().clone_from_slice(slice)
1042 }
1043}
1044
1045macro_rules! define_typedarray {
1046 ($name:ident, $type:ident, $kind:ident) => {
1047 #[derive(Debug)]
1048 pub struct $name(Value);
1049
1050 impl $name {
1051 pub fn new(env: &Env, len: usize) -> Result<Self> {
1052 let arraybuffer = ArrayBuffer::new(env, len * size_of::<$type>())?;
1053
1054 let mut ptr: *mut js_value_t = ptr::null_mut();
1055
1056 let status = unsafe {
1057 js_create_typedarray(
1058 env.ptr,
1059 js_typedarray_type_t::$kind,
1060 len,
1061 arraybuffer.0.ptr,
1062 0,
1063 &mut ptr,
1064 )
1065 };
1066
1067 check_status!(env, status);
1068
1069 Ok(Self(Value { env: env.ptr, ptr }))
1070 }
1071
1072 pub fn with_slice(env: &Env, slice: &[$type]) -> Result<Self> {
1073 let mut typedarray = $name::new(env, slice.len())?;
1074
1075 typedarray.copy_from_slice(slice);
1076
1077 Ok(typedarray)
1078 }
1079 }
1080
1081 impl TypedArray<$type> for $name {
1082 fn as_slice(&self) -> &[$type] {
1083 let mut len: usize = 0;
1084 let mut data: *mut c_void = ptr::null_mut();
1085
1086 unsafe {
1087 js_get_typedarray_info(
1088 self.0.env,
1089 self.0.ptr,
1090 ptr::null_mut(),
1091 &mut data,
1092 &mut len,
1093 ptr::null_mut(),
1094 ptr::null_mut(),
1095 );
1096 }
1097
1098 unsafe { slice::from_raw_parts(data as *const $type, len) }
1099 }
1100
1101 fn as_mut_slice(&mut self) -> &mut [$type] {
1102 let mut len: usize = 0;
1103 let mut data: *mut c_void = ptr::null_mut();
1104
1105 unsafe {
1106 js_get_typedarray_info(
1107 self.0.env,
1108 self.0.ptr,
1109 ptr::null_mut(),
1110 &mut data,
1111 &mut len,
1112 ptr::null_mut(),
1113 ptr::null_mut(),
1114 );
1115 }
1116
1117 unsafe { slice::from_raw_parts_mut(data as *mut $type, len) }
1118 }
1119 }
1120
1121 value_conversions!($name);
1122 };
1123}
1124
1125define_typedarray!(Int8Array, i8, js_int8array);
1126define_typedarray!(Uint8Array, u8, js_uint8array);
1127define_typedarray!(Uint8ClampedArray, u8, js_uint8clampedarray);
1128define_typedarray!(Int16Array, i16, js_int16array);
1129define_typedarray!(Uint16Array, u16, js_uint16array);
1130define_typedarray!(Int32Array, i32, js_int32array);
1131define_typedarray!(Uint32Array, u32, js_uint32array);
1132define_typedarray!(Float32Array, f32, js_float32array);
1133define_typedarray!(Float64Array, f64, js_float64array);
1134define_typedarray!(BigInt64Array, i32, js_bigint64array);
1135define_typedarray!(BigUint64Array, u32, js_biguint64array);
1136
1137macro_rules! define_error {
1138 ($name:ident, $create:ident) => {
1139 #[derive(Debug)]
1140 pub struct $name(Value);
1141
1142 impl $name {
1143 pub fn new(env: &Env, message: &str) -> Self {
1144 let message = String::new(env, message).unwrap();
1145
1146 let mut ptr: *mut js_value_t = std::ptr::null_mut();
1147
1148 unsafe {
1149 $create(env.ptr, std::ptr::null_mut(), message.0.ptr, &mut ptr);
1150 }
1151
1152 Self(Value { env: env.ptr, ptr })
1153 }
1154 }
1155
1156 value_conversions!($name);
1157 };
1158}
1159
1160define_error!(Error, js_create_error);
1161define_error!(TypeError, js_create_type_error);
1162define_error!(RangeError, js_create_range_error);
1163define_error!(SyntaxError, js_create_syntax_error);
1164define_error!(ReferenceError, js_create_reference_error);
1165
1166#[macro_export]
1167macro_rules! bare_exports {
1168 ($name:ident, $exports:expr) => {
1169 #[unsafe(no_mangle)]
1170 pub unsafe extern "C" fn $name(
1171 env: *mut $crate::ffi::js_env_t,
1172 _: *mut $crate::ffi::js_value_t,
1173 ) -> *mut $crate::ffi::js_value_t {
1174 let result: Result<$crate::Value, $crate::Value> = $exports(crate::Env::from(env));
1175
1176 match result {
1177 Ok(result) => result.into(),
1178 Err(error) => {
1179 unsafe {
1180 $crate::ffi::js_throw(env, error.into());
1181 }
1182
1183 std::ptr::null_mut()
1184 }
1185 }
1186 }
1187 };
1188}
1189
1190#[macro_export]
1191macro_rules! bare_module {
1192 ($exports:expr) => {
1193 $crate::bare_exports!(bare_register_module_v0, $exports);
1194 };
1195}