diff --git a/Cargo.lock b/Cargo.lock index 47f366ee8f4..9498a77abd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,7 @@ dependencies = [ "rand", "regex", "rustc-hash", + "ryu-js", "serde", "serde_json", ] @@ -806,6 +807,11 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "ryu-js" +version = "1.0.5" +source = "git+https://github.com/Tropid/ryu-js#fe366fa397d04324fa693b5d85134851b09719b3" + [[package]] name = "same-file" version = "1.0.6" diff --git a/boa/Cargo.toml b/boa/Cargo.toml index ecf5b94c038..5b9a22912f7 100644 --- a/boa/Cargo.toml +++ b/boa/Cargo.toml @@ -23,6 +23,7 @@ rustc-hash = "1.1.0" num-bigint = { version = "0.3.0", features = ["serde"] } num-integer = "0.1.43" bitflags = "1.2.1" +ryu-js = "0.2.0" # Optional Dependencies serde = { version = "1.0.114", features = ["derive"], optional = true } diff --git a/boa/src/builtins/value/display.rs b/boa/src/builtins/value/display.rs index 5637c04abb6..f2bb3bada37 100644 --- a/boa/src/builtins/value/display.rs +++ b/boa/src/builtins/value/display.rs @@ -177,19 +177,15 @@ impl Display for Value { None => write!(f, "Symbol()"), }, Self::String(ref v) => write!(f, "{}", v), - Self::Rational(v) => write!( - f, - "{}", - match v { - _ if v.is_nan() => "NaN".to_string(), - _ if v.is_infinite() && v.is_sign_negative() => "-Infinity".to_string(), - _ if v.is_infinite() => "Infinity".to_string(), - _ => v.to_string(), - } - ), + Self::Rational(v) => format_rational(*v, f), Self::Object(_) => write!(f, "{}", log_string_from(self, true)), Self::Integer(v) => write!(f, "{}", v), Self::BigInt(ref num) => write!(f, "{}n", num), } } } + +fn format_rational(v: f64, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut buffer = ryu_js::Buffer::new(); + write!(f, "{}", buffer.format(v)) +} diff --git a/boa/src/builtins/value/tests.rs b/boa/src/builtins/value/tests.rs index 16323fd0e83..607d6bdfcc5 100644 --- a/boa/src/builtins/value/tests.rs +++ b/boa/src/builtins/value/tests.rs @@ -214,6 +214,40 @@ fn get_types() { ); } +#[test] +fn to_string() { + let f64_to_str = |f| Value::Rational(f).to_string(); + + assert_eq!(f64_to_str(f64::NAN), "NaN"); + assert_eq!(f64_to_str(0.0), "0"); + assert_eq!(f64_to_str(f64::INFINITY), "Infinity"); + assert_eq!(f64_to_str(f64::NEG_INFINITY), "-Infinity"); + assert_eq!(f64_to_str(90.12), "90.12"); + assert_eq!(f64_to_str(111111111111111111111.0), "111111111111111110000"); + assert_eq!( + f64_to_str(1111111111111111111111.0), + "1.1111111111111111e+21" + ); + + assert_eq!(f64_to_str(-90.12), "-90.12"); + + assert_eq!( + f64_to_str(-111111111111111111111.0), + "-111111111111111110000" + ); + assert_eq!( + f64_to_str(-1111111111111111111111.0), + "-1.1111111111111111e+21" + ); + + assert_eq!(f64_to_str(0.0000001), "1e-7"); + assert_eq!(f64_to_str(0.000001), "0.000001"); + assert_eq!(f64_to_str(0.0000002), "2e-7"); + assert_eq!(f64_to_str(-0.0000001), "-1e-7"); + + assert_eq!(f64_to_str(3e50), "3e+50"); +} + #[test] fn add_number_and_number() { let realm = Realm::create();