1#![deny(missing_docs)]
30
31use crate::error::throw_type_error;
32use crate::jsapi::Heap;
33use crate::jsapi::JS;
34use crate::jsapi::{JSContext, JSObject, JSString};
35use crate::jsapi::{JS_DeprecatedStringHasLatin1Chars, JSPROP_ENUMERATE};
36use crate::jsval::{BooleanValue, DoubleValue, Int32Value, NullValue, UInt32Value, UndefinedValue};
37use crate::jsval::{JSVal, ObjectOrNullValue, ObjectValue, StringValue, SymbolValue};
38use crate::rooted;
39use crate::rust::for_of;
40use crate::rust::maybe_wrap_value;
41use crate::rust::wrappers2::{
42 AssertSameCompartment, JS_DefineElement, JS_GetLatin1StringCharsAndLength,
43 JS_GetTwoByteStringCharsAndLength, JS_NewStringCopyUTF8N, NewArrayObject1,
44};
45use crate::rust::ForOfIterationFailure;
46use crate::rust::{maybe_wrap_object_or_null_value, maybe_wrap_object_value, ToString};
47use crate::rust::{HandleValue, MutableHandleValue};
48use crate::rust::{ToBoolean, ToInt32, ToInt64, ToNumber, ToUint16, ToUint32, ToUint64};
49use libc;
50use log::debug;
51use num_traits::PrimInt;
52use std::borrow::Cow;
53use std::ffi::CStr;
54use std::ops::ControlFlow;
55use std::ptr::NonNull;
56use std::rc::Rc;
57use std::{ptr, slice};
58
59trait As<O>: Copy {
60 fn cast(self) -> O;
61}
62
63macro_rules! impl_as {
64 ($I:ty, $O:ty) => {
65 impl As<$O> for $I {
66 fn cast(self) -> $O {
67 self as $O
68 }
69 }
70 };
71}
72
73impl_as!(f64, u8);
74impl_as!(f64, u16);
75impl_as!(f64, u32);
76impl_as!(f64, u64);
77impl_as!(f64, i8);
78impl_as!(f64, i16);
79impl_as!(f64, i32);
80impl_as!(f64, i64);
81
82impl_as!(u8, f64);
83impl_as!(u16, f64);
84impl_as!(u32, f64);
85impl_as!(u64, f64);
86impl_as!(i8, f64);
87impl_as!(i16, f64);
88impl_as!(i32, f64);
89impl_as!(i64, f64);
90
91impl_as!(i32, i8);
92impl_as!(i32, u8);
93impl_as!(i32, i16);
94impl_as!(u16, u16);
95impl_as!(i32, i32);
96impl_as!(u32, u32);
97impl_as!(i64, i64);
98impl_as!(u64, u64);
99
100pub trait Number {
102 const ZERO: Self;
104 const MIN: Self;
106 const MAX: Self;
108}
109
110macro_rules! impl_num {
111 ($N:ty, $zero:expr, $min:expr, $max:expr) => {
112 impl Number for $N {
113 const ZERO: $N = $zero;
114 const MIN: $N = $min;
115 const MAX: $N = $max;
116 }
117 };
118}
119
120impl_num!(u8, 0, u8::MIN, u8::MAX);
122impl_num!(u16, 0, u16::MIN, u16::MAX);
123impl_num!(u32, 0, u32::MIN, u32::MAX);
124impl_num!(u64, 0, 0, (1 << 53) - 1);
125
126impl_num!(i8, 0, i8::MIN, i8::MAX);
127impl_num!(i16, 0, i16::MIN, i16::MAX);
128impl_num!(i32, 0, i32::MIN, i32::MAX);
129impl_num!(i64, 0, -(1 << 53) + 1, (1 << 53) - 1);
130
131impl_num!(f32, 0.0, f32::MIN, f32::MAX);
132impl_num!(f64, 0.0, f64::MIN, f64::MAX);
133
134pub trait ToJSValConvertible {
136 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, rval: MutableHandleValue);
138}
139
140#[derive(PartialEq, Eq, Clone, Debug)]
142pub enum ConversionResult<T> {
143 Success(T),
145 Failure(Cow<'static, CStr>),
147}
148
149impl<T> ConversionResult<T> {
150 pub fn get_success_value(&self) -> Option<&T> {
152 match *self {
153 ConversionResult::Success(ref v) => Some(v),
154 _ => None,
155 }
156 }
157}
158
159pub trait FromJSValConvertible: Sized {
161 type Config;
163
164 fn safe_from_jsval(
170 cx: &mut crate::context::JSContext,
171 val: HandleValue,
172 option: Self::Config,
173 ) -> Result<ConversionResult<Self>, ()>;
174}
175
176pub trait FromJSValConvertibleRc: Sized {
178 fn safe_from_jsval(
182 cx: &mut crate::context::JSContext,
183 val: HandleValue,
184 ) -> Result<ConversionResult<Rc<Self>>, ()>;
185}
186
187impl<T: FromJSValConvertibleRc> FromJSValConvertible for Rc<T> {
188 type Config = ();
189
190 fn safe_from_jsval(
191 cx: &mut crate::context::JSContext,
192 val: HandleValue,
193 _option: (),
194 ) -> Result<ConversionResult<Rc<T>>, ()> {
195 <T as FromJSValConvertibleRc>::safe_from_jsval(cx, val)
196 }
197}
198
199#[derive(PartialEq, Eq, Clone)]
201pub enum ConversionBehavior {
202 Default,
204 EnforceRange,
206 Clamp,
208}
209
210fn enforce_range<D>(cx: &mut crate::context::JSContext, d: f64) -> Result<ConversionResult<D>, ()>
214where
215 D: Number + As<f64>,
216 f64: As<D>,
217{
218 if d.is_infinite() {
219 unsafe {
220 throw_type_error(
221 cx.raw_cx(),
222 c"value out of range in an EnforceRange argument",
223 )
224 };
225 return Err(());
226 }
227
228 let rounded = d.signum() * d.abs().floor();
229 if D::MIN.cast() <= rounded && rounded <= D::MAX.cast() {
230 Ok(ConversionResult::Success(rounded.cast()))
231 } else {
232 unsafe {
233 throw_type_error(
234 cx.raw_cx(),
235 c"value out of range in an EnforceRange argument",
236 )
237 };
238 Err(())
239 }
240}
241
242fn clamp_to<D>(d: f64) -> D
252where
253 D: Number + PrimInt + As<f64>,
254 f64: As<D>,
255{
256 if d.is_nan() {
258 return D::ZERO;
259 }
260
261 if d >= D::MAX.cast() {
262 return D::MAX;
263 }
264 if d <= D::MIN.cast() {
265 return D::MIN;
266 }
267
268 debug_assert!(d.is_finite());
269
270 let to_truncate = if d < 0.0 { d - 0.5 } else { d + 0.5 };
276
277 let mut truncated: D = to_truncate.cast();
278
279 if truncated.cast() == to_truncate {
280 truncated = truncated & !D::one();
286 }
287
288 truncated
289}
290
291impl ToJSValConvertible for () {
293 #[inline]
294 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
295 rval.set(UndefinedValue());
296 }
297}
298
299impl FromJSValConvertible for JSVal {
300 type Config = ();
301
302 fn safe_from_jsval(
303 _cx: &mut crate::context::JSContext,
304 value: HandleValue,
305 _option: (),
306 ) -> Result<ConversionResult<JSVal>, ()> {
307 Ok(ConversionResult::Success(value.get()))
308 }
309}
310
311impl ToJSValConvertible for JSVal {
312 #[inline]
313 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
314 rval.set(*self);
315 maybe_wrap_value(cx, rval);
316 }
317}
318
319impl<'a> ToJSValConvertible for HandleValue<'a> {
320 #[inline]
321 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
322 rval.set(self.get());
323 maybe_wrap_value(cx, rval);
324 }
325}
326
327impl ToJSValConvertible for Heap<JSVal> {
328 #[inline]
329 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
330 rval.set(self.get());
331 maybe_wrap_value(cx, rval);
332 }
333}
334
335#[inline]
336fn convert_int_from_jsval<T, M>(
337 cx: &mut crate::context::JSContext,
338 value: HandleValue,
339 option: ConversionBehavior,
340 convert_fn: unsafe fn(*mut JSContext, HandleValue) -> Result<M, ()>,
341) -> Result<ConversionResult<T>, ()>
342where
343 T: Number + As<f64> + PrimInt,
344 M: Number + As<T>,
345 f64: As<T>,
346{
347 match option {
348 ConversionBehavior::Default => Ok(ConversionResult::Success(unsafe {
349 convert_fn(cx.raw_cx(), value)?.cast()
350 })),
351 ConversionBehavior::EnforceRange => {
352 let number = unsafe { ToNumber(cx.raw_cx(), value) }?;
353 enforce_range(cx, number)
354 }
355 ConversionBehavior::Clamp => Ok(ConversionResult::Success(clamp_to(unsafe {
356 ToNumber(cx.raw_cx(), value)
357 }?))),
358 }
359}
360
361impl ToJSValConvertible for bool {
363 #[inline]
364 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
365 rval.set(BooleanValue(*self));
366 }
367}
368
369impl FromJSValConvertible for bool {
371 type Config = ();
372
373 fn safe_from_jsval(
374 _cx: &mut crate::context::JSContext,
375 val: HandleValue,
376 _option: (),
377 ) -> Result<ConversionResult<bool>, ()> {
378 unsafe { Ok(ToBoolean(val)).map(ConversionResult::Success) }
379 }
380}
381
382impl ToJSValConvertible for i8 {
384 #[inline]
385 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
386 rval.set(Int32Value(*self as i32));
387 }
388}
389
390impl FromJSValConvertible for i8 {
392 type Config = ConversionBehavior;
393
394 fn safe_from_jsval(
395 cx: &mut crate::context::JSContext,
396 val: HandleValue,
397 option: ConversionBehavior,
398 ) -> Result<ConversionResult<i8>, ()> {
399 convert_int_from_jsval(cx, val, option, ToInt32)
400 }
401}
402
403impl ToJSValConvertible for u8 {
405 #[inline]
406 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
407 rval.set(Int32Value(*self as i32));
408 }
409}
410
411impl FromJSValConvertible for u8 {
413 type Config = ConversionBehavior;
414
415 fn safe_from_jsval(
416 cx: &mut crate::context::JSContext,
417 val: HandleValue,
418 option: ConversionBehavior,
419 ) -> Result<ConversionResult<u8>, ()> {
420 convert_int_from_jsval(cx, val, option, ToInt32)
421 }
422}
423
424impl ToJSValConvertible for i16 {
426 #[inline]
427 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
428 rval.set(Int32Value(*self as i32));
429 }
430}
431
432impl FromJSValConvertible for i16 {
434 type Config = ConversionBehavior;
435
436 fn safe_from_jsval(
437 cx: &mut crate::context::JSContext,
438 val: HandleValue,
439 option: ConversionBehavior,
440 ) -> Result<ConversionResult<i16>, ()> {
441 convert_int_from_jsval(cx, val, option, ToInt32)
442 }
443}
444
445impl ToJSValConvertible for u16 {
447 #[inline]
448 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
449 rval.set(Int32Value(*self as i32));
450 }
451}
452
453impl FromJSValConvertible for u16 {
455 type Config = ConversionBehavior;
456
457 fn safe_from_jsval(
458 cx: &mut crate::context::JSContext,
459 val: HandleValue,
460 option: ConversionBehavior,
461 ) -> Result<ConversionResult<u16>, ()> {
462 convert_int_from_jsval(cx, val, option, ToUint16)
463 }
464}
465
466impl ToJSValConvertible for i32 {
468 #[inline]
469 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
470 rval.set(Int32Value(*self));
471 }
472}
473
474impl FromJSValConvertible for i32 {
476 type Config = ConversionBehavior;
477
478 fn safe_from_jsval(
479 cx: &mut crate::context::JSContext,
480 val: HandleValue,
481 option: ConversionBehavior,
482 ) -> Result<ConversionResult<i32>, ()> {
483 convert_int_from_jsval(cx, val, option, ToInt32)
484 }
485}
486
487impl ToJSValConvertible for u32 {
489 #[inline]
490 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
491 rval.set(UInt32Value(*self));
492 }
493}
494
495impl FromJSValConvertible for u32 {
497 type Config = ConversionBehavior;
498
499 fn safe_from_jsval(
500 cx: &mut crate::context::JSContext,
501 val: HandleValue,
502 option: ConversionBehavior,
503 ) -> Result<ConversionResult<u32>, ()> {
504 convert_int_from_jsval(cx, val, option, ToUint32)
505 }
506}
507
508impl ToJSValConvertible for i64 {
510 #[inline]
511 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
512 rval.set(DoubleValue(*self as f64));
513 }
514}
515
516impl FromJSValConvertible for i64 {
518 type Config = ConversionBehavior;
519
520 fn safe_from_jsval(
521 cx: &mut crate::context::JSContext,
522 val: HandleValue,
523 option: ConversionBehavior,
524 ) -> Result<ConversionResult<i64>, ()> {
525 convert_int_from_jsval(cx, val, option, ToInt64)
526 }
527}
528
529impl ToJSValConvertible for u64 {
531 #[inline]
532 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
533 rval.set(DoubleValue(*self as f64));
534 }
535}
536
537impl FromJSValConvertible for u64 {
539 type Config = ConversionBehavior;
540
541 fn safe_from_jsval(
542 cx: &mut crate::context::JSContext,
543 val: HandleValue,
544 option: ConversionBehavior,
545 ) -> Result<ConversionResult<u64>, ()> {
546 convert_int_from_jsval(cx, val, option, ToUint64)
547 }
548}
549
550impl ToJSValConvertible for f32 {
552 #[inline]
553 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
554 rval.set(DoubleValue(*self as f64));
555 }
556}
557
558impl FromJSValConvertible for f32 {
560 type Config = ();
561
562 fn safe_from_jsval(
563 cx: &mut crate::context::JSContext,
564 val: HandleValue,
565 _option: (),
566 ) -> Result<ConversionResult<f32>, ()> {
567 let result = unsafe { ToNumber(cx.raw_cx(), val) };
568 result.map(|f| f as f32).map(ConversionResult::Success)
569 }
570}
571
572impl ToJSValConvertible for f64 {
574 #[inline]
575 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
576 rval.set(DoubleValue(*self))
577 }
578}
579
580impl FromJSValConvertible for f64 {
582 type Config = ();
583
584 fn safe_from_jsval(
585 cx: &mut crate::context::JSContext,
586 val: HandleValue,
587 _option: (),
588 ) -> Result<ConversionResult<f64>, ()> {
589 unsafe { ToNumber(cx.raw_cx(), val).map(ConversionResult::Success) }
590 }
591}
592
593pub unsafe fn latin1_to_string(cx: &crate::context::JSContext, s: NonNull<JSString>) -> String {
599 assert!(unsafe { JS_DeprecatedStringHasLatin1Chars(s.as_ptr()) });
600
601 let mut length = 0;
602 let chars = unsafe {
603 let chars = JS_GetLatin1StringCharsAndLength(cx, s.as_ptr(), &mut length);
604 assert!(!chars.is_null());
605
606 slice::from_raw_parts(chars, length as usize)
607 };
608 let mut v = vec![0; chars.len() * 2];
612 let real_size = encoding_rs::mem::convert_latin1_to_utf8(chars, v.as_mut_slice());
613
614 v.truncate(real_size);
615
616 unsafe { String::from_utf8_unchecked(v) }
619}
620
621pub unsafe fn jsstr_to_string(cx: &crate::context::JSContext, jsstr: NonNull<JSString>) -> String {
626 if unsafe { JS_DeprecatedStringHasLatin1Chars(jsstr.as_ptr()) } {
627 return latin1_to_string(cx, jsstr);
628 }
629
630 let mut length = 0;
631 let chars = unsafe { JS_GetTwoByteStringCharsAndLength(cx, jsstr.as_ptr(), &mut length) };
632 assert!(!chars.is_null());
633 let char_vec = unsafe { slice::from_raw_parts(chars, length as usize) };
634 String::from_utf16_lossy(char_vec)
635}
636
637#[deprecated(note = "Use latin1_to_string instead")]
642pub unsafe fn unsafe_latin1_to_string(cx: *mut JSContext, s: NonNull<JSString>) -> String {
643 let cx = crate::context::JSContext::from_ptr(NonNull::new(cx).unwrap());
646 latin1_to_string(&cx, s)
647}
648
649#[deprecated(note = "Use jsstr_to_string instead")]
653pub unsafe fn unsafe_jsstr_to_string(cx: *mut JSContext, jsstr: NonNull<JSString>) -> String {
654 let cx = crate::context::JSContext::from_ptr(NonNull::new(cx).unwrap());
657 jsstr_to_string(&cx, jsstr)
658}
659
660impl ToJSValConvertible for str {
662 #[inline]
663 #[deny(unsafe_op_in_unsafe_fn)]
664 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
665 let s = Utf8Chars::from(self);
669 let jsstr = unsafe { JS_NewStringCopyUTF8N(cx, &*s as *const _) };
670 if jsstr.is_null() {
671 panic!("JS String copy routine failed");
672 }
673 unsafe {
674 rval.set(StringValue(&*jsstr));
675 }
676 }
677}
678
679impl ToJSValConvertible for String {
681 #[inline]
682 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
683 (**self).safe_to_jsval(cx, rval);
684 }
685}
686
687impl FromJSValConvertible for String {
689 type Config = ();
690
691 fn safe_from_jsval(
692 cx: &mut crate::context::JSContext,
693 value: HandleValue,
694 _config: Self::Config,
695 ) -> Result<ConversionResult<String>, ()> {
696 let jsstr = unsafe { ToString(cx, value) };
697 let Some(jsstr) = NonNull::new(jsstr) else {
698 debug!("ToString failed");
699 return Err(());
700 };
701 Ok(unsafe { jsstr_to_string(cx, jsstr) }).map(ConversionResult::Success)
702 }
703}
704
705impl<T: ToJSValConvertible> ToJSValConvertible for Option<T> {
706 #[inline]
707 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
708 match self {
709 &Some(ref value) => value.safe_to_jsval(cx, rval),
710 &None => rval.set(NullValue()),
711 }
712 }
713}
714
715impl<T: FromJSValConvertible> FromJSValConvertible for Option<T> {
716 type Config = T::Config;
717
718 fn safe_from_jsval(
719 cx: &mut crate::context::JSContext,
720 value: HandleValue,
721 option: T::Config,
722 ) -> Result<ConversionResult<Option<T>>, ()> {
723 if value.get().is_null_or_undefined() {
724 Ok(ConversionResult::Success(None))
725 } else {
726 Ok(
727 match FromJSValConvertible::safe_from_jsval(cx, value, option)? {
728 ConversionResult::Success(v) => ConversionResult::Success(Some(v)),
729 ConversionResult::Failure(v) => ConversionResult::Failure(v),
730 },
731 )
732 }
733 }
734}
735
736impl<T: ToJSValConvertible> ToJSValConvertible for &'_ T {
737 #[inline]
738 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
739 (**self).safe_to_jsval(cx, rval)
740 }
741}
742
743impl<T: ToJSValConvertible> ToJSValConvertible for Box<T> {
744 #[inline]
745 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
746 (**self).safe_to_jsval(cx, rval)
747 }
748}
749
750impl<T: ToJSValConvertible> ToJSValConvertible for Rc<T> {
751 #[inline]
752 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
753 (**self).safe_to_jsval(cx, rval)
754 }
755}
756
757impl<T: ToJSValConvertible> ToJSValConvertible for [T] {
759 #[inline]
760 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
761 rooted!(&in(cx) let js_array = unsafe { NewArrayObject1(cx, self.len() as libc::size_t) });
762 assert!(!js_array.handle().is_null());
763
764 rooted!(&in(cx) let mut val = UndefinedValue());
765 for (index, obj) in self.iter().enumerate() {
766 obj.safe_to_jsval(cx, val.handle_mut());
767
768 assert!(unsafe {
769 JS_DefineElement(
770 cx,
771 js_array.handle(),
772 index as u32,
773 val.handle(),
774 JSPROP_ENUMERATE as u32,
775 )
776 });
777 }
778
779 rval.set(ObjectValue(js_array.handle().get()));
780 }
781}
782
783impl<T: ToJSValConvertible> ToJSValConvertible for Vec<T> {
785 #[inline]
786 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
787 <[_]>::safe_to_jsval(self, cx, rval)
788 }
789}
790
791impl<C: Clone, T: FromJSValConvertible<Config = C>> FromJSValConvertible for Vec<T> {
792 type Config = C;
793
794 fn safe_from_jsval(
795 cx: &mut crate::context::JSContext,
796 value: HandleValue,
797 option: C,
798 ) -> Result<ConversionResult<Vec<T>>, ()> {
799 if !value.is_object() {
800 return Ok(ConversionResult::Failure(c"Value is not an object".into()));
801 }
802
803 let mut return_value = vec![];
804 let result = for_of(unsafe { cx.raw_cx() }, value, |iterator_element| {
805 let conversion_result = T::safe_from_jsval(cx, iterator_element, option.clone())
806 .map_err(|_| ForOfIterationFailure::JSFailed)?;
807 return_value.push(match conversion_result {
808 ConversionResult::Success(value) => value,
809 ConversionResult::Failure(error) => {
810 return Err(ForOfIterationFailure::Other(error));
811 }
812 });
813
814 Ok(ControlFlow::Continue(()))
815 });
816
817 match result {
818 Ok(_) => Ok(ConversionResult::Success(return_value)),
819 Err(ForOfIterationFailure::ValueIsNotIterable) => {
820 Ok(ConversionResult::Failure(c"Value is not iterable".into()))
821 }
822 Err(ForOfIterationFailure::JSFailed) => Err(()),
823 Err(ForOfIterationFailure::Other(error)) => {
824 unsafe { throw_type_error(cx.raw_cx(), error.as_ref()) };
825 Err(())
826 }
827 }
828 }
829}
830
831impl ToJSValConvertible for *mut JSObject {
833 #[inline]
834 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
835 rval.set(ObjectOrNullValue(*self));
836 maybe_wrap_object_or_null_value(cx, rval);
837 }
838}
839
840impl ToJSValConvertible for ptr::NonNull<JSObject> {
842 #[inline]
843 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
844 rval.set(ObjectValue(self.as_ptr()));
845 unsafe { maybe_wrap_object_value(cx, rval) };
846 }
847}
848
849impl ToJSValConvertible for Heap<*mut JSObject> {
851 #[inline]
852 fn safe_to_jsval(&self, cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
853 rval.set(ObjectOrNullValue(self.get()));
854 maybe_wrap_object_or_null_value(cx, rval);
855 }
856}
857
858impl FromJSValConvertible for *mut JSObject {
860 type Config = ();
861
862 #[inline]
863 fn safe_from_jsval(
864 cx: &mut crate::context::JSContext,
865 value: HandleValue,
866 _option: (),
867 ) -> Result<ConversionResult<*mut JSObject>, ()> {
868 if !value.is_object() {
869 unsafe {
870 throw_type_error(cx.raw_cx(), c"value is not an object");
871 }
872 return Err(());
873 }
874
875 unsafe { AssertSameCompartment(cx, value.to_object()) };
876
877 Ok(ConversionResult::Success(value.to_object()))
878 }
879}
880
881impl ToJSValConvertible for *mut JS::Symbol {
882 #[inline]
883 fn safe_to_jsval(&self, _cx: &mut crate::context::JSContext, mut rval: MutableHandleValue) {
884 unsafe { rval.set(SymbolValue(&**self)) };
885 }
886}
887
888impl FromJSValConvertible for *mut JS::Symbol {
889 type Config = ();
890
891 #[inline]
892 fn safe_from_jsval(
893 cx: &mut crate::context::JSContext,
894 value: HandleValue,
895 _option: (),
896 ) -> Result<ConversionResult<*mut JS::Symbol>, ()> {
897 if !value.is_symbol() {
898 unsafe {
899 throw_type_error(cx.raw_cx(), c"value is not a symbol");
900 }
901 return Err(());
902 }
903
904 Ok(ConversionResult::Success(value.to_symbol()))
905 }
906}
907
908pub struct Utf8Chars<'a> {
912 lt_marker: std::marker::PhantomData<&'a ()>,
913 inner: crate::jsapi::UTF8Chars,
914}
915
916impl<'a> std::ops::Deref for Utf8Chars<'a> {
917 type Target = crate::jsapi::UTF8Chars;
918
919 fn deref(&self) -> &Self::Target {
920 &self.inner
921 }
922}
923
924impl<'a> From<&'a str> for Utf8Chars<'a> {
925 #[allow(unsafe_code)]
926 fn from(value: &'a str) -> Self {
927 use std::marker::PhantomData;
928
929 use crate::jsapi::mozilla::{Range, RangedPtr};
930 use crate::jsapi::UTF8Chars;
931
932 let range = value.as_bytes().as_ptr_range();
933 let range_start = range.start as *mut _;
934 let range_end = range.end as *mut _;
935 let start = RangedPtr {
936 _phantom_0: PhantomData,
937 mPtr: range_start,
938 #[cfg(feature = "debugmozjs")]
939 mRangeStart: range_start,
940 #[cfg(feature = "debugmozjs")]
941 mRangeEnd: range_end,
942 };
943 let end = RangedPtr {
944 _phantom_0: PhantomData,
945 mPtr: range_end,
946 #[cfg(feature = "debugmozjs")]
947 mRangeStart: range_start,
948 #[cfg(feature = "debugmozjs")]
949 mRangeEnd: range_end,
950 };
951 let base = Range {
952 _phantom_0: PhantomData,
953 mStart: start,
954 mEnd: end,
955 };
956 let inner = UTF8Chars { _base: base };
957 Self {
958 lt_marker: PhantomData,
959 inner,
960 }
961 }
962}