feat: 实现 ECMAScript 类型强制转换
This commit is contained in:
Generated
+8
@@ -293,6 +293,12 @@ version = "3.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
|
||||
|
||||
[[package]]
|
||||
name = "fast-float"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.4.1"
|
||||
@@ -795,10 +801,12 @@ name = "oxide_vm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"fast-float",
|
||||
"hashbrown 0.14.5",
|
||||
"oxide_compiler",
|
||||
"oxide_kernel",
|
||||
"proptest",
|
||||
"ryu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -33,6 +33,8 @@ bumpalo = "3"
|
||||
hashbrown = "0.14"
|
||||
proptest = "1"
|
||||
rustc-hash = "2"
|
||||
fast-float = "0.2"
|
||||
ryu = "1"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
all = { level = "deny", priority = -1 }
|
||||
|
||||
@@ -11,6 +11,8 @@ oxide_compiler = { path = "../oxide_compiler" }
|
||||
oxide_kernel = { path = "../oxide_kernel" }
|
||||
bumpalo.workspace = true
|
||||
hashbrown.workspace = true
|
||||
fast-float.workspace = true
|
||||
ryu.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
proptest.workspace = true
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
use crate::value::JsValue;
|
||||
|
||||
pub fn to_primitive(val: JsValue) -> JsValue {
|
||||
if val.is_object() {
|
||||
panic_to_object();
|
||||
}
|
||||
val
|
||||
}
|
||||
|
||||
pub fn to_number(val: JsValue) -> f64 {
|
||||
if val.is_int() {
|
||||
return val.as_int() as f64;
|
||||
}
|
||||
if val.is_double() {
|
||||
return val.as_double();
|
||||
}
|
||||
if val.is_bool() {
|
||||
return if val.as_bool() { 1.0 } else { 0.0 };
|
||||
}
|
||||
if val.is_null() {
|
||||
return 0.0;
|
||||
}
|
||||
if val.is_undefined() {
|
||||
return f64::NAN;
|
||||
}
|
||||
if val.is_object() {
|
||||
panic_to_object();
|
||||
}
|
||||
f64::NAN
|
||||
}
|
||||
|
||||
pub fn to_string(val: JsValue) -> String {
|
||||
if val.is_int() {
|
||||
return val.as_int().to_string();
|
||||
}
|
||||
if val.is_double() {
|
||||
let d = val.as_double();
|
||||
if d.is_nan() {
|
||||
return "NaN".to_string();
|
||||
}
|
||||
if d.is_infinite() {
|
||||
return if d.is_sign_positive() {
|
||||
"Infinity".to_string()
|
||||
} else {
|
||||
"-Infinity".to_string()
|
||||
};
|
||||
}
|
||||
let mut buf = ryu::Buffer::new();
|
||||
return buf.format(d).to_string();
|
||||
}
|
||||
if val.is_bool() {
|
||||
return val.as_bool().to_string();
|
||||
}
|
||||
if val.is_null() {
|
||||
return "null".to_string();
|
||||
}
|
||||
if val.is_undefined() {
|
||||
return "undefined".to_string();
|
||||
}
|
||||
if val.is_object() {
|
||||
panic_to_object();
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
|
||||
pub fn to_boolean(val: JsValue) -> bool {
|
||||
if val.is_undefined() || val.is_null() {
|
||||
return false;
|
||||
}
|
||||
if val.is_bool() {
|
||||
return val.as_bool();
|
||||
}
|
||||
if val.is_int() {
|
||||
return val.as_int() != 0;
|
||||
}
|
||||
if val.is_double() {
|
||||
let d = val.as_double();
|
||||
return !(d == 0.0 || d == -0.0 || d.is_nan());
|
||||
}
|
||||
if val.is_object() {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn abstract_eq(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_null() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) {
|
||||
return strict_double_eq(to_number(lhs), to_number(rhs));
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && rhs.is_bool() {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_bool() && (rhs.is_int() || rhs.is_double()) {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_bool() || rhs.is_bool() {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_null() || rhs.is_null() {
|
||||
return false;
|
||||
}
|
||||
if lhs.is_object() || rhs.is_object() {
|
||||
panic_to_object();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn strict_eq(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_object() && rhs.is_object() {
|
||||
return lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn strict_double_eq(a: f64, b: f64) -> bool {
|
||||
if a.is_nan() || b.is_nan() {
|
||||
return false;
|
||||
}
|
||||
a == b
|
||||
}
|
||||
|
||||
pub fn relational_compare(lhs: JsValue, rhs: JsValue) -> Option<bool> {
|
||||
let l = to_number(lhs);
|
||||
let r = to_number(rhs);
|
||||
if l.is_nan() || r.is_nan() {
|
||||
return None;
|
||||
}
|
||||
l.partial_cmp(&r).map(|o| o.is_lt())
|
||||
}
|
||||
|
||||
pub fn string_concat(lhs: &str, rhs: &str) -> String {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
s.push_str(rhs);
|
||||
s
|
||||
}
|
||||
|
||||
fn panic_to_object() {
|
||||
panic!("ToObject not yet implemented (Phase 6)")
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#![doc = "OxideJS - Register-based VM with epoch arena memory"]
|
||||
|
||||
pub mod coercion;
|
||||
pub mod mem;
|
||||
pub mod value;
|
||||
pub use value::JsValue;
|
||||
|
||||
Reference in New Issue
Block a user