diff --git a/crates/oxide_vm/src/coercion.rs b/crates/oxide_vm/src/coercion.rs index 10c7a2cf..dd0d6fd2 100644 --- a/crates/oxide_vm/src/coercion.rs +++ b/crates/oxide_vm/src/coercion.rs @@ -207,6 +207,16 @@ pub fn string_concat(lhs: &str, rhs: &str) -> String { s } +fn to_f64(val: JsValue) -> f64 { + if val.is_int() { + val.as_int() as f64 + } else if val.is_double() { + val.as_double() + } else { + f64::NAN + } +} + pub fn same_value(lhs: JsValue, rhs: JsValue) -> bool { if lhs.is_double() && rhs.is_double() { let a = lhs.as_double(); @@ -224,6 +234,17 @@ pub fn same_value(lhs: JsValue, rhs: JsValue) -> bool { if lhs.is_int() && rhs.is_int() { return lhs.as_int() == rhs.as_int(); } + if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) { + let a = to_f64(lhs); + let b = to_f64(rhs); + if a.is_nan() && b.is_nan() { + return true; + } + if a == 0.0 && b == 0.0 { + return a.is_sign_negative() == b.is_sign_negative(); + } + return a == b; + } if lhs.is_bool() && rhs.is_bool() { return lhs.as_bool() == rhs.as_bool(); } diff --git a/crates/oxide_vm/tests/coercion_tests.rs b/crates/oxide_vm/tests/coercion_tests.rs index 1e741bc0..d0939790 100644 --- a/crates/oxide_vm/tests/coercion_tests.rs +++ b/crates/oxide_vm/tests/coercion_tests.rs @@ -62,7 +62,13 @@ fn test_same_value_nan() { #[test] fn test_same_value_type_mismatch() { - assert!(!coercion::same_value(JsValue::int(1), JsValue::float(1.0))); + assert!(!coercion::same_value(JsValue::int(1), JsValue::bool(true))); +} + +#[test] +fn test_same_value_int_float_equal() { + assert!(coercion::same_value(JsValue::int(1), JsValue::float(1.0))); + assert!(!coercion::same_value(JsValue::int(1), JsValue::float(2.0))); } #[test] @@ -76,9 +82,21 @@ fn test_strict_equality_nan() { #[test] fn test_strict_equality_type_mismatch() { assert!(!coercion::strict_equality( + JsValue::int(1), + JsValue::bool(true) + )); +} + +#[test] +fn test_strict_equality_int_float_equal() { + assert!(coercion::strict_equality( JsValue::int(1), JsValue::float(1.0) )); + assert!(!coercion::strict_equality( + JsValue::int(1), + JsValue::float(2.0) + )); } #[test]