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