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