mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
fix(codegen): minify large numbers (#4889)
This commit is contained in:
parent
4d28d037e6
commit
21f576252a
5 changed files with 26 additions and 29 deletions
|
|
@ -7,7 +7,6 @@ use oxc_span::GetSpan;
|
||||||
use oxc_syntax::{
|
use oxc_syntax::{
|
||||||
identifier::{LS, PS},
|
identifier::{LS, PS},
|
||||||
keyword::is_reserved_keyword_or_global_object,
|
keyword::is_reserved_keyword_or_global_object,
|
||||||
number::NumberBase,
|
|
||||||
operator::{BinaryOperator, LogicalOperator, UnaryOperator},
|
operator::{BinaryOperator, LogicalOperator, UnaryOperator},
|
||||||
precedence::{GetPrecedence, Precedence},
|
precedence::{GetPrecedence, Precedence},
|
||||||
};
|
};
|
||||||
|
|
@ -1153,26 +1152,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for NumericLiteral<'a> {
|
||||||
p.print_str("-");
|
p.print_str("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = if self.base == NumberBase::Float {
|
|
||||||
print_non_negative_float(abs_value, p)
|
|
||||||
} else {
|
|
||||||
let value = abs_value as u64;
|
|
||||||
// If integers less than 1000, we know that exponential notation will always be longer than
|
|
||||||
// the integer representation. This is not the case for 1000 which is "1e3".
|
|
||||||
if value < 1000 {
|
|
||||||
format!("{value}")
|
|
||||||
} else if (1_000_000_000_000..=0xFFFF_FFFF_FFFF_F800).contains(&value) {
|
|
||||||
let hex = format!("{value:#x}");
|
|
||||||
let result = print_non_negative_float(abs_value, p);
|
let result = print_non_negative_float(abs_value, p);
|
||||||
if hex.len() < result.len() {
|
|
||||||
hex
|
|
||||||
} else {
|
|
||||||
result
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print_non_negative_float(abs_value, p)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let bytes = result.as_str();
|
let bytes = result.as_str();
|
||||||
p.print_str(bytes);
|
p.print_str(bytes);
|
||||||
need_space_before_dot(bytes, p);
|
need_space_before_dot(bytes, p);
|
||||||
|
|
@ -1188,15 +1168,18 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for NumericLiteral<'a> {
|
||||||
|
|
||||||
// TODO: refactor this with less allocations
|
// TODO: refactor this with less allocations
|
||||||
// <https://github.com/evanw/esbuild/blob/360d47230813e67d0312ad754cad2b6ee09b151b/internal/js_printer/js_printer.go#L3472>
|
// <https://github.com/evanw/esbuild/blob/360d47230813e67d0312ad754cad2b6ee09b151b/internal/js_printer/js_printer.go#L3472>
|
||||||
|
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||||
fn print_non_negative_float<const MINIFY: bool>(value: f64, _p: &Codegen<{ MINIFY }>) -> String {
|
fn print_non_negative_float<const MINIFY: bool>(value: f64, _p: &Codegen<{ MINIFY }>) -> String {
|
||||||
use oxc_syntax::number::ToJsString;
|
use oxc_syntax::number::ToJsString;
|
||||||
let mut result = value.to_js_string();
|
if value < 1000.0 && value.fract() == 0.0 {
|
||||||
|
return value.to_js_string();
|
||||||
|
}
|
||||||
|
let mut result = format!("{value:e}");
|
||||||
let chars = result.as_bytes();
|
let chars = result.as_bytes();
|
||||||
let len = chars.len();
|
let len = chars.len();
|
||||||
let dot = chars.iter().position(|&c| c == b'.');
|
let dot = chars.iter().position(|&c| c == b'.');
|
||||||
let u8_to_string = |num: &[u8]| {
|
let u8_to_string = |num: &[u8]| {
|
||||||
// SAFETY: criteria of `from_utf8_unchecked`.are met.
|
// SAFETY: criteria of `from_utf8_unchecked`.are met.
|
||||||
|
|
||||||
unsafe { String::from_utf8_unchecked(num.to_vec()) }
|
unsafe { String::from_utf8_unchecked(num.to_vec()) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1244,6 +1227,16 @@ fn print_non_negative_float<const MINIFY: bool>(value: f64, _p: &Codegen<{ MINIF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if MINIFY && value.fract() == 0.0 {
|
||||||
|
let value = value as u64;
|
||||||
|
if (1_000_000_000_000..=0xFFFF_FFFF_FFFF_F800).contains(&value) {
|
||||||
|
let hex = format!("{value:#x}");
|
||||||
|
if hex.len() < result.len() {
|
||||||
|
result = hex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
use crate::tester::{test, test_minify};
|
use crate::tester::{test, test_minify};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn test_number() {
|
fn test_number() {
|
||||||
// Check "1eN"
|
// Check "1eN"
|
||||||
test("x = 1e-100", "x = 1e-100;\n");
|
test("x = 1e-100", "x = 1e-100;\n");
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ fn expr() {
|
||||||
"class Foo {\n\t#test;\n\tbar() {\n\t\tif (!(#test in Foo)) {}\n\t}\n}\n",
|
"class Foo {\n\t#test;\n\tbar() {\n\t\tif (!(#test in Foo)) {}\n\t}\n}\n",
|
||||||
);
|
);
|
||||||
test_minify("x in new Error()", "x in new Error();");
|
test_minify("x in new Error()", "x in new Error();");
|
||||||
|
|
||||||
|
test("1000000000000000128.0.toFixed(0)", "1000000000000000128.0.toFixed(0);\n");
|
||||||
|
test_minify("1000000000000000128.0.toFixed(0)", "0xde0b6b3a7640080.toFixed(0);");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue