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 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 ctx = val.ctx().clone();
566 let mut val = val.clone();
567 loop {
568 let is_proxy = unsafe { JS_IsProxy(val.as_raw()) };
569 if !is_proxy {
570 return false;
571 }
572 val = unsafe {
573 let target = JS_GetProxyTarget(ctx.as_raw().as_ptr(), val.as_raw());
574 Value::from_raw(ctx.clone(), target)
575 };
576 if unsafe { JS_IsArray(val.as_raw()) } {
577 return true;
578 }
579 }
580}
581
582fn get_index<'a>(obj: &Object<'a>, idx: usize) -> rquickjs::Result<Value<'a>> {
583 unsafe {
584 let ctx = obj.ctx();
585 let val = JS_GetPropertyUint32(ctx.as_raw().as_ptr(), obj.as_raw(), idx as _);
586 if JS_VALUE_GET_NORM_TAG(val) == JS_TAG_EXCEPTION {
587 return Err(rquickjs::Error::Exception);
588 }
589 Ok(Value::from_raw(ctx.clone(), val))
590 }
591}
592
593struct UnitEnumAccess {
595 variant: String,
596}
597
598impl<'de> de::EnumAccess<'de> for UnitEnumAccess {
599 type Error = Error;
600 type Variant = UnitOnlyVariant;
601
602 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
603 where
604 V: de::DeserializeSeed<'de>,
605 {
606 let v = seed.deserialize(self.variant.into_deserializer())?;
607 Ok((v, UnitOnlyVariant))
608 }
609}
610
611struct UnitOnlyVariant;
612
613impl<'de> de::VariantAccess<'de> for UnitOnlyVariant {
614 type Error = Error;
615
616 fn unit_variant(self) -> Result<()> {
617 Ok(())
618 }
619
620 fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value>
621 where
622 T: de::DeserializeSeed<'de>,
623 {
624 Err(de::Error::invalid_type(
625 Unexpected::NewtypeVariant,
626 &"unit variant",
627 ))
628 }
629
630 fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
631 where
632 V: de::Visitor<'de>,
633 {
634 Err(de::Error::invalid_type(
635 Unexpected::TupleVariant,
636 &"unit variant",
637 ))
638 }
639
640 fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value>
641 where
642 V: de::Visitor<'de>,
643 {
644 Err(de::Error::invalid_type(
645 Unexpected::StructVariant,
646 &"unit variant",
647 ))
648 }
649}
650
651#[cfg(test)]
652mod tests {
653 use std::collections::BTreeMap;
654
655 use rquickjs::Value;
656 use serde::de::DeserializeOwned;
657 use serde::{Deserialize, Serialize};
658
659 use super::Deserializer as ValueDeserializer;
660 use crate::test::Runtime;
661 use crate::{MAX_SAFE_INTEGER, from_value, to_value};
662
663 fn deserialize_value<T>(v: Value<'_>) -> T
664 where
665 T: DeserializeOwned,
666 {
667 let ctx = v.ctx().clone();
668 let mut deserializer = ValueDeserializer::from(v);
669 match T::deserialize(&mut deserializer) {
670 Ok(val) => val,
671 Err(e) => panic!("{}", e.catch(&ctx)),
672 }
673 }
674
675 #[test]
676 fn test_null() {
677 let rt = Runtime::default();
678 rt.context().with(|cx| {
679 let val = Value::new_null(cx);
680 deserialize_value::<()>(val);
681 });
682 }
683
684 #[test]
685 fn test_undefined() {
686 let rt = Runtime::default();
687 rt.context().with(|cx| {
688 let val = Value::new_undefined(cx);
689 deserialize_value::<()>(val);
690 });
691 }
692
693 #[test]
694 fn test_nan() {
695 let rt = Runtime::default();
696 rt.context().with(|cx| {
697 let val = Value::new_float(cx, f64::NAN);
698 let actual = deserialize_value::<f64>(val);
699 assert!(actual.is_nan());
700 });
701 }
702
703 #[test]
704 fn test_infinity() {
705 let rt = Runtime::default();
706
707 rt.context().with(|cx| {
708 let val = Value::new_float(cx, f64::INFINITY);
709 let actual = deserialize_value::<f64>(val);
710 assert!(actual.is_infinite() && actual.is_sign_positive());
711 });
712 }
713
714 #[test]
715 fn test_negative_infinity() {
716 let rt = Runtime::default();
717 rt.context().with(|cx| {
718 let val = Value::new_float(cx, f64::NEG_INFINITY);
719 let actual = deserialize_value::<f64>(val);
720 assert!(actual.is_infinite() && actual.is_sign_negative());
721 })
722 }
723
724 #[test]
725 fn test_map_always_converts_keys_to_string() {
726 let rt = Runtime::default();
727 rt.context().with(|c| {
730 c.eval::<Value<'_>, _>("var a = {1337: 42};").unwrap();
731 let val = c.globals().get("a").unwrap();
732 let actual = deserialize_value::<BTreeMap<String, i32>>(val);
733
734 assert_eq!(42, *actual.get("1337").unwrap())
735 });
736 }
737
738 #[test]
739 fn test_u64_bounds() {
740 let rt = Runtime::default();
741 rt.context().with(|c| {
742 let max = u64::MAX;
743 let val = Value::new_number(c.clone(), max as f64);
744 let actual = deserialize_value::<f64>(val);
745 assert_eq!(max as f64, actual);
746
747 let min = u64::MIN;
748 let val = Value::new_number(c.clone(), min as f64);
749 let actual = deserialize_value::<f64>(val);
750 assert_eq!(min as f64, actual);
751 });
752 }
753
754 #[test]
755 fn test_i64_bounds() {
756 let rt = Runtime::default();
757
758 rt.context().with(|c| {
759 let max = i64::MAX;
760 let val = Value::new_number(c.clone(), max as _);
761 let actual = deserialize_value::<f64>(val);
762 assert_eq!(max as f64, actual);
763
764 let min = i64::MIN;
765 let val = Value::new_number(c.clone(), min as _);
766 let actual = deserialize_value::<f64>(val);
767 assert_eq!(min as f64, actual);
768 });
769 }
770
771 #[test]
772 fn test_float_to_integer_conversion() {
773 let rt = Runtime::default();
774
775 rt.context().with(|c| {
776 let expected = MAX_SAFE_INTEGER - 1;
777 let val = Value::new_float(c.clone(), expected as _);
778 let actual = deserialize_value::<i64>(val);
779 assert_eq!(expected, actual);
780
781 let expected = MAX_SAFE_INTEGER + 1;
782 let val = Value::new_float(c.clone(), expected as _);
783 let actual = deserialize_value::<f64>(val);
784 assert_eq!(expected as f64, actual);
785 });
786 }
787
788 #[test]
789 fn test_u32_upper_bound() {
790 let rt = Runtime::default();
791
792 rt.context().with(|c| {
793 let expected = u32::MAX;
794 let val = Value::new_number(c, expected as _);
795 let actual = deserialize_value::<u32>(val);
796 assert_eq!(expected, actual);
797 });
798 }
799
800 #[test]
801 fn test_u32_lower_bound() {
802 let rt = Runtime::default();
803
804 rt.context().with(|cx| {
805 let expected = i32::MAX as u32 + 1;
806 let val = Value::new_number(cx, expected as _);
807 let actual = deserialize_value::<u32>(val);
808 assert_eq!(expected, actual);
809 });
810 }
811
812 #[test]
813 fn test_array() {
814 let rt = Runtime::default();
815 rt.context().with(|cx| {
816 cx.eval::<Value<'_>, _>("var a = [1, 2, 3];").unwrap();
817 let v = cx.globals().get("a").unwrap();
818
819 let val = deserialize_value::<Vec<u8>>(v);
820
821 assert_eq!(vec![1, 2, 3], val);
822 });
823 }
824
825 #[test]
826 fn test_array_proxy() {
827 let rt = Runtime::default();
828 rt.context().with(|cx| {
829 cx.eval::<Value<'_>, _>(
830 r#"
831 var arr = [1, 2, 3];
832 var a = new Proxy(arr, {});
833 "#,
834 )
835 .unwrap();
836 let v = cx.globals().get("a").unwrap();
837 let val = deserialize_value::<Vec<u8>>(v);
838 assert_eq!(vec![1, 2, 3], val);
839 });
840 }
841
842 #[test]
843 fn test_non_json_object_values_are_dropped() {
844 let rt = Runtime::default();
845 rt.context().with(|cx| {
846 cx.eval::<Value<'_>, _>(
847 r#"
848 var unitialized;
849 var a = {
850 a: undefined,
851 b: function() {},
852 c: Symbol(),
853 d: () => {},
854 e: unitialized,
855 };"#,
856 )
857 .unwrap();
858 let v = cx.globals().get("a").unwrap();
859
860 let val = deserialize_value::<BTreeMap<String, ()>>(v);
861 assert_eq!(BTreeMap::new(), val);
862 });
863 }
864
865 #[test]
866 fn test_non_json_array_values_are_null() {
867 let rt = Runtime::default();
868 rt.context().with(|cx| {
869 cx.eval::<Value<'_>, _>(
870 r#"
871 var unitialized;
872 var a = [
873 undefined,
874 function() {},
875 Symbol(),
876 () => {},
877 unitialized,
878 ];"#,
879 )
880 .unwrap();
881 let v = cx.globals().get("a").unwrap();
882
883 let val = deserialize_value::<Vec<Option<()>>>(v);
884 assert_eq!(vec![None; 5], val);
885 });
886 }
887
888 #[test]
889 fn test_enum() {
890 let rt = Runtime::default();
891
892 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
893 enum Test {
894 One,
895 Two,
896 Three,
897 }
898
899 rt.context().with(|cx| {
900 let left = Test::Two;
901 let value = to_value(cx, left).unwrap();
902 let right: Test = from_value(value).unwrap();
903 assert_eq!(left, right);
904 });
905 }
906
907 #[test]
908 fn test_short_bigint() {
909 let rt = Runtime::default();
910 rt.context().with(|cx| {
911 cx.eval::<Value<'_>, _>("var a = BigInt(1);").unwrap();
912 let v = cx.globals().get("a").unwrap();
913 let val = deserialize_value::<String>(v);
914 assert_eq!(val, "1");
915 });
916 }
917
918 #[test]
919 fn test_bigint() {
920 let rt = Runtime::default();
921 rt.context().with(|cx| {
922 cx.eval::<Value<'_>, _>(
923 r#"
924 const left = 12345678901234567890n;
925 const right = 98765432109876543210n;
926 var a = left * right;
927 "#,
928 )
929 .unwrap();
930 let v = cx.globals().get("a").unwrap();
931 let val = deserialize_value::<String>(v);
932 assert_eq!(val, "1219326311370217952237463801111263526900");
933 });
934 }
935}