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