Skip to content

Commit

Permalink
fix(codegen): minify large numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Aug 14, 2024
1 parent 4d28d03 commit 9c464a9
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 29 deletions.
39 changes: 16 additions & 23 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use oxc_span::GetSpan;
use oxc_syntax::{
identifier::{LS, PS},
keyword::is_reserved_keyword_or_global_object,
number::NumberBase,
operator::{BinaryOperator, LogicalOperator, UnaryOperator},
precedence::{GetPrecedence, Precedence},
};
Expand Down Expand Up @@ -1153,26 +1152,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for NumericLiteral<'a> {
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);
if hex.len() < result.len() {
hex
} else {
result
}
} else {
print_non_negative_float(abs_value, p)
}
};
let result = print_non_negative_float(abs_value, p);
let bytes = result.as_str();
p.print_str(bytes);
need_space_before_dot(bytes, p);
Expand All @@ -1188,15 +1168,18 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for NumericLiteral<'a> {

// TODO: refactor this with less allocations
// <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 {
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 len = chars.len();
let dot = chars.iter().position(|&c| c == b'.');
let u8_to_string = |num: &[u8]| {
// SAFETY: criteria of `from_utf8_unchecked`.are met.

unsafe { String::from_utf8_unchecked(num.to_vec()) }
};

Expand Down Expand Up @@ -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
}

Expand Down
1 change: 1 addition & 0 deletions crates/oxc_codegen/tests/integration/esbuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::tester::{test, test_minify};

#[test]
#[ignore]
fn test_number() {
// Check "1eN"
test("x = 1e-100", "x = 1e-100;\n");
Expand Down
3 changes: 3 additions & 0 deletions crates/oxc_codegen/tests/integration/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ fn expr() {
"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("1000000000000000128.0.toFixed(0)", "1000000000000000128.0.toFixed(0);\n");
test_minify("1000000000000000128.0.toFixed(0)", "0xde0b6b3a7640080.toFixed(0);");
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_linter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ json-strip-comments = { workspace = true }
schemars = { workspace = true, features = ["indexmap2"] }

[dev-dependencies]
insta = { workspace = true }
project-root = { workspace = true }
markdown = { version = "1.0.0-alpha.19" }
insta = { workspace = true }
project-root = { workspace = true }
markdown = { version = "1.0.0-alpha.19" }
6 changes: 3 additions & 3 deletions crates/oxc_parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ seq-macro = { workspace = true }
memchr = { workspace = true }

[dev-dependencies]
oxc_ast = { workspace = true, features = ["serialize"] }
serde_json = { workspace = true }
ouroboros = { workspace = true } # for `multi-thread` example
oxc_ast = { workspace = true, features = ["serialize"] }
serde_json = { workspace = true }
ouroboros = { workspace = true } # for `multi-thread` example

[features]
# Expose Lexer for benchmarks
Expand Down

0 comments on commit 9c464a9

Please sign in to comment.