1use js_sys::Reflect;
2use wasm_bindgen::{JsCast, JsValue};
3
4pub fn deep_equal(v1: &JsValue, v2: &JsValue) -> bool {
8 if v1 == v2 || js_sys::Object::is(v1, v2) {
9 return true;
10 }
11
12 let t1 = v1.js_typeof();
13 let t2 = v2.js_typeof();
14
15 if t1 != t2 {
16 return false;
17 };
18
19 if t1 == "object" && !v1.is_null() && !v2.is_null() {
20 let p1 = Reflect::get_prototype_of(v1).unwrap();
21 let p2 = Reflect::get_prototype_of(v1).unwrap();
22
23 p1 == p2 && {
24 let a1 = v1.dyn_ref::<js_sys::Array>();
25 let a2 = v2.dyn_ref::<js_sys::Array>();
26
27 match (a1, a2) {
28 (Some(a1), Some(a2)) => {
29 a1.length() == a2.length()
30 && a1.every(&mut |v, i, _| deep_equal(&v, &a2.get(i)))
31 }
32 (None, None) => {
33 let o1 = v1.dyn_ref::<js_sys::Object>();
34 let o2 = v2.dyn_ref::<js_sys::Object>();
35 match (o1, o2) {
36 (Some(o1), Some(o2)) => {
37 let d1 = o1.dyn_ref::<js_sys::Date>();
38 let d2 = o2.dyn_ref::<js_sys::Date>();
39
40 match (d1, d2) {
41 (Some(d1), Some(d2)) => return d1.get_time() == d2.get_time(),
42 _ => {}
43 }
44
45 let keys1 = js_sys::Reflect::own_keys(&o1).unwrap();
46 let keys2 =
47 js_sys::Set::new(js_sys::Reflect::own_keys(&o2).unwrap().as_ref());
48
49 keys1.for_each(&mut |v, _, _| {
50 keys2.delete(&v);
51 });
52
53 keys2.size() == 0
54 && keys1.every(&mut |k, _, _| {
55 let v1 = js_sys::Reflect::get(&o1, &k).unwrap();
56 let v2 = js_sys::Reflect::get(&o2, &k).unwrap();
57 deep_equal(&v1, &v2)
58 })
59 }
60 _ => false,
61 }
62 }
63 _ => false,
64 }
65 }
66 } else {
67 false
68 }
69}