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}