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},
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
23#[derive(Debug, Copy, Clone)]
27enum ClassId {
28 Number = 4,
29 String = 5,
30 Bool = 6,
31 BigInt = 35,
32}
33
34impl PartialEq<ClassId> for u32 {
35 fn eq(&self, other: &ClassId) -> bool {
36 *self == *other as u32
37 }
38}
39
40pub struct Deserializer<'js> {
61 value: Value<'js>,
62 strict: bool,
64 map_key: bool,
65 current_kv: Option<(Value<'js>, Value<'js>)>,
66 stack: Vec<Value<'js>>,
68}
69
70impl<'js> Deserializer<'js> {
71 pub fn new(value: Value<'js>) -> Self {
72 Self::from(value)
73 }
74
75 pub fn with_strict(self) -> Self {
76 Self {
77 strict: true,
78 ..self
79 }
80 }
81}
82
83impl<'de> From<Value<'de>> for Deserializer<'de> {
84 fn from(value: Value<'de>) -> Self {
85 Self {
86 value,
87 strict: false,
88 map_key: false,
89 current_kv: None,
90 stack: Vec::with_capacity(100),
93 }
94 }
95}
96
97impl<'js> Deserializer<'js> {
98 fn deserialize_number<'de, V>(&mut self, visitor: V) -> Result<V::Value>
99 where
100 V: de::Visitor<'de>,
101 {
102 if let Some(i) = self.value.as_int() {
103 return visitor.visit_i32(i);
104 }
105
106 if let Some(f64_representation) = self.value.as_float() {
107 let is_positive = f64_representation.is_sign_positive();
108 let safe_integer_range = (MIN_SAFE_INTEGER as f64)..=(MAX_SAFE_INTEGER as f64);
109 let whole = (f64_representation % 1.0) == 0.0;
110
111 if whole && is_positive && f64_representation <= u32::MAX as f64 {
112 return visitor.visit_u32(f64_representation as u32);
113 }
114
115 if whole && safe_integer_range.contains(&f64_representation) {
116 let x = f64_representation as i64;
117 return visitor.visit_i64(x);
118 }
119
120 return visitor.visit_f64(f64_representation);
121 }
122
123 Err(Error::new(Exception::throw_type(
124 self.value.ctx(),
125 "Unsupported number type",
126 )))
127 }
128
129 fn pop_visited(&mut self) -> Result<Value<'js>> {
131 let v = self
132 .stack
133 .pop()
134 .ok_or_else(|| Error::new("No entries found in the deserializer stack"))?;
135 Ok(v)
136 }
137
138 fn check_cycles(&self) -> Result<()> {
142 for val in self.stack.iter().rev() {
143 if self.value.eq(val) {
144 return Err(Error::new(Exception::throw_type(
145 val.ctx(),
146 "circular dependency",
147 )));
148 }
149 }
150 Ok(())
151 }
152}
153
154impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> {
155 type Error = Error;
156
157 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
158 where
159 V: de::Visitor<'de>,
160 {
161 if self.value.is_number() {
162 return self.deserialize_number(visitor);
163 }
164
165 if get_class_id(&self.value) == ClassId::Number {
166 let value_of = get_valueof(&self.value);
167 if let Some(f) = value_of {
168 let v = f.call((This(self.value.clone()),)).map_err(Error::new)?;
169 self.value = v;
170 return self.deserialize_number(visitor);
171 }
172 }
173
174 if let Some(b) = self.value.as_bool() {
175 return visitor.visit_bool(b);
176 }
177
178 if get_class_id(&self.value) == ClassId::Bool {
179 let value_of = get_valueof(&self.value);
180 if let Some(f) = value_of {
181 let v = f.call((This(self.value.clone()),)).map_err(Error::new)?;
182 return visitor.visit_bool(v);
183 }
184 }
185
186 if self.value.is_null() || self.value.is_undefined() {
187 return visitor.visit_unit();
188 }
189
190 if get_class_id(&self.value) == ClassId::String {
191 let to_string = get_to_string(&self.value);
192 if let Some(f) = to_string {
193 let v = f.call(((This(self.value.clone())),)).map_err(Error::new)?;
194 self.value = v;
195 }
196 }
197
198 if self.value.is_string() {
199 if self.map_key {
200 self.map_key = false;
201 let key = as_key(&self.value)?;
202 return visitor.visit_str(&key);
203 } else {
204 let val = self
205 .value
206 .as_string()
207 .map(|s| {
208 s.to_string()
209 .unwrap_or_else(|e| to_string_lossy(self.value.ctx(), s, e))
210 })
211 .unwrap();
212 return visitor.visit_str(&val);
213 }
214 }
215
216 if is_array_or_proxy_of_array(&self.value)
217 && let Some(seq) = self.value.as_object()
218 {
219 let seq_access = SeqAccess::new(self, seq.clone())?;
220 return visitor.visit_seq(seq_access);
221 }
222
223 if get_class_id(&self.value) == ClassId::BigInt || self.value.is_big_int() {
224 if let Some(f) = get_to_json(&self.value) {
225 let v: Value = f.call((This(self.value.clone()),)).map_err(Error::new)?;
226 self.value = v;
227 return self.deserialize_any(visitor);
228 }
229
230 if let Some(f) = get_to_string(&self.value)
231 && !self.strict
232 {
233 let v: Value = f.call((This(self.value.clone()),)).map_err(Error::new)?;
234 self.value = v;
235 return self.deserialize_any(visitor);
236 }
237 }
238
239 if self.value.is_object() {
240 ensure_supported(&self.value)?;
241
242 if let Some(f) = get_to_json(&self.value) {
243 let v: Value = f.call((This(self.value.clone()),)).map_err(Error::new)?;
244
245 if v.is_undefined() {
246 self.value = Value::new_undefined(v.ctx().clone());
247 } else {
248 self.value = v;
249 }
250 return self.deserialize_any(visitor);
251 }
252
253 let map_access = MapAccess::new(self, self.value.clone().into_object().unwrap())?;
254 let result = visitor.visit_map(map_access);
255 return result;
256 }
257
258 Err(Error::new(Exception::throw_type(
259 self.value.ctx(),
260 "Unsupported type",
261 )))
262 }
263
264 fn is_human_readable(&self) -> bool {
265 false
266 }
267
268 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
269 where
270 V: de::Visitor<'de>,
271 {
272 if self.value.is_null() || self.value.is_undefined() {
273 visitor.visit_none()
274 } else {
275 visitor.visit_some(self)
276 }
277 }
278
279 fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
280 where
281 V: de::Visitor<'de>,
282 {
283 visitor.visit_newtype_struct(self)
284 }
285
286 fn deserialize_enum<V>(
287 self,
288 _name: &'static str,
289 _variants: &'static [&'static str],
290 visitor: V,
291 ) -> Result<V::Value>
292 where
293 V: de::Visitor<'de>,
294 {
295 if get_class_id(&self.value) == ClassId::String
296 && let Some(f) = get_to_string(&self.value)
297 {
298 let v = f.call((This(self.value.clone()),)).map_err(Error::new)?;
299 self.value = v;
300 }
301
302 if let Some(obj) = self.value.as_object() {
303 let (variant, value): (String, Value<'de>) = obj
304 .props::<String, Value>()
305 .next()
306 .ok_or_else(|| Error::new("expected enum object with one key"))?
307 .map_err(Error::new)?;
308
309 visitor.visit_enum(EnumAccessImpl {
310 variant,
311 value: Some(value.clone()),
312 })
313 } else if let Some(s) = self.value.as_string() {
314 let s = s
316 .to_string()
317 .unwrap_or_else(|e| to_string_lossy(self.value.ctx(), s, e));
318
319 visitor.visit_enum(EnumAccessImpl {
320 variant: s,
321 value: None,
322 })
323 } else {
324 Err(Error::new("expected a string or object for enum"))
325 }
326 }
327
328 forward_to_deserialize_any! {
329 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
330 bytes byte_buf unit unit_struct seq tuple
331 tuple_struct map struct identifier ignored_any
332 }
333}
334
335struct MapAccess<'a, 'de: 'a> {
337 de: &'a mut Deserializer<'de>,
339 properties: ObjectIter<'de, Value<'de>, Value<'de>>,
341 obj: Object<'de>,
343}
344
345impl<'a, 'de> MapAccess<'a, 'de> {
346 fn new(de: &'a mut Deserializer<'de>, obj: Object<'de>) -> Result<Self> {
347 let filter = Filter::new().enum_only().string();
348 let properties: ObjectIter<'_, _, Value<'_>> =
349 obj.own_props::<Value<'_>, Value<'_>>(filter);
350
351 let val = obj.clone().into_value();
352 de.stack.push(val.clone());
353
354 Ok(Self {
355 de,
356 properties,
357 obj,
358 })
359 }
360
361 fn pop(&mut self) -> Result<()> {
364 let v = self.de.pop_visited()?;
365 if v != self.obj.clone().into_value() {
366 return Err(Error::new(
367 "Popped a mismatched value. Expected the top level sequence value",
368 ));
369 }
370
371 Ok(())
372 }
373}
374
375impl<'de> de::MapAccess<'de> for MapAccess<'_, 'de> {
376 type Error = Error;
377
378 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
379 where
380 K: de::DeserializeSeed<'de>,
381 {
382 loop {
383 if let Some(kv) = self.properties.next() {
384 let (k, v) = kv.map_err(Error::new)?;
385
386 let to_json = get_to_json(&v);
387 let v = if let Some(f) = to_json {
388 f.call((This(v.clone()), k.clone())).map_err(Error::new)?
389 } else {
390 v
391 };
392
393 if !ensure_supported(&v)? || k.is_symbol() {
396 continue;
397 }
398
399 let class_id = get_class_id(&v);
400
401 if class_id == ClassId::Bool || class_id == ClassId::Number {
402 let value_of = get_valueof(&v);
403 if let Some(f) = value_of {
404 let v = f.call((This(v.clone()),)).map_err(Error::new)?;
405 self.de.current_kv = Some((k.clone(), v));
406 }
407 } else if class_id == ClassId::String {
408 let to_string = get_to_string(&v);
409 if let Some(f) = to_string {
410 let v = f.call((This(v.clone()),)).map_err(Error::new)?;
411 self.de.current_kv = Some((k.clone(), v));
412 }
413 } else {
414 self.de.current_kv = Some((k.clone(), v));
415 }
416 self.de.value = k;
417 self.de.map_key = true;
418
419 return seed.deserialize(&mut *self.de).map(Some);
420 } else {
421 self.pop()?;
422 return Ok(None);
423 }
424 }
425 }
426
427 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
428 where
429 V: de::DeserializeSeed<'de>,
430 {
431 self.de.value = self.de.current_kv.clone().unwrap().1;
432 self.de.check_cycles()?;
433 seed.deserialize(&mut *self.de)
434 }
435}
436
437struct SeqAccess<'a, 'de: 'a> {
439 de: &'a mut Deserializer<'de>,
441 seq: Object<'de>,
445 length: usize,
447 index: usize,
449}
450
451impl<'a, 'de: 'a> SeqAccess<'a, 'de> {
452 fn new(de: &'a mut Deserializer<'de>, seq: Object<'de>) -> Result<Self> {
455 de.stack.push(seq.clone().into_value());
456
457 let value: Value = seq.get(PredefinedAtom::Length).map_err(Error::new)?;
462 let length: usize = if let Some(n) = value.as_number() {
463 n as usize
464 } else {
465 let value_of: Function = value
466 .as_object()
467 .expect("length to be an object")
468 .get(PredefinedAtom::ValueOf)
469 .map_err(Error::new)?;
470 value_of.call(()).map_err(Error::new)?
471 };
472
473 Ok(Self {
474 de,
475 seq,
476 length,
477 index: 0,
478 })
479 }
480
481 fn pop(&mut self) -> Result<()> {
484 let v = self.de.pop_visited()?;
485 if v != self.seq.clone().into_value() {
486 return Err(Error::new(
487 "Popped a mismatched value. Expected the top level sequence value",
488 ));
489 }
490
491 Ok(())
492 }
493}
494
495impl<'de> de::SeqAccess<'de> for SeqAccess<'_, 'de> {
496 type Error = Error;
497
498 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
499 where
500 T: de::DeserializeSeed<'de>,
501 {
502 if self.index < self.length {
503 let el = get_index(&self.seq, self.index).map_err(Error::new)?;
504 let to_json = get_to_json(&el);
505
506 if let Some(f) = to_json {
507 let index_value = JSString::from_str(el.ctx().clone(), &self.index.to_string());
508 self.de.value = f
509 .call((This(el.clone()), index_value))
510 .map_err(Error::new)?;
511 } else if ensure_supported(&el)? {
512 self.de.value = el
513 } else {
514 self.de.value = Null.into_value(self.seq.ctx().clone())
515 }
516 self.index += 1;
517 self.de.check_cycles()?;
520 seed.deserialize(&mut *self.de).map(Some)
521 } else {
522 self.pop()?;
524 Ok(None)
525 }
526 }
527}
528
529pub(crate) fn get_to_json<'a>(value: &Value<'a>) -> Option<Function<'a>> {
531 get_function(value, PredefinedAtom::ToJSON)
532}
533
534fn get_valueof<'a>(value: &Value<'a>) -> Option<Function<'a>> {
536 get_function(value, PredefinedAtom::ValueOf)
537}
538
539fn get_to_string<'a>(value: &Value<'a>) -> Option<Function<'a>> {
541 get_function(value, PredefinedAtom::ToString)
542}
543
544fn get_function<'a>(value: &Value<'a>, atom: PredefinedAtom) -> Option<Function<'a>> {
545 let f = unsafe { JS_GetProperty(value.ctx().as_raw().as_ptr(), value.as_raw(), atom as u32) };
546 let f = unsafe { Value::from_raw(value.ctx().clone(), f) };
547 if f.is_function()
548 && let Some(f) = f.into_function()
549 {
550 Some(f)
551 } else {
552 None
553 }
554}
555
556fn get_class_id(v: &Value) -> u32 {
558 unsafe { JS_GetClassID(v.as_raw()) }
559}
560
561fn ensure_supported(value: &Value<'_>) -> Result<bool> {
563 let class_id = get_class_id(value);
564 if class_id == ClassId::Bool || class_id == ClassId::Number {
565 return Ok(true);
566 }
567
568 if class_id == ClassId::BigInt {
569 return Err(Error::new(Exception::throw_type(
570 value.ctx(),
571 "BigInt not supported",
572 )));
573 }
574
575 Ok(!matches!(
576 value.type_of(),
577 rquickjs::Type::Undefined
578 | rquickjs::Type::Symbol
579 | rquickjs::Type::Function
580 | rquickjs::Type::Uninitialized
581 | rquickjs::Type::Constructor
582 ))
583}
584
585fn is_array_or_proxy_of_array(val: &Value) -> bool {
586 if val.is_array() {
587 return true;
588 }
589 let mut val = val.clone();
590 loop {
591 let Some(proxy) = val.into_proxy() else {
592 return false;
593 };
594 let Ok(target) = proxy.target() else {
595 return false;
596 };
597 val = target.into_value();
598 if val.is_array() {
599 return true;
600 }
601 }
602}
603
604fn get_index<'a>(obj: &Object<'a>, idx: usize) -> rquickjs::Result<Value<'a>> {
605 unsafe {
606 let ctx = obj.ctx();
607 let val = JS_GetPropertyUint32(ctx.as_raw().as_ptr(), obj.as_raw(), idx as _);
608 if JS_VALUE_GET_NORM_TAG(val) == JS_TAG_EXCEPTION {
609 return Err(rquickjs::Error::Exception);
610 }
611 Ok(Value::from_raw(ctx.clone(), val))
612 }
613}
614
615struct EnumAccessImpl<'de> {
617 variant: String,
619 value: Option<Value<'de>>,
621}
622
623impl<'de> de::EnumAccess<'de> for EnumAccessImpl<'de> {
624 type Error = Error;
625 type Variant = VariantAccessImpl<'de>;
626
627 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
628 where
629 V: de::DeserializeSeed<'de>,
630 {
631 let val = seed.deserialize(self.variant.into_deserializer())?;
632 Ok((val, VariantAccessImpl { value: self.value }))
633 }
634}
635
636struct VariantAccessImpl<'de> {
637 value: Option<Value<'de>>,
638}
639
640impl<'de> de::VariantAccess<'de> for VariantAccessImpl<'de> {
641 type Error = Error;
642
643 fn unit_variant(self) -> Result<()> {
644 match self.value {
645 None => Ok(()),
646 Some(_) => Err(Error::new("expected unit variant")),
647 }
648 }
649
650 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
651 where
652 T: de::DeserializeSeed<'de>,
653 {
654 let value = self
655 .value
656 .ok_or_else(|| Error::new("expected value for newtype variant"))?;
657
658 seed.deserialize(&mut Deserializer::from(value))
659 }
660
661 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
662 where
663 V: de::Visitor<'de>,
664 {
665 let value = self
666 .value
667 .ok_or_else(|| Error::new("expected tuple variant"))?;
668
669 de::Deserializer::deserialize_seq(&mut Deserializer::from(value), visitor)
670 }
671
672 fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
673 where
674 V: de::Visitor<'de>,
675 {
676 let value = self
677 .value
678 .ok_or_else(|| Error::new("expected struct variant"))?;
679
680 de::Deserializer::deserialize_map(&mut Deserializer::from(value), visitor)
681 }
682}
683
684#[cfg(test)]
685mod tests {
686 use std::collections::BTreeMap;
687
688 use rquickjs::Value;
689 use serde::de::DeserializeOwned;
690 use serde::{Deserialize, Serialize};
691
692 use super::{ClassId, Deserializer as ValueDeserializer, get_class_id};
693 use crate::test::Runtime;
694 use crate::{MAX_SAFE_INTEGER, from_value, to_value};
695
696 fn deserialize_value<T>(v: Value<'_>) -> T
697 where
698 T: DeserializeOwned,
699 {
700 let ctx = v.ctx().clone();
701 let mut deserializer = ValueDeserializer::from(v);
702 match T::deserialize(&mut deserializer) {
703 Ok(val) => val,
704 Err(e) => panic!("{}", e.catch(&ctx)),
705 }
706 }
707
708 #[test]
709 fn test_null() {
710 let rt = Runtime::default();
711 rt.context().with(|cx| {
712 let val = Value::new_null(cx);
713 deserialize_value::<()>(val);
714 });
715 }
716
717 #[test]
718 fn test_undefined() {
719 let rt = Runtime::default();
720 rt.context().with(|cx| {
721 let val = Value::new_undefined(cx);
722 deserialize_value::<()>(val);
723 });
724 }
725
726 #[test]
727 fn test_boxed_boolean() {
728 let rt = Runtime::default();
729 rt.context().with(|cx| {
730 cx.eval::<Value<'_>, _>("var a = new Boolean(true);")
731 .unwrap();
732 let v = cx.globals().get("a").unwrap();
733 assert!(deserialize_value::<bool>(v));
734
735 cx.eval::<Value<'_>, _>("var b = new Boolean(false);")
736 .unwrap();
737 let v = cx.globals().get("b").unwrap();
738 assert!(!deserialize_value::<bool>(v));
739 });
740 }
741
742 #[test]
743 fn test_boxed_number() {
744 let rt = Runtime::default();
745 rt.context().with(|cx| {
746 cx.eval::<Value<'_>, _>("var a = new Number(42);").unwrap();
747 let v = cx.globals().get("a").unwrap();
748 assert_eq!(42, deserialize_value::<i32>(v));
749
750 cx.eval::<Value<'_>, _>("var b = new Number(1.5);").unwrap();
751 let v = cx.globals().get("b").unwrap();
752 assert_eq!(1.5, deserialize_value::<f64>(v));
753 });
754 }
755
756 #[test]
757 fn test_boxed_string() {
758 let rt = Runtime::default();
759 rt.context().with(|cx| {
760 cx.eval::<Value<'_>, _>("var a = new String('hello');")
761 .unwrap();
762 let v = cx.globals().get("a").unwrap();
763 assert_eq!("hello", deserialize_value::<String>(v));
764 });
765 }
766
767 #[test]
768 fn test_nan() {
769 let rt = Runtime::default();
770 rt.context().with(|cx| {
771 let val = Value::new_float(cx, f64::NAN);
772 let actual = deserialize_value::<f64>(val);
773 assert!(actual.is_nan());
774 });
775 }
776
777 #[test]
778 fn test_infinity() {
779 let rt = Runtime::default();
780
781 rt.context().with(|cx| {
782 let val = Value::new_float(cx, f64::INFINITY);
783 let actual = deserialize_value::<f64>(val);
784 assert!(actual.is_infinite() && actual.is_sign_positive());
785 });
786 }
787
788 #[test]
789 fn test_negative_infinity() {
790 let rt = Runtime::default();
791 rt.context().with(|cx| {
792 let val = Value::new_float(cx, f64::NEG_INFINITY);
793 let actual = deserialize_value::<f64>(val);
794 assert!(actual.is_infinite() && actual.is_sign_negative());
795 })
796 }
797
798 #[test]
799 fn test_map_always_converts_keys_to_string() {
800 let rt = Runtime::default();
801 rt.context().with(|c| {
804 c.eval::<Value<'_>, _>("var a = {1337: 42};").unwrap();
805 let val = c.globals().get("a").unwrap();
806 let actual = deserialize_value::<BTreeMap<String, i32>>(val);
807
808 assert_eq!(42, *actual.get("1337").unwrap())
809 });
810 }
811
812 #[test]
813 fn test_map_with_boxed_primitives() {
814 #[derive(Debug, Deserialize, PartialEq)]
815 struct Boxed {
816 b: bool,
817 n: i32,
818 s: String,
819 }
820
821 let rt = Runtime::default();
822 rt.context().with(|cx| {
823 cx.eval::<Value<'_>, _>(
824 r#"
825 var a = {
826 b: new Boolean(true),
827 n: new Number(42),
828 s: new String("hello"),
829 };
830 "#,
831 )
832 .unwrap();
833 let v = cx.globals().get("a").unwrap();
834 assert_eq!(
835 Boxed {
836 b: true,
837 n: 42,
838 s: "hello".to_string(),
839 },
840 deserialize_value::<Boxed>(v)
841 );
842 });
843 }
844
845 #[test]
846 fn test_u64_bounds() {
847 let rt = Runtime::default();
848 rt.context().with(|c| {
849 let max = u64::MAX;
850 let val = Value::new_number(c.clone(), max as f64);
851 let actual = deserialize_value::<f64>(val);
852 assert_eq!(max as f64, actual);
853
854 let min = u64::MIN;
855 let val = Value::new_number(c.clone(), min as f64);
856 let actual = deserialize_value::<f64>(val);
857 assert_eq!(min as f64, actual);
858 });
859 }
860
861 #[test]
862 fn test_i64_bounds() {
863 let rt = Runtime::default();
864
865 rt.context().with(|c| {
866 let max = i64::MAX;
867 let val = Value::new_number(c.clone(), max as _);
868 let actual = deserialize_value::<f64>(val);
869 assert_eq!(max as f64, actual);
870
871 let min = i64::MIN;
872 let val = Value::new_number(c.clone(), min as _);
873 let actual = deserialize_value::<f64>(val);
874 assert_eq!(min as f64, actual);
875 });
876 }
877
878 #[test]
879 fn test_float_to_integer_conversion() {
880 let rt = Runtime::default();
881
882 rt.context().with(|c| {
883 let expected = MAX_SAFE_INTEGER - 1;
884 let val = Value::new_float(c.clone(), expected as _);
885 let actual = deserialize_value::<i64>(val);
886 assert_eq!(expected, actual);
887
888 let expected = MAX_SAFE_INTEGER + 1;
889 let val = Value::new_float(c.clone(), expected as _);
890 let actual = deserialize_value::<f64>(val);
891 assert_eq!(expected as f64, actual);
892 });
893 }
894
895 #[test]
896 fn test_u32_upper_bound() {
897 let rt = Runtime::default();
898
899 rt.context().with(|c| {
900 let expected = u32::MAX;
901 let val = Value::new_number(c, expected as _);
902 let actual = deserialize_value::<u32>(val);
903 assert_eq!(expected, actual);
904 });
905 }
906
907 #[test]
908 fn test_u32_lower_bound() {
909 let rt = Runtime::default();
910
911 rt.context().with(|cx| {
912 let expected = i32::MAX as u32 + 1;
913 let val = Value::new_number(cx, expected as _);
914 let actual = deserialize_value::<u32>(val);
915 assert_eq!(expected, actual);
916 });
917 }
918
919 #[test]
920 fn test_array() {
921 let rt = Runtime::default();
922 rt.context().with(|cx| {
923 cx.eval::<Value<'_>, _>("var a = [1, 2, 3];").unwrap();
924 let v = cx.globals().get("a").unwrap();
925
926 let val = deserialize_value::<Vec<u8>>(v);
927
928 assert_eq!(vec![1, 2, 3], val);
929 });
930 }
931
932 #[test]
933 fn test_array_with_boxed_primitives() {
934 let rt = Runtime::default();
935 rt.context().with(|cx| {
936 cx.eval::<Value<'_>, _>(
937 r#"
938 var a = [new Boolean(false), new Number(7), new String("x")];
939 "#,
940 )
941 .unwrap();
942 let v = cx.globals().get("a").unwrap();
943 assert_eq!(
944 (false, 7, "x".to_string()),
945 deserialize_value::<(bool, i32, String)>(v)
946 );
947 });
948 }
949
950 #[test]
951 fn test_array_proxy() {
952 let rt = Runtime::default();
953 rt.context().with(|cx| {
954 cx.eval::<Value<'_>, _>(
955 r#"
956 var arr = [1, 2, 3];
957 var a = new Proxy(arr, {});
958 "#,
959 )
960 .unwrap();
961 let v = cx.globals().get("a").unwrap();
962 let val = deserialize_value::<Vec<u8>>(v);
963 assert_eq!(vec![1, 2, 3], val);
964 });
965 }
966
967 #[test]
968 fn test_non_json_object_values_are_dropped() {
969 let rt = Runtime::default();
970 rt.context().with(|cx| {
971 cx.eval::<Value<'_>, _>(
972 r#"
973 var unitialized;
974 var a = {
975 a: undefined,
976 b: function() {},
977 c: Symbol(),
978 d: () => {},
979 e: unitialized,
980 };"#,
981 )
982 .unwrap();
983 let v = cx.globals().get("a").unwrap();
984
985 let val = deserialize_value::<BTreeMap<String, ()>>(v);
986 assert_eq!(BTreeMap::new(), val);
987 });
988 }
989
990 #[test]
991 fn test_non_json_array_values_are_null() {
992 let rt = Runtime::default();
993 rt.context().with(|cx| {
994 cx.eval::<Value<'_>, _>(
995 r#"
996 var unitialized;
997 var a = [
998 undefined,
999 function() {},
1000 Symbol(),
1001 () => {},
1002 unitialized,
1003 ];"#,
1004 )
1005 .unwrap();
1006 let v = cx.globals().get("a").unwrap();
1007
1008 let val = deserialize_value::<Vec<Option<()>>>(v);
1009 assert_eq!(vec![None; 5], val);
1010 });
1011 }
1012
1013 #[test]
1014 fn test_enum_unit() {
1015 let rt = Runtime::default();
1016
1017 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
1018 enum Test {
1019 One,
1020 Two,
1021 Three,
1022 }
1023
1024 rt.context().with(|cx| {
1025 let left = Test::Two;
1026 let value = to_value(cx, left).unwrap();
1027 let right: Test = from_value(value).unwrap();
1028 assert_eq!(left, right);
1029 });
1030 }
1031
1032 #[test]
1033 fn test_enum_boxed_string() {
1034 #[derive(Debug, PartialEq, Deserialize)]
1035 enum Test {
1036 One,
1037 Two,
1038 }
1039
1040 let rt = Runtime::default();
1041 rt.context().with(|cx| {
1042 cx.eval::<Value<'_>, _>("var a = new String('Two');")
1043 .unwrap();
1044 let v = cx.globals().get("a").unwrap();
1045 assert_eq!(Test::Two, deserialize_value::<Test>(v));
1046 });
1047 }
1048
1049 #[test]
1050 fn test_enum_newtype() {
1051 let rt = Runtime::default();
1052
1053 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
1054 enum Test {
1055 One(i32),
1056 Two(i32),
1057 }
1058
1059 rt.context().with(|cx| {
1060 let left = Test::One(6);
1061 let value = to_value(cx, left).unwrap();
1062 let right: Test = from_value(value).unwrap();
1063 assert_eq!(left, right);
1064 });
1065 }
1066
1067 #[test]
1068 fn test_enum_struct() {
1069 let rt = Runtime::default();
1070
1071 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
1072 enum Test {
1073 One { a: i32 },
1074 Two(i32),
1075 }
1076
1077 rt.context().with(|cx| {
1078 let left = Test::One { a: 6 };
1079 let value = to_value(cx, left).unwrap();
1080 let right: Test = from_value(value).unwrap();
1081 assert_eq!(left, right);
1082 });
1083 }
1084
1085 #[test]
1086 fn test_enum_tuple() {
1087 let rt = Runtime::default();
1088
1089 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
1090 enum Test {
1091 One(i32, i32),
1092 }
1093
1094 rt.context().with(|cx| {
1095 let left = Test::One(1, 2);
1096 let value = to_value(cx, left).unwrap();
1097 let right: Test = from_value(value).unwrap();
1098 assert_eq!(left, right);
1099 });
1100 }
1101
1102 #[test]
1103 fn test_short_bigint() {
1104 let rt = Runtime::default();
1105 rt.context().with(|cx| {
1106 cx.eval::<Value<'_>, _>("var a = BigInt(1);").unwrap();
1107 let v = cx.globals().get("a").unwrap();
1108 let val = deserialize_value::<String>(v);
1109 assert_eq!(val, "1");
1110 });
1111 }
1112
1113 #[test]
1114 fn test_boxed_bigint() {
1115 let rt = Runtime::default();
1116 rt.context().with(|cx| {
1117 cx.eval::<Value<'_>, _>("var a = Object(1n);").unwrap();
1118 let v = cx.globals().get("a").unwrap();
1119 let val = deserialize_value::<String>(v);
1120 assert_eq!(val, "1");
1121 });
1122 }
1123
1124 #[test]
1125 fn test_bigint() {
1126 let rt = Runtime::default();
1127 rt.context().with(|cx| {
1128 cx.eval::<Value<'_>, _>(
1129 r#"
1130 const left = 12345678901234567890n;
1131 const right = 98765432109876543210n;
1132 var a = left * right;
1133 "#,
1134 )
1135 .unwrap();
1136 let v = cx.globals().get("a").unwrap();
1137 let val = deserialize_value::<String>(v);
1138 assert_eq!(val, "1219326311370217952237463801111263526900");
1139 });
1140 }
1141
1142 #[test]
1143 fn test_class_ids_have_not_changed() {
1144 let rt = Runtime::default();
1145 rt.context().with(|cx| {
1146 let cases = [
1147 ("new Number(1)", ClassId::Number),
1148 ("new String('x')", ClassId::String),
1149 ("new Boolean(true)", ClassId::Bool),
1150 ("Object(1n)", ClassId::BigInt),
1151 ];
1152
1153 for (expr, expected) in cases {
1154 let val = cx.eval::<Value<'_>, _>(expr).unwrap();
1155 assert_eq!(get_class_id(&val), expected, "{expr} class id changed");
1156 }
1157 });
1158 }
1159}