Skip to content

Commit b14a3db

Browse files
committed
fix(linter): avoid no-loss-of-precision false positive for 3e-308
1 parent 0f0ff51 commit b14a3db

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

crates/oxc_linter/src/rules/eslint/no_loss_of_precision.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,19 @@ fn round_to_precision(digits: &mut String, precision: usize) -> bool {
348348
}
349349
}
350350

351+
fn fractional_digits_for_precision(num: f64, precision: usize) -> usize {
352+
let exponent = format!("{num:e}")
353+
.rsplit_once('e')
354+
.and_then(|(_, exp)| exp.parse::<isize>().ok())
355+
.unwrap_or_default();
356+
357+
if exponent.is_negative() {
358+
exponent.unsigned_abs().saturating_add(precision).saturating_add(1)
359+
} else {
360+
100
361+
}
362+
}
363+
351364
/// Mimics JavaScript's `Number.prototype.toPrecision()` method
352365
///
353366
/// The `toPrecision()` method returns a string representing the Number object to the specified precision.
@@ -391,8 +404,10 @@ pub fn to_precision(mut num: f64, precision: usize) -> String {
391404
suffix = "0".repeat(precision);
392405
exponent = 0;
393406
} else {
394-
// Format with maximum precision to get all digits
395-
suffix = format!("{num:.100}");
407+
// For very small numbers (e.g. 3e-308), we need more than 100 fractional digits
408+
// to keep enough significant digits for precision comparison.
409+
let fractional_digits = fractional_digits_for_precision(num, precision);
410+
suffix = format!("{num:.fractional_digits$}");
396411

397412
// Calculate exponent
398413
exponent = flt_str_to_exp(&suffix);
@@ -519,6 +534,7 @@ fn test() {
519534
"const a = Infinity",
520535
"const a = 480.00",
521536
"const a = -30.00",
537+
"const x = 3e-308",
522538
"(1000000000000000128).toFixed(0)",
523539
];
524540

0 commit comments

Comments
 (0)