1use alloc::string::{String, ToString as _};
2use alloc::vec::Vec;
3
4use rquickjs::{
5 Exception, Filter, Function, Null, Object, String as JSString, Value,
6 atom::PredefinedAtom,
7 function::This,
8 object::ObjectIter,
9 qjs::{
10 JS_GetClassID, JS_GetProperty, JS_GetPropertyUint32, JS_TAG_EXCEPTION,
11 JS_VALUE_GET_NORM_TAG,
12 },
13};
14use serde::{
15 de::{self, IntoDeserializer, Unexpected},
16 forward_to_deserialize_any,
17};
18
19use crate::err::{Error, Result};
20use crate::utils::{as_key, to_string_lossy};
21use crate::{MAX_SAFE_INTEGER, MIN_SAFE_INTEGER};
22
23enum ClassId {
27 Number = 4,
28 String = 5,
29 Bool = 6,
30 BigInt = 35,
31}
32
33pub struct Deserializer<'js> {
54 value: Value<'js>,
55 strict: bool,
57 map_key: bool,
58 current_kv: Option<(Value<'js>, Value<'js>)>,
59 stack: Vec<Value<'js>>,
61}
62
63impl<'js> Deserializer<'js> {
64 pub fn new(value: Value<'js>) -> Self {
65 Self::from(value)
66 }
67
68 pub fn with_strict(self) -> Self {
69 Self {
70 strict: true,
71 ..self
72 }
73 }
74}
75
76impl<'de> From<Value<'de>> for Deserializer<'de> {
77 fn from(value: Value<'de>) -> Self {
78 Self {
79 value,
80 strict: false,
81 map_key: false,
82 current_kv: None,
83 stack: Vec::with_capacity(100),
86 }
87 }
88}
89
90impl<'js> Deserializer<'js> {
91 fn deserialize_number<'de, V>(&mut self, visitor: V) -> Result<V::Value>
92 where
93 V: de::Visitor<'de>,
94 {
95 if let Some(i) = self.value.as_int() {
96 return visitor.visit_i32(i);
97 }
98
99 if let Some(f64_representation) = self.value.as_float() {
100 let is_positive = f64_representation.is_sign_positive();
101 let safe_integer_range = (MIN_SAFE_INTEGER as f64)..=(MAX_SAFE_INTEGER as f64);
102 let whole = (f64_representation % 1.0) == 0.0;
103
104 if whole && is_positive && f64_representation <= u32::MAX as f64 {
105 return visitor.visit_u32(f64_representation as u32);
106 }
107
108 if whole && safe_integer_range.contains(&f64_representation) {
109 let x = f64_representation as i64;
110 return visitor.visit_i64(x);
111 }
112
113 return visitor.visit_f64(f64_representation);
114 }
115
116 Err(Error::new(Exception::throw_type(
117 self.value.ctx(),
118 "Unsupported number type",
119 )))
120 }
121
122 fn pop_visited(&mut self) -> Result<Value<'js>> {
124 let v = self
125 .stack
126 .pop()
127 .ok_or_else(|| Error::new("No entries found in the deserializer stack"))?;
128 Ok(v)
129 }
130
131 fn check_cycles(&self) -> Result<()> {
135 for val in self.stack.iter().rev() {
136 if self.value.eq(val) {
137 return Err(Error::new(Exception::throw_type(
138 val.ctx(),
139 "circular dependency",
140 )));
141 }
142 }
143 Ok(())
144 }
145}
146
147impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> {
148 type Error = Error;
149
150 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
151 where
152 V: de::Visitor<'de>,
153 {
154 if self.value.is_number() {
155 return self.deserialize_number(visitor);
156 }
157
158 if get_class_id(&self.value) == ClassId::Number as u32 {
159 let value_of = get_valueof(&self.value);
160 if let Some(f) = value_of {
161 let v = f.call((This(self.value.clone()),)).map_err(Error::new)?;
162 self.value = v;
163 return self.deserialize_number(visitor);
164 }
165 }
166
167 if let Some(b) = self.value.as_bool() {
168 return visitor.visit_bool(b);
169 }
170
171 if get_class_id(&self.value) == ClassId::Bool as u32 {
172 let value_of = get_valueof(&self.value);
173 if let Some(f) = value_of {
174 let v = f.call((This(self.value.clone()),)).map_err(Error::new)?;
175 return visitor.visit_bool(v);
176 }
177 }
178
179 if self.value.is_null() || self.value.is_undefined() {
180 return visitor.visit_unit();
181 }
182
183 if get_class_id(&self.value) == ClassId::String as u32 {
184 let value_of = get_to_string(&self.value);
185 if let Some(f) = value_of {
186 let v = f.call(((This(self.value.clone())),)).map_err(Error::new)?;
187 self.value = v;
188 }
189 }
190
191 if self.value.is_string() {
192 if self.map_key {
193 self.map_key = false;
194 let key = as_key(&self.value)?;
195 return visitor.visit_str(&key);
196 } else {
197 let val = self
198 .value
199 .as_string()
200 .map(|s| {
201 s.to_string()
202 .unwrap_or_else(|e| to_string_lossy(self.value.ctx(), s, e))
203 })
204 .unwrap();
205 return visitor.visit_str(&val);
206 }
207 }
208
209 if is_array_or_proxy_of_array(&self.value)
210 && let Some(seq) = self.value.as_object()
211 {
212 let seq_access = SeqAccess::new(self, seq.clone())?;
213 return visitor.visit_seq(seq_access);
214 }
215
216 if self.value.is_object() {
217 ensure_supported(&self.value)?;
218
219 if let Some(f) = get_to_json(&self.value) {
220 let v: Value = f.call((This(self.value.clone()),)).map_err(Error::new)?;
221
222 if v.is_undefined() {
223 self.value = Value::new_undefined(v.ctx().clone());
224 } else {
225 self.value = v;
226 }
227 return self.deserialize_any(visitor);
228 }
229
230 let map_access = MapAccess::new(self, self.value.clone().into_object().unwrap())?;
231 let result = visitor.visit_map(map_access);
232 return result;
233 }
234
235 if get_class_id(&self.value) == ClassId::BigInt as u32 || self.value.is_big_int() {
236 if let Some(f) = get_to_json(&self.value) {
237 let v: Value = f.call((This(self.value.clone()),)).map_err(Error::new)?;
238 self.value = v;
239 return self.deserialize_any(visitor);
240 }
241
242 if let Some(f) = get_to_string(&self.value)
243 && !self.strict
244 {
245 let v: Value = f.call((This(self.value.clone()),)).map_err(Error::new)?;
246 self.value = v;
247 return self.deserialize_any(visitor);
248 }
249 }
250
251 Err(Error::new(Exception::throw_type(
252 self.value.ctx(),
253 "Unsupported type",
254 )))
255 }
256
257 fn is_human_readable(&self) -> bool {
258 false
259 }
260
261 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
262 where
263 V: de::Visitor<'de>,
264 {
265 if self.value.is_null() || self.value.is_undefined() {
266 visitor.visit_none()
267 } else {
268 visitor.visit_some(self)
269 }
270 }
271
272 fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
273 where
274 V: de::Visitor<'de>,
275 {
276 visitor.visit_newtype_struct(self)
277 }
278
279 fn deserialize_enum<V>(
280 self,
281 _name: &'static str,
282 _variants: &'static [&'static str],
283 visitor: V,
284 ) -> Result<V::Value>
285 where
286 V: de::Visitor<'de>,
287 {
288 if get_class_id(&self.value) == ClassId::String as u32
289 && let Some(f) = get_to_string(&self.value)
290 {
291 let v = f.call((This(self.value.clone()),)).map_err(Error::new)?;
292 self.value = v;
293 }
294
295 let s = if let Some(s) = self.value.as_string() {
297 s.to_string()
298 .unwrap_or_else(|e| to_string_lossy(self.value.ctx(), s, e))
299 } else {
300 return Err(Error::new("expected a string for enum unit variant"));
301 };
302
303 visitor.visit_enum(UnitEnumAccess { variant: s })
305 }
306
307 forward_to_deserialize_any! {
308 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
309 bytes byte_buf unit unit_struct seq tuple
310 tuple_struct map struct identifier ignored_any
311 }
312}
313
314struct MapAccess<'a, 'de: 'a> {
316 de: &'a mut Deserializer<'de>,
318 properties: ObjectIter<'de, Value<'de>, Value<'de>>,
320 obj: Object<'de>,
322}
323
324impl<'a, 'de> MapAccess<'a, 'de> {
325 fn new(de: &'a mut Deserializer<'de>, obj: Object<'de>) -> Result<Self> {
326 let filter = Filter::new().enum_only().string();
327 let properties: ObjectIter<'_, _, Value<'_>> =
328 obj.own_props::<Value<'_>, Value<'_>>(filter);
329
330 let val = obj.clone().into_value();
331 de.stack.push(val.clone());
332
333 Ok(Self {
334 de,
335 properties,
336 obj,
337 })
338 }
339
340 fn pop(&mut self) -> Result<()> {
343 let v = self.de.pop_visited()?;
344 if v != self.obj.clone().into_value() {
345 return Err(Error::new(
346 "Popped a mismatched value. Expected the top level sequence value",
347 ));
348 }
349
350 Ok(())
351 }
352}
353
354impl<'de> de::MapAccess<'de> for MapAccess<'_, 'de> {
355 type Error = Error;
356
357 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
358 where
359 K: de::DeserializeSeed<'de>,
360 {
361 loop {
362 if let Some(kv) = self.properties.next() {
363 let (k, v) = kv.map_err(Error::new)?;
364
365 let to_json = get_to_json(&v);
366 let v = if let Some(f) = to_json {
367 f.call((This(v.clone()), k.clone())).map_err(Error::new)?
368 } else {
369 v
370 };
371
372 if !ensure_supported(&v)? || k.is_symbol() {
375 continue;
376 }
377
378 let class_id = get_class_id(&v);
379
380 if class_id == ClassId::Bool as u32 || class_id == ClassId::Number as u32 {
381 let value_of = get_valueof(&v);
382 if let Some(f) = value_of {
383 let v = f.call((This(v.clone()),)).map_err(Error::new)?;
384 self.de.current_kv = Some((k.clone(), v));
385 }
386 } else if class_id == ClassId::String as u32 {
387 let to_string = get_to_string(&v);
388 if let Some(f) = to_string {
389 let v = f.call((This(v.clone()),)).map_err(Error::new)?;
390 self.de.current_kv = Some((k.clone(), v));
391 }
392 } else {
393 self.de.current_kv = Some((k.clone(), v));
394 }
395 self.de.value = k;
396 self.de.map_key = true;
397
398 return seed.deserialize(&mut *self.de).map(Some);
399 } else {
400 self.pop()?;
401 return Ok(None);
402 }
403 }
404 }
405
406 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
407 where
408 V: de::DeserializeSeed<'de>,
409 {
410 self.de.value = self.de.current_kv.clone().unwrap().1;
411 self.de.check_cycles()?;
412 seed.deserialize(&mut *self.de)
413 }
414}
415
416struct SeqAccess<'a, 'de: 'a> {
418 de: &'a mut Deserializer<'de>,
420 seq: Object<'de>,
424 length: usize,
426 index: usize,
428}
429
430impl<'a, 'de: 'a> SeqAccess<'a, 'de> {
431 fn new(de: &'a mut Deserializer<'de>, seq: Object<'de>) -> Result<Self> {
434 de.stack.push(seq.clone().into_value());
435
436 let value: Value = seq.get(PredefinedAtom::Length).map_err(Error::new)?;
441 let length: usize = if let Some(n) = value.as_number() {
442 n as usize
443 } else {
444 let value_of: Function = value
445 .as_object()
446 .expect("length to be an object")
447 .get(PredefinedAtom::ValueOf)
448 .map_err(Error::new)?;
449 value_of.call(()).map_err(Error::new)?
450 };
451
452 Ok(Self {
453 de,
454 seq,
455 length,
456 index: 0,
457 })
458 }
459
460 fn pop(&mut self) -> Result<()> {
463 let v = self.de.pop_visited()?;
464 if v != self.seq.clone().into_value() {
465 return Err(Error::new(
466 "Popped a mismatched value. Expected the top level sequence value",
467 ));
468 }
469
470 Ok(())
471 }
472}
473
474impl<'de> de::SeqAccess<'de> for SeqAccess<'_, 'de> {
475 type Error = Error;
476
477 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
478 where
479 T: de::DeserializeSeed<'de>,
480 {
481 if self.index < self.length {
482 let el = get_index(&self.seq, self.index).map_err(Error::new)?;
483 let to_json = get_to_json(&el);
484
485 if let Some(f) = to_json {
486 let index_value = JSString::from_str(el.ctx().clone(), &self.index.to_string());
487 self.de.value = f
488 .call((This(el.clone()), index_value))
489 .map_err(Error::new)?;
490 } else if ensure_supported(&el)? {
491 self.de.value = el
492 } else {
493 self.de.value = Null.into_value(self.seq.ctx().clone())
494 }
495 self.index += 1;
496 self.de.check_cycles()?;
499 seed.deserialize(&mut *self.de).map(Some)
500 } else {
501 self.pop()?;
503 Ok(None)
504 }
505 }
506}
507
508pub(crate) fn get_to_json<'a>(value: &Value<'a>) -> Option<Function<'a>> {
510 get_function(value, PredefinedAtom::ToJSON)
511}
512
513fn get_valueof<'a>(value: &Value<'a>) -> Option<Function<'a>> {
515 get_function(value, PredefinedAtom::ValueOf)
516}
517
518fn get_to_string<'a>(value: &Value<'a>) -> Option<Function<'a>> {
520 get_function(value, PredefinedAtom::ToString)
521}
522
523fn get_function<'a>(value: &Value<'a>, atom: PredefinedAtom) -> Option<Function<'a>> {
524 let f = unsafe { JS_GetProperty(value.ctx().as_raw().as_ptr(), value.as_raw(), atom as u32) };
525 let f = unsafe { Value::from_raw(value.ctx().clone(), f) };
526 if f.is_function()
527 && let Some(f) = f.into_function()
528 {
529 Some(f)
530 } else {
531 None
532 }
533}
534
535fn get_class_id(v: &Value) -> u32 {
537 unsafe { JS_GetClassID(v.as_raw()) }
538}
539
540fn ensure_supported(value: &Value<'_>) -> Result<bool> {
542 let class_id = get_class_id(value);
543 if class_id == (ClassId::Bool as u32) || class_id == (ClassId::Number as u32) {
544 return Ok(true);
545 }
546
547 if class_id == ClassId::BigInt as u32 {
548 return Err(Error::new(Exception::throw_type(
549 value.ctx(),
550 "BigInt not supported",
551 )));
552 }
553
554 Ok(!matches!(
555 value.type_of(),
556 rquickjs::Type::Undefined
557 | rquickjs::Type::Symbol
558 | rquickjs::Type::Function
559 | rquickjs::Type::Uninitialized
560 | rquickjs::Type::Constructor
561 ))
562}
563
564fn is_array_or_proxy_of_array(val: &Value) -> bool {
565 if val.is_array() {
566 return true;
567 }
568 let mut val = val.clone();
569 loop {
570 let Some(proxy) = val.into_proxy() else {
571 return false;
572 };
573 let Ok(target) = proxy.target() else {
574 return false;
575 };
576 val = target.into_value();
577 if val.is_array() {
578 return true;
579 }
580 }
581}
582
583fn get_index<'a>(obj: &Object<'a>, idx: usize) -> rquickjs::Result<Value<'a>> {
584 unsafe {
585 let ctx = obj.ctx();
586 let val = JS_GetPropertyUint32(ctx.as_raw().as_ptr(), obj.as_raw(), idx as _);
587 if JS_VALUE_GET_NORM_TAG(val) == JS_TAG_EXCEPTION {
588 return Err(rquickjs::Error::Exception);
589 }
590 Ok(Value::from_raw(ctx.clone(), val))
591 }
592}
593
594struct UnitEnumAccess {
596 variant: String,
597}
598
599impl<'de> de::EnumAccess<'de> for UnitEnumAccess {
600 type Error = Error;
601 type Variant = UnitOnlyVariant;
602
603 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
604 where
605 V: de::DeserializeSeed<'de>,
606 {
607 let v = seed.deserialize(self.variant.into_deserializer())?;
608 Ok((v, UnitOnlyVariant))
609 }
610}
611
612struct UnitOnlyVariant;
613
614impl<'de> de::VariantAccess<'de> for UnitOnlyVariant {
615 type Error = Error;
616
617 fn unit_variant(self) -> Result<()> {
618 Ok(())
619 }
620
621 fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value>
622 where
623 T: de::DeserializeSeed<'de>,
624 {
625 Err(de::Error::invalid_type(
626 Unexpected::NewtypeVariant,
627 &"unit variant",
628 ))
629 }
630
631 fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
632 where
633 V: de::Visitor<'de>,
634 {
635 Err(de::Error::invalid_type(
636 Unexpected::TupleVariant,
637 &"unit variant",
638 ))
639 }
640
641 fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value>
642 where
643 V: de::Visitor<'de>,
644 {
645 Err(de::Error::invalid_type(
646 Unexpected::StructVariant,
647 &"unit variant",
648 ))
649 }
650}
651
652#[cfg(test)]
653mod tests {
654 use std::collections::BTreeMap;
655
656 use rquickjs::Value;
657 use serde::de::DeserializeOwned;
658 use serde::{Deserialize, Serialize};
659
660 use super::Deserializer as ValueDeserializer;
661 use crate::test::Runtime;
662 use crate::{MAX_SAFE_INTEGER, from_value, to_value};
663
664 fn deserialize_value<T>(v: Value<'_>) -> T
665 where
666 T: DeserializeOwned,
667 {
668 let ctx = v.ctx().clone();
669 let mut deserializer = ValueDeserializer::from(v);
670 match T::deserialize(&mut deserializer) {
671 Ok(val) => val,
672 Err(e) => panic!("{}", e.catch(&ctx)),
673 }
674 }
675
676 #[test]
677 fn test_null() {
678 let rt = Runtime::default();
679 rt.context().with(|cx| {
680 let val = Value::new_null(cx);
681 deserialize_value::<()>(val);
682 });
683 }
684
685 #[test]
686 fn test_undefined() {
687 let rt = Runtime::default();
688 rt.context().with(|cx| {
689 let val = Value::new_undefined(cx);
690 deserialize_value::<()>(val);
691 });
692 }
693
694 #[test]
695 fn test_nan() {
696 let rt = Runtime::default();
697 rt.context().with(|cx| {
698 let val = Value::new_float(cx, f64::NAN);
699 let actual = deserialize_value::<f64>(val);
700 assert!(actual.is_nan());
701 });
702 }
703
704 #[test]
705 fn test_infinity() {
706 let rt = Runtime::default();
707
708 rt.context().with(|cx| {
709 let val = Value::new_float(cx, f64::INFINITY);
710 let actual = deserialize_value::<f64>(val);
711 assert!(actual.is_infinite() && actual.is_sign_positive());
712 });
713 }
714
715 #[test]
716 fn test_negative_infinity() {
717 let rt = Runtime::default();
718 rt.context().with(|cx| {
719 let val = Value::new_float(cx, f64::NEG_INFINITY);
720 let actual = deserialize_value::<f64>(val);
721 assert!(actual.is_infinite() && actual.is_sign_negative());
722 })
723 }
724
725 #[test]
726 fn test_map_always_converts_keys_to_string() {
727 let rt = Runtime::default();
728 rt.context().with(|c| {
731 c.eval::<Value<'_>, _>("var a = {1337: 42};").unwrap();
732 let val = c.globals().get("a").unwrap();
733 let actual = deserialize_value::<BTreeMap<String, i32>>(val);
734
735 assert_eq!(42, *actual.get("1337").unwrap())
736 });
737 }
738
739 #[test]
740 fn test_u64_bounds() {
741 let rt = Runtime::default();
742 rt.context().with(|c| {
743 let max = u64::MAX;
744 let val = Value::new_number(c.clone(), max as f64);
745 let actual = deserialize_value::<f64>(val);
746 assert_eq!(max as f64, actual);
747
748 let min = u64::MIN;
749 let val = Value::new_number(c.clone(), min as f64);
750 let actual = deserialize_value::<f64>(val);
751 assert_eq!(min as f64, actual);
752 });
753 }
754
755 #[test]
756 fn test_i64_bounds() {
757 let rt = Runtime::default();
758
759 rt.context().with(|c| {
760 let max = i64::MAX;
761 let val = Value::new_number(c.clone(), max as _);
762 let actual = deserialize_value::<f64>(val);
763 assert_eq!(max as f64, actual);
764
765 let min = i64::MIN;
766 let val = Value::new_number(c.clone(), min as _);
767 let actual = deserialize_value::<f64>(val);
768 assert_eq!(min as f64, actual);
769 });
770 }
771
772 #[test]
773 fn test_float_to_integer_conversion() {
774 let rt = Runtime::default();
775
776 rt.context().with(|c| {
777 let expected = MAX_SAFE_INTEGER - 1;
778 let val = Value::new_float(c.clone(), expected as _);
779 let actual = deserialize_value::<i64>(val);
780 assert_eq!(expected, actual);
781
782 let expected = MAX_SAFE_INTEGER + 1;
783 let val = Value::new_float(c.clone(), expected as _);
784 let actual = deserialize_value::<f64>(val);
785 assert_eq!(expected as f64, actual);
786 });
787 }
788
789 #[test]
790 fn test_u32_upper_bound() {
791 let rt = Runtime::default();
792
793 rt.context().with(|c| {
794 let expected = u32::MAX;
795 let val = Value::new_number(c, expected as _);
796 let actual = deserialize_value::<u32>(val);
797 assert_eq!(expected, actual);
798 });
799 }
800
801 #[test]
802 fn test_u32_lower_bound() {
803 let rt = Runtime::default();
804
805 rt.context().with(|cx| {
806 let expected = i32::MAX as u32 + 1;
807 let val = Value::new_number(cx, expected as _);
808 let actual = deserialize_value::<u32>(val);
809 assert_eq!(expected, actual);
810 });
811 }
812
813 #[test]
814 fn test_array() {
815 let rt = Runtime::default();
816 rt.context().with(|cx| {
817 cx.eval::<Value<'_>, _>("var a = [1, 2, 3];").unwrap();
818 let v = cx.globals().get("a").unwrap();
819
820 let val = deserialize_value::<Vec<u8>>(v);
821
822 assert_eq!(vec![1, 2, 3], val);
823 });
824 }
825
826 #[test]
827 fn test_array_proxy() {
828 let rt = Runtime::default();
829 rt.context().with(|cx| {
830 cx.eval::<Value<'_>, _>(
831 r#"
832 var arr = [1, 2, 3];
833 var a = new Proxy(arr, {});
834 "#,
835 )
836 .unwrap();
837 let v = cx.globals().get("a").unwrap();
838 let val = deserialize_value::<Vec<u8>>(v);
839 assert_eq!(vec![1, 2, 3], val);
840 });
841 }
842
843 #[test]
844 fn test_non_json_object_values_are_dropped() {
845 let rt = Runtime::default();
846 rt.context().with(|cx| {
847 cx.eval::<Value<'_>, _>(
848 r#"
849 var unitialized;
850 var a = {
851 a: undefined,
852 b: function() {},
853 c: Symbol(),
854 d: () => {},
855 e: unitialized,
856 };"#,
857 )
858 .unwrap();
859 let v = cx.globals().get("a").unwrap();
860
861 let val = deserialize_value::<BTreeMap<String, ()>>(v);
862 assert_eq!(BTreeMap::new(), val);
863 });
864 }
865
866 #[test]
867 fn test_non_json_array_values_are_null() {
868 let rt = Runtime::default();
869 rt.context().with(|cx| {
870 cx.eval::<Value<'_>, _>(
871 r#"
872 var unitialized;
873 var a = [
874 undefined,
875 function() {},
876 Symbol(),
877 () => {},
878 unitialized,
879 ];"#,
880 )
881 .unwrap();
882 let v = cx.globals().get("a").unwrap();
883
884 let val = deserialize_value::<Vec<Option<()>>>(v);
885 assert_eq!(vec![None; 5], val);
886 });
887 }
888
889 #[test]
890 fn test_enum() {
891 let rt = Runtime::default();
892
893 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
894 enum Test {
895 One,
896 Two,
897 Three,
898 }
899
900 rt.context().with(|cx| {
901 let left = Test::Two;
902 let value = to_value(cx, left).unwrap();
903 let right: Test = from_value(value).unwrap();
904 assert_eq!(left, right);
905 });
906 }
907
908 #[test]
909 fn test_short_bigint() {
910 let rt = Runtime::default();
911 rt.context().with(|cx| {
912 cx.eval::<Value<'_>, _>("var a = BigInt(1);").unwrap();
913 let v = cx.globals().get("a").unwrap();
914 let val = deserialize_value::<String>(v);
915 assert_eq!(val, "1");
916 });
917 }
918
919 #[test]
920 fn test_bigint() {
921 let rt = Runtime::default();
922 rt.context().with(|cx| {
923 cx.eval::<Value<'_>, _>(
924 r#"
925 const left = 12345678901234567890n;
926 const right = 98765432109876543210n;
927 var a = left * right;
928 "#,
929 )
930 .unwrap();
931 let v = cx.globals().get("a").unwrap();
932 let val = deserialize_value::<String>(v);
933 assert_eq!(val, "1219326311370217952237463801111263526900");
934 });
935 }
936}