1use std::collections::HashMap;
2use std::convert::TryFrom;
3use std::convert::TryInto;
4use std::hash::Hash;
5
6#[cfg(feature = "chrono")]
7use chrono::{DateTime, Utc};
8use libquickjs_ng_sys as q;
9
10#[cfg(feature = "bigint")]
11use crate::utils::create_bigint;
12#[cfg(feature = "chrono")]
13use crate::utils::create_date;
14use crate::utils::{
15 add_array_element, add_object_property, create_bool, create_empty_array, create_empty_object,
16 create_float, create_function, create_int, create_null, create_string,
17};
18use crate::OwnedJsPromise;
19use crate::{ExecutionError, ValueError};
20
21use super::tag::JsTag;
22use super::JsCompiledFunction;
23use super::JsFunction;
24use super::JsModule;
25use super::OwnedJsArray;
26use super::OwnedJsObject;
27
28pub struct OwnedJsValue {
39 context: *mut q::JSContext,
40 pub(crate) value: q::JSValue,
42}
43
44unsafe impl Send for OwnedJsValue {}
45unsafe impl Sync for OwnedJsValue {}
46
47impl PartialEq for OwnedJsValue {
48 fn eq(&self, other: &Self) -> bool {
49 unsafe { q::JS_Ext_GetPtr(self.value) == q::JS_Ext_GetPtr(other.value) }
50 }
51}
52
53impl OwnedJsValue {
54 #[inline]
55 pub fn context(&self) -> *mut q::JSContext {
56 self.context
57 }
58
59 #[inline]
63 pub fn new(context: *mut q::JSContext, value: q::JSValue) -> Self {
64 Self { context, value }
65 }
66
67 #[inline]
70 pub fn own(context: *mut q::JSContext, value: &q::JSValue) -> Self {
71 unsafe { q::JS_DupValue(context, *value) };
72 Self::new(context, *value)
73 }
74
75 #[inline]
76 pub fn tag(&self) -> JsTag {
77 JsTag::from_c(&self.value)
78 }
79
80 pub unsafe fn as_inner(&self) -> &q::JSValue {
84 &self.value
85 }
86
87 pub unsafe fn extract(self) -> q::JSValue {
91 let v = self.value;
92 std::mem::forget(self);
93 v
94 }
95
96 pub fn replace(&mut self, new: q::JSValue) {
99 unsafe {
100 q::JS_FreeValue(self.context, self.value);
101 }
102 self.value = new;
103 }
104
105 #[inline]
107 pub fn is_null(&self) -> bool {
108 self.tag().is_null()
109 }
110
111 #[inline]
113 pub fn is_undefined(&self) -> bool {
114 self.tag() == JsTag::Undefined
115 }
116
117 #[inline]
119 pub fn is_bool(&self) -> bool {
120 self.tag() == JsTag::Bool
121 }
122
123 #[inline]
125 pub fn is_int(&self) -> bool {
126 self.tag() == JsTag::Int
127 }
128
129 #[inline]
131 #[cfg(feature = "bigint")]
132 pub fn is_bigint(&self) -> bool {
133 self.tag() == JsTag::BigInt || self.tag() == JsTag::ShortBigInt
134 }
135
136 #[inline]
138 #[cfg(feature = "bigint")]
139 pub fn is_short_bigint(&self) -> bool {
140 self.tag() == JsTag::ShortBigInt
141 }
142
143 #[inline]
145 pub fn is_float(&self) -> bool {
146 self.tag() == JsTag::Float64
147 }
148
149 #[inline]
151 pub fn is_exception(&self) -> bool {
152 self.tag() == JsTag::Exception
153 }
154
155 #[inline]
157 pub fn is_object(&self) -> bool {
158 self.tag() == JsTag::Object
159 }
160
161 #[inline]
163 pub fn is_array(&self) -> bool {
164 unsafe { q::JS_IsArray(self.value) }
165 }
166
167 #[inline]
169 pub fn is_array_buffer(&self) -> bool {
170 unsafe { q::JS_IsArrayBuffer(self.value) }
171 }
172
173 #[inline]
175 pub fn is_proxy(&self) -> bool {
176 unsafe { q::JS_IsProxy(self.value) }
177 }
178
179 #[inline]
181 pub fn is_function(&self) -> bool {
182 unsafe { q::JS_IsFunction(self.context, self.value) }
183 }
184
185 #[inline]
187 pub fn is_constructor(&self) -> bool {
188 unsafe { q::JS_IsConstructor(self.context, self.value) }
189 }
190
191 #[inline]
193 pub fn is_promise(&self) -> bool {
194 unsafe { q::JS_Ext_IsPromise(self.context, self.value) }
195 }
196
197 #[inline]
199 pub fn is_error(&self) -> bool {
200 unsafe { q::JS_IsError(self.context, self.value) }
201 }
202
203 #[inline]
205 pub fn is_regexp(&self) -> bool {
206 unsafe { q::JS_IsRegExp(self.value) }
207 }
208
209 #[inline]
211 pub fn is_set(&self) -> bool {
212 unsafe { q::JS_IsSet(self.value) }
213 }
214
215 #[inline]
217 pub fn is_map(&self) -> bool {
218 unsafe { q::JS_IsMap(self.value) }
219 }
220
221 #[inline]
223 pub fn is_weak_set(&self) -> bool {
224 unsafe { q::JS_IsWeakSet(self.value) }
225 }
226
227 #[inline]
229 pub fn is_weak_map(&self) -> bool {
230 unsafe { q::JS_IsWeakMap(self.value) }
231 }
232
233 #[inline]
235 pub fn is_weak_ref(&self) -> bool {
236 unsafe { q::JS_IsWeakRef(self.value) }
237 }
238
239 #[inline]
241 pub fn is_data_view(&self) -> bool {
242 unsafe { q::JS_IsDataView(self.value) }
243 }
244
245 #[inline]
247 pub fn is_module(&self) -> bool {
248 self.tag().is_module()
249 }
250
251 #[inline]
253 pub fn is_string(&self) -> bool {
254 self.tag() == JsTag::String
255 }
256
257 #[inline]
259 pub fn is_compiled_function(&self) -> bool {
260 self.tag() == JsTag::FunctionBytecode
261 }
262
263 #[inline]
264 fn check_tag(&self, expected: JsTag) -> Result<(), ValueError> {
265 if self.tag() == expected {
266 Ok(())
267 } else {
268 Err(ValueError::UnexpectedType)
269 }
270 }
271
272 pub fn to_bool(&self) -> Result<bool, ValueError> {
274 self.check_tag(JsTag::Bool)?;
275 let val = unsafe { q::JS_Ext_GetBool(self.value) };
276 Ok(val == 1)
277 }
278
279 pub fn to_int(&self) -> Result<i32, ValueError> {
281 self.check_tag(JsTag::Int)?;
282 let val = unsafe { q::JS_Ext_GetInt(self.value) };
283 Ok(val)
284 }
285
286 pub fn to_float(&self) -> Result<f64, ValueError> {
288 self.check_tag(JsTag::Float64)?;
289 let val = unsafe { q::JS_Ext_GetFloat64(self.value) };
290 Ok(val)
291 }
292
293 pub fn to_string(&self) -> Result<String, ValueError> {
295 self.check_tag(JsTag::String)?;
296 let ptr =
297 unsafe { q::JS_ToCStringLen2(self.context, std::ptr::null_mut(), self.value, false) };
298
299 if ptr.is_null() {
300 return Err(ValueError::Internal(
301 "Could not convert string: got a null pointer".into(),
302 ));
303 }
304
305 let cstr = unsafe { std::ffi::CStr::from_ptr(ptr) };
306
307 let s = cstr
308 .to_str()
309 .map_err(ValueError::InvalidString)?
310 .to_string();
311
312 unsafe { q::JS_FreeCString(self.context, ptr) };
314
315 Ok(s)
316 }
317
318 pub fn to_array(&self) -> Result<OwnedJsArray, ValueError> {
319 OwnedJsArray::try_from_value(self.clone())
320 }
321
322 pub fn get_proxy_target(&self, recursive: bool) -> Result<OwnedJsValue, ValueError> {
323 if !self.is_proxy() {
324 return Err(ValueError::UnexpectedType);
325 }
326
327 let target = unsafe { q::JS_GetProxyTarget(self.context, self.value) };
328 let target = OwnedJsValue::new(self.context, target);
329
330 if recursive && target.is_proxy() {
331 target.get_proxy_target(true)
332 } else {
333 Ok(target)
334 }
335 }
336
337 pub fn try_into_object(self) -> Result<OwnedJsObject, ValueError> {
339 OwnedJsObject::try_from_value(self)
340 }
341
342 #[cfg(feature = "chrono")]
343 pub fn to_date(&self) -> Result<chrono::DateTime<chrono::Utc>, ValueError> {
344 use chrono::offset::TimeZone;
345
346 use crate::utils::js_date_constructor;
347
348 let date_constructor = js_date_constructor(self.context);
349 let is_date = unsafe { q::JS_IsInstanceOf(self.context, self.value, date_constructor) > 0 };
350
351 if is_date {
352 let getter = unsafe {
353 q::JS_GetPropertyStr(
354 self.context,
355 self.value,
356 std::ffi::CStr::from_bytes_with_nul(b"getTime\0")
357 .unwrap()
358 .as_ptr(),
359 )
360 };
361 let tag = unsafe { q::JS_Ext_ValueGetTag(getter) };
362 assert_eq!(tag, q::JS_TAG_OBJECT);
363
364 let timestamp_raw =
365 unsafe { q::JS_Call(self.context, getter, self.value, 0, std::ptr::null_mut()) };
366
367 unsafe {
368 q::JS_FreeValue(self.context, getter);
369 q::JS_FreeValue(self.context, date_constructor);
370 };
371
372 let tag = unsafe { q::JS_Ext_ValueGetTag(timestamp_raw) };
373 if tag == q::JS_TAG_FLOAT64 {
374 let f = unsafe { q::JS_Ext_GetFloat64(timestamp_raw) } as i64;
375 let datetime = chrono::Utc.timestamp_millis_opt(f).unwrap();
376 Ok(datetime)
377 } else if tag == q::JS_TAG_INT {
378 let f = unsafe { q::JS_Ext_GetInt(timestamp_raw) } as i64;
379 let datetime = chrono::Utc.timestamp_millis_opt(f).unwrap();
380 Ok(datetime)
381 } else {
382 Err(ValueError::Internal(
383 "Could not convert 'Date' instance to timestamp".into(),
384 ))
385 }
386 } else {
387 unsafe { q::JS_FreeValue(self.context, date_constructor) };
388 Err(ValueError::UnexpectedType)
389 }
390 }
391
392 #[cfg(feature = "bigint")]
393 pub fn to_bigint(&self) -> Result<crate::BigInt, ValueError> {
394 use crate::value::BigInt;
395 use crate::value::BigIntOrI64;
396
397 if self.is_int() {
398 let int = self.to_int()?;
399 return Ok(BigInt {
400 inner: BigIntOrI64::Int(int as i64),
401 });
402 }
403
404 if self.is_float() {
406 let float = self.to_float()?;
407 return Ok(BigInt {
408 inner: BigIntOrI64::Int(float as i64),
409 });
410 }
411
412 if self.is_short_bigint() {
413 let int = unsafe { q::JS_Ext_GetShortBigInt(self.value) };
414 return Ok(BigInt {
415 inner: BigIntOrI64::Int(int as i64),
416 });
417 }
418
419 let ret = unsafe { q::JS_Ext_BigIntToString1(self.context, self.value, 16) };
420 let ret = OwnedJsValue::new(self.context, ret);
421
422 if ret.is_exception() {
423 let err = OwnedJsValue::new(self.context, unsafe { q::JS_GetException(self.context) });
424
425 return Err(ValueError::Internal(format!(
426 "Could not convert BigInt to string: {}",
427 err.js_to_string().unwrap()
428 )));
429 }
430
431 if !ret.is_string() {
432 return Err(ValueError::Internal(
433 "Could not convert BigInt: unexpected error".into(),
434 ));
435 }
436
437 let ret_str = ret.to_string().unwrap();
438
439 let bigint = num_bigint::BigInt::parse_bytes(ret_str.as_bytes(), 16).unwrap();
440
441 Ok(BigInt {
442 inner: BigIntOrI64::BigInt(bigint),
443 })
444 }
446
447 pub fn try_into_function(self) -> Result<JsFunction, ValueError> {
449 JsFunction::try_from_value(self)
450 }
451
452 pub fn try_into_promise(self) -> Result<OwnedJsPromise, ValueError> {
454 OwnedJsPromise::try_from_value(self)
455 }
456
457 pub fn try_into_compiled_function(self) -> Result<JsCompiledFunction, ValueError> {
459 JsCompiledFunction::try_from_value(self)
460 }
461
462 pub fn try_into_module(self) -> Result<JsModule, ValueError> {
464 JsModule::try_from_value(self)
465 }
466
467 pub fn js_to_string(&self) -> Result<String, ExecutionError> {
469 let value = if self.is_string() {
470 self.to_string()?
471 } else {
472 let raw = unsafe { q::JS_ToString(self.context, self.value) };
473 let value = OwnedJsValue::new(self.context, raw);
474
475 if !value.is_string() {
476 return Err(ExecutionError::Internal(
477 "Could not convert value to string".into(),
478 ));
479 }
480 value.to_string()?
481 };
482
483 Ok(value)
484 }
485
486 pub fn to_json_string(&self, space: u8) -> Result<String, ExecutionError> {
488 let replacer = unsafe { q::JS_Ext_NewSpecialValue(q::JS_TAG_NULL, 0) };
489 let space = unsafe { q::JS_Ext_NewInt32(self.context, space as i32) };
490 let raw = unsafe { q::JS_JSONStringify(self.context, self.value, replacer, space) };
491
492 let value = OwnedJsValue::new(self.context, raw);
493
494 unsafe {
495 q::JS_FreeValue(self.context, replacer);
496 q::JS_FreeValue(self.context, space);
497 }
498
499 if !value.is_string() {
500 return Err(ExecutionError::Internal(
501 "Could not convert value to string".to_string(),
502 ));
503 }
504
505 let value = value.to_string()?;
506
507 Ok(value)
508 }
509
510 #[cfg(test)]
511 pub(crate) fn get_ref_count(&self) -> i32 {
512 unsafe { q::JS_Ext_GetRefCount(self.value) }
513 }
514}
515
516impl Drop for OwnedJsValue {
517 fn drop(&mut self) {
518 unsafe {
519 q::JS_FreeValue(self.context, self.value);
520 }
521 }
522}
523
524impl Clone for OwnedJsValue {
525 fn clone(&self) -> Self {
526 unsafe { q::JS_DupValue(self.context, self.value) };
527 Self {
528 context: self.context,
529 value: self.value,
530 }
531 }
532}
533
534impl std::fmt::Debug for OwnedJsValue {
535 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
536 write!(f, "{:?}(_)", self.tag())
537 }
538}
539
540impl TryFrom<OwnedJsValue> for bool {
541 type Error = ValueError;
542
543 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
544 value.to_bool()
545 }
546}
547
548impl TryFrom<OwnedJsValue> for i32 {
549 type Error = ValueError;
550
551 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
552 if value.is_int() {
553 return value.to_int();
554 } else if value.is_float() {
555 let f = value.to_float()?;
556 if f.fract() != 0.0 {
557 return Err(ValueError::UnexpectedType);
558 }
559 if f < (i32::MIN as f64) || f > (i32::MAX as f64) {
560 return Err(ValueError::OutOfRange);
561 }
562 return Ok(f as i32);
563 }
564 Err(ValueError::UnexpectedType)
565 }
566}
567
568impl TryFrom<OwnedJsValue> for f64 {
569 type Error = ValueError;
570
571 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
572 if value.is_float() {
573 return value.to_float();
574 } else if value.is_int() {
575 let i = value.to_int()?;
576 return Ok(i as f64);
577 }
578 Err(ValueError::UnexpectedType)
579 }
580}
581
582impl TryFrom<OwnedJsValue> for String {
583 type Error = ValueError;
584
585 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
586 value.to_string()
587 }
588}
589
590#[cfg(feature = "chrono")]
591impl TryFrom<OwnedJsValue> for DateTime<Utc> {
592 type Error = ValueError;
593
594 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
595 value.to_date()
596 }
597}
598
599#[cfg(feature = "bigint")]
600impl TryFrom<OwnedJsValue> for crate::BigInt {
601 type Error = ValueError;
602
603 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
604 value.to_bigint()
605 }
606}
607
608#[cfg(feature = "bigint")]
609impl TryFrom<OwnedJsValue> for i64 {
610 type Error = ValueError;
611
612 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
613 if value.is_int() {
614 value.to_int().map(|v| v as i64)
615 } else {
616 value
617 .to_bigint()
618 .and_then(|v| v.as_i64().ok_or(ValueError::BigIntOverflow))
619 }
620 }
621}
622
623#[cfg(feature = "bigint")]
624impl TryFrom<OwnedJsValue> for u64 {
625 type Error = ValueError;
626
627 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
628 use num_traits::ToPrimitive;
629 let bigint = value.to_bigint()?;
630 bigint
631 .into_bigint()
632 .to_u64()
633 .ok_or(ValueError::BigIntOverflow)
634 }
635}
636
637#[cfg(feature = "bigint")]
638impl TryFrom<OwnedJsValue> for i128 {
639 type Error = ValueError;
640
641 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
642 use num_traits::ToPrimitive;
643 let bigint = value.to_bigint()?;
644 bigint
645 .into_bigint()
646 .to_i128()
647 .ok_or(ValueError::BigIntOverflow)
648 }
649}
650
651#[cfg(feature = "bigint")]
652impl TryFrom<OwnedJsValue> for u128 {
653 type Error = ValueError;
654
655 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
656 use num_traits::ToPrimitive;
657 let bigint = value.to_bigint()?;
658 bigint
659 .into_bigint()
660 .to_u128()
661 .ok_or(ValueError::BigIntOverflow)
662 }
663}
664
665#[cfg(feature = "bigint")]
666impl TryFrom<OwnedJsValue> for num_bigint::BigInt {
667 type Error = ValueError;
668
669 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
670 value.to_bigint().map(|v| v.into_bigint())
671 }
672}
673
674impl<T: TryFrom<OwnedJsValue, Error = ValueError>> TryFrom<OwnedJsValue> for Option<T> {
675 type Error = ValueError;
676
677 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
678 if value.is_null() {
679 return Ok(None);
680 }
681 Ok(Some(value.try_into()?))
682 }
683}
684
685impl<T: TryFrom<OwnedJsValue, Error = ValueError>> TryFrom<OwnedJsValue> for Vec<T> {
686 type Error = ValueError;
687
688 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
689 let arr = value.to_array()?;
690 let mut ret: Vec<T> = vec![];
691 for i in 0..arr.length() {
692 let item = arr.get_index(i as u32).unwrap();
693 if let Some(item) = item {
694 let item = item.try_into()?;
695 ret.push(item);
696 }
697 }
698 Ok(ret)
699 }
700}
701
702impl<K: From<String> + PartialEq + Eq + Hash, V: TryFrom<OwnedJsValue, Error = ValueError>>
703 TryFrom<OwnedJsValue> for HashMap<K, V>
704{
705 type Error = ValueError;
706
707 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
708 let obj = value.try_into_object()?;
709 let mut ret: HashMap<K, V> = HashMap::new();
710 let mut iter = obj.properties_iter()?.step_by(2);
711 while let Some(Ok(key)) = iter.next() {
712 let key = key.to_string()?;
713 let item = obj.property(&key).unwrap();
714 if let Some(item) = item {
715 let item = item.try_into()?;
716 ret.insert(key.into(), item);
717 }
718 }
719 Ok(ret)
720 }
721}
722
723impl TryFrom<OwnedJsValue> for JsFunction {
724 type Error = ValueError;
725
726 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
727 JsFunction::try_from_value(value)
728 }
729}
730
731impl TryFrom<OwnedJsValue> for OwnedJsPromise {
732 type Error = ValueError;
733
734 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
735 OwnedJsPromise::try_from_value(value)
736 }
737}
738
739impl TryFrom<OwnedJsValue> for OwnedJsArray {
740 type Error = ValueError;
741
742 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
743 OwnedJsArray::try_from_value(value)
744 }
745}
746
747impl TryFrom<OwnedJsValue> for OwnedJsObject {
748 type Error = ValueError;
749
750 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
751 OwnedJsObject::try_from_value(value)
752 }
753}
754
755impl TryFrom<OwnedJsValue> for JsCompiledFunction {
756 type Error = ValueError;
757
758 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
759 JsCompiledFunction::try_from_value(value)
760 }
761}
762
763impl TryFrom<OwnedJsValue> for JsModule {
764 type Error = ValueError;
765
766 fn try_from(value: OwnedJsValue) -> Result<Self, Self::Error> {
767 JsModule::try_from_value(value)
768 }
769}
770
771pub trait ToOwnedJsValue {
776 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue;
777}
778
779impl ToOwnedJsValue for bool {
780 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
781 let val = create_bool(context, self);
782 OwnedJsValue::new(context, val)
783 }
784}
785
786impl ToOwnedJsValue for i32 {
787 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
788 let val = create_int(context, self);
789 OwnedJsValue::new(context, val)
790 }
791}
792
793impl ToOwnedJsValue for i8 {
794 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
795 let val = create_int(context, self as i32);
796 OwnedJsValue::new(context, val)
797 }
798}
799
800impl ToOwnedJsValue for i16 {
801 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
802 let val = create_int(context, self as i32);
803 OwnedJsValue::new(context, val)
804 }
805}
806
807impl ToOwnedJsValue for u8 {
808 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
809 let val = create_int(context, self as i32);
810 OwnedJsValue::new(context, val)
811 }
812}
813
814impl ToOwnedJsValue for u16 {
815 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
816 let val = create_int(context, self as i32);
817 OwnedJsValue::new(context, val)
818 }
819}
820
821impl ToOwnedJsValue for f64 {
822 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
823 let val = create_float(context, self);
824 OwnedJsValue::new(context, val)
825 }
826}
827
828impl ToOwnedJsValue for u32 {
829 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
830 let val = create_float(context, self as f64);
831 OwnedJsValue::new(context, val)
832 }
833}
834
835impl ToOwnedJsValue for &str {
836 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
837 let val = create_string(context, self).unwrap();
838 OwnedJsValue::new(context, val)
839 }
840}
841
842impl ToOwnedJsValue for String {
843 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
844 let val = create_string(context, &self).unwrap();
845 OwnedJsValue::new(context, val)
846 }
847}
848
849#[cfg(feature = "chrono")]
850impl ToOwnedJsValue for DateTime<Utc> {
851 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
852 let val = create_date(context, self).unwrap();
853 OwnedJsValue::new(context, val)
854 }
855}
856
857#[cfg(feature = "bigint")]
858impl ToOwnedJsValue for crate::BigInt {
859 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
860 let val = create_bigint(context, self).unwrap();
861 OwnedJsValue::new(context, val)
862 }
863}
864
865#[cfg(feature = "bigint")]
866impl ToOwnedJsValue for num_bigint::BigInt {
867 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
868 let val = create_bigint(context, self.into()).unwrap();
869 OwnedJsValue::new(context, val)
870 }
871}
872
873#[cfg(feature = "bigint")]
874impl ToOwnedJsValue for i64 {
875 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
876 let val = create_bigint(context, self.into()).unwrap();
877 OwnedJsValue::new(context, val)
878 }
879}
880
881#[cfg(feature = "bigint")]
882impl ToOwnedJsValue for u64 {
883 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
884 let bigint: num_bigint::BigInt = self.into();
885 let val = create_bigint(context, bigint.into()).unwrap();
886 OwnedJsValue::new(context, val)
887 }
888}
889
890#[cfg(feature = "bigint")]
891impl ToOwnedJsValue for i128 {
892 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
893 let bigint: num_bigint::BigInt = self.into();
894 let val = create_bigint(context, bigint.into()).unwrap();
895 OwnedJsValue::new(context, val)
896 }
897}
898
899#[cfg(feature = "bigint")]
900impl ToOwnedJsValue for u128 {
901 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
902 let bigint: num_bigint::BigInt = self.into();
903 let val = create_bigint(context, bigint.into()).unwrap();
904 OwnedJsValue::new(context, val)
905 }
906}
907
908impl ToOwnedJsValue for JsFunction {
909 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
910 let val = create_function(context, self).unwrap();
911 OwnedJsValue::new(context, val)
912 }
913}
914
915impl ToOwnedJsValue for OwnedJsPromise {
916 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
917 let val = unsafe { self.into_value().extract() };
918 OwnedJsValue::new(context, val)
919 }
920}
921
922impl ToOwnedJsValue for OwnedJsValue {
924 fn to_owned(self, _: *mut q::JSContext) -> OwnedJsValue {
925 self
926 }
927}
928
929impl<T> ToOwnedJsValue for Vec<T>
930where
931 T: ToOwnedJsValue,
932{
933 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
934 let arr = create_empty_array(context).unwrap();
935 self.into_iter().enumerate().for_each(|(idx, val)| {
936 let val: OwnedJsValue = (context, val).into();
937 add_array_element(context, arr, idx as u32, unsafe { val.extract() }).unwrap();
938 });
939
940 OwnedJsValue::new(context, arr)
941 }
942}
943
944impl<K, V> ToOwnedJsValue for HashMap<K, V>
945where
946 K: Into<String>,
947 V: ToOwnedJsValue,
948{
949 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
950 let obj = create_empty_object(context).unwrap();
951 self.into_iter().for_each(|(key, val)| {
952 let val: OwnedJsValue = (context, val).into();
953 add_object_property(context, obj, key.into().as_str(), unsafe { val.extract() })
954 .unwrap();
955 });
956
957 OwnedJsValue::new(context, obj)
958 }
959}
960
961impl<T> ToOwnedJsValue for Option<T>
962where
963 T: ToOwnedJsValue,
964{
965 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
966 if let Some(val) = self {
967 (context, val).into()
968 } else {
969 OwnedJsValue::new(context, create_null())
970 }
971 }
972}
973
974impl<T> ToOwnedJsValue for &T
975where
976 T: ToOwnedJsValue,
977{
978 fn to_owned(self, context: *mut q::JSContext) -> OwnedJsValue {
979 (context, self).into()
980 }
981}
982
983impl<T> From<(*mut q::JSContext, T)> for OwnedJsValue
984where
985 T: ToOwnedJsValue,
986{
987 fn from((context, value): (*mut q::JSContext, T)) -> Self {
988 value.to_owned(context)
989 }
990}