1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use crate::runner::ds::function_object::ConstructorKind;
use crate::runner::ds::object::{JsObject, ObjectType};
use crate::runner::ds::operations::type_conversion::{
get_type, TYPE_STR_BOOLEAN, TYPE_STR_FUNCTION, TYPE_STR_NULL,
TYPE_STR_NUMBER, TYPE_STR_OBJECT, TYPE_STR_STRING, TYPE_STR_SYMBOL, TYPE_STR_UNDEFINED,
};
use crate::runner::ds::value::{JsNumberType, JsValue};
use std::ops::Deref;
use std::ptr;
fn is_same_value<'a>(a: &'a JsValue, b: &'a JsValue, strict_mode: bool) -> bool {
let type_a = get_type(a);
let type_b = get_type(b);
if type_a == type_b {
if type_a == TYPE_STR_UNDEFINED || type_a == TYPE_STR_NULL {
true
} else {
if type_a == TYPE_STR_NUMBER {
if let JsValue::Number(na) = a {
if let JsValue::Number(nb) = b {
match na {
JsNumberType::NaN => {
if strict_mode {
false
} else {
if let JsNumberType::NaN = nb {
true
} else {
false
}
}
}
JsNumberType::PositiveInfinity => {
if let JsNumberType::PositiveInfinity = nb {
true
} else {
false
}
}
JsNumberType::NegativeInfinity => {
if let JsNumberType::NegativeInfinity = nb {
true
} else {
false
}
}
_ => {
let na_value = match na {
JsNumberType::Float(f) => *f,
JsNumberType::Integer(i) => *i as f64,
_ => 0 as f64, // Not really possible
};
let nb_value = match nb {
JsNumberType::Float(f) => *f,
JsNumberType::Integer(i) => *i as f64,
_ => return false,
};
na_value == nb_value
}
}
} else {
false
}
} else {
false
}
} else if type_a == TYPE_STR_STRING {
if let JsValue::String(a_value) = a {
if let JsValue::String(b_value) = b {
if a_value == b_value {
return true;
}
}
}
false
} else if type_a == TYPE_STR_BOOLEAN {
if let JsValue::Boolean(a_value) = a {
if let JsValue::Boolean(b_value) = b {
if a_value == b_value {
return true;
}
}
}
false
} else if type_a == TYPE_STR_SYMBOL {
if let JsValue::Symbol(a_value) = a {
if let JsValue::Symbol(b_value) = b {
if a_value == b_value {
return true;
}
}
}
false
} else if type_a == TYPE_STR_OBJECT || type_a == TYPE_STR_FUNCTION {
if let JsValue::Object(a_value) = a {
if let JsValue::Object(b_value) = b {
if same_object(
a_value.deref().borrow().deref(),
b_value.deref().borrow().deref(),
) {
return true;
}
}
}
false
} else {
false
}
}
} else {
false
}
}
pub fn same_object<'a>(a: &'a ObjectType, b: &'a ObjectType) -> bool {
a == b
}
pub fn same_js_object(a: &dyn JsObject, b: &dyn JsObject) -> bool {
ptr::eq(a.get_object_base(), b.get_object_base())
}
pub fn same_value<'a>(a: &'a JsValue, b: &'a JsValue) -> bool {
is_same_value(a, b, false)
}
pub fn is_constructor(obj: &ObjectType) -> bool {
if let ObjectType::Function(f) = obj {
if let ConstructorKind::None = f.get_function_object_base().constructor_kind {
false
} else {
true
}
} else {
false
}
}