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