fix(es/codegen): Handle minify number (#9541)

**Related issue:**

- Closes https://github.com/swc-project/swc/issues/9540
This commit is contained in:
magic-akari 2024-09-11 10:20:51 +08:00 committed by GitHub
parent 3fc47fc5a3
commit 8b1e4428a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 115 additions and 78 deletions

View File

@ -0,0 +1,6 @@
---
swc_core: patch
swc_ecma_codegen: patch
---
fix(es/codegen): Handle minify number

View File

@ -0,0 +1,19 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false
},
"target": "es2022",
"loose": false,
"minify": {
"compress": false,
"mangle": false
}
},
"module": {
"type": "es6"
},
"minify": true,
"isModule": true
}

View File

@ -0,0 +1,4 @@
219994525426954..toString();
219994525420000..toString();
12300000..toString(1);
12300001..toString(1);

View File

@ -0,0 +1 @@
0xc815778a650a.toString();21999452542e4.toString();123e5.toString(1);0xbbaee1.toString(1);

View File

@ -697,7 +697,7 @@ where
fn emit_num_lit_internal(
&mut self,
num: &Number,
detect_dot: bool,
mut detect_dot: bool,
) -> std::result::Result<bool, io::Error> {
self.wr.commit_pending_semi()?;
@ -722,7 +722,7 @@ where
if num.value.is_infinite() && num.raw.is_some() {
self.wr.write_str_lit(DUMMY_SP, num.raw.as_ref().unwrap())?;
} else {
value = minify_number(num.value);
value = minify_number(num.value, &mut detect_dot);
self.wr.write_str_lit(DUMMY_SP, &value)?;
}
} else {
@ -4327,69 +4327,76 @@ fn is_empty_comments(span: &Span, comments: &Option<&dyn Comments>) -> bool {
span.is_dummy() || comments.map_or(true, |c| !c.has_leading(span.span_hi() - BytePos(1)))
}
fn minify_number(num: f64) -> String {
let mut printed = num.to_string();
fn minify_number(num: f64, detect_dot: &mut bool) -> String {
// ddddd -> 0xhhhh
// len(0xhhhh) == len(ddddd)
// 10000000 <= num <= 0xffffff
'hex: {
if num.fract() == 0.0 && num.abs() <= u64::MAX as f64 {
let int = num.abs() as u64;
let mut original = printed.clone();
if num.fract() == 0.0 && (i64::MIN as f64) <= num && num <= (i64::MAX as f64) {
let hex = format!(
"{}{:#x}",
if num.is_sign_negative() { "-" } else { "" },
num as i64
);
if hex.len() < printed.len() {
printed = hex;
}
}
if original.starts_with("0.") {
original.replace_range(0..1, "");
}
if original.starts_with("-0.") {
original.replace_range(1..2, "");
}
if original.starts_with(".000") {
let mut cnt = 3;
for &v in original.as_bytes().iter().skip(4) {
if v == b'0' {
cnt += 1;
} else {
break;
if int < 10000000 {
break 'hex;
}
}
original.replace_range(0..cnt + 1, "");
let remain_len = original.len();
original.push_str("e-");
original.push_str(&(remain_len + cnt).to_string());
} else if original.ends_with("000") {
let mut cnt = 3;
for &v in original.as_bytes().iter().rev().skip(3) {
if v == b'0' {
cnt += 1;
} else {
break;
// use scientific notation
if int % 1000 == 0 {
break 'hex;
}
*detect_dot = false;
return format!(
"{}{:#x}",
if num.is_sign_negative() { "-" } else { "" },
int
);
}
original.truncate(original.len() - cnt);
original.push('e');
original.push_str(&cnt.to_string());
}
if original.len() < printed.len() {
printed = original;
let mut num = num.to_string();
if num.contains(".") {
*detect_dot = false;
}
printed
if let Some(num) = num.strip_prefix("0.") {
let cnt = clz(num);
if cnt > 2 {
return format!("{}e-{}", &num[cnt..], num.len());
}
return format!(".{}", num);
}
if let Some(num) = num.strip_prefix("-0.") {
let cnt = clz(num);
if cnt > 2 {
return format!("-{}e-{}", &num[cnt..], num.len());
}
return format!("-.{}", num);
}
if num.ends_with("000") {
*detect_dot = false;
let cnt = num
.as_bytes()
.iter()
.rev()
.skip(3)
.take_while(|&&c| c == b'0')
.count()
+ 3;
num.truncate(num.len() - cnt);
num.push('e');
num.push_str(&cnt.to_string());
}
num
}
fn clz(s: &str) -> usize {
s.as_bytes().iter().take_while(|&&c| c == b'0').count()
}
fn span_has_leading_comment(cmt: &dyn Comments, span: Span) -> bool {

View File

@ -1 +1 @@
function te(a){var b,c,d,e,f;if(isNaN(a)){return Qe(),Pe}if(a<-0x7fffffffffffffff){return Qe(),Ne}if(a>=0x7fffffffffffffff){return Qe(),Me}e=false;if(a<0){e=true;a=-a}d=0;if(a>=17592186044416){d=Bc(a/17592186044416);a-=d*17592186044416}c=0;if(a>=4194304){c=Bc(a/4194304);a-=c*4194304}b=Bc(a);f=de(b,c,d);e&&je(f);return f}
function te(a){var b,c,d,e,f;if(isNaN(a)){return Qe(),Pe}if(a<-0x8000000000000000){return Qe(),Ne}if(a>=0x8000000000000000){return Qe(),Me}e=false;if(a<0){e=true;a=-a}d=0;if(a>=0x100000000000){d=Bc(a/0x100000000000);a-=d*0x100000000000}c=0;if(a>=4194304){c=Bc(a/4194304);a-=c*4194304}b=Bc(a);f=de(b,c,d);e&&je(f);return f}

View File

@ -1 +1 @@
const exp=1e3;const Exp=1e12;const negativeExp=1e-8;const huge=0xe8d4a51001;const big=100000000001;const fractional=100.23002;const numeric_separators=1e12;const one=1e3;const two=1e6;const three=-1e6;const bin=85;const oct=342391;const hex=3735928559;const fractional2=1000.0001;const identifier=_1000;const negate_identifier=-_1000;const foo=.1;const foo1=+.1;const foo2=-.1;const foo3=1050;const foo4=100500;const foo5=10005e3;const foo6=100005e4;const foo7=.1;const foo8=.01;const foo9=.001;const foo10=1e-4;const foo11=1e-5;const foo12=1e-6;const foo13=24e-6;const foo14=-24e-6;const foo15=10;const foo16=100;const foo17=1e3;const foo18=1e4;const foo19=1e5;const foo20=.1;const foo21=.01;const foo22=.001;const foo23=1e-4;const foo24=1e-5;const foo25=-.1;const foo26=-.01;const foo27=-.001;const foo28=-1e-4;const foo29=-1e-5;const foo30=.001;const foo31=.00321;const foo32=321e-6;const foo33=.1;const foo34=1e-5;const foo35=0;const foo36=-0;const foo37=+0;const foo38=1543e-8;const foo39=1543e-8;const foo40=(1543e-8);const foo41={100005e4:"foo"};const foo42=0xe8d4a51caa;const foo43_=-0xe8d4a51caa;const foo43=0;const foo44=-0;const foo45=+0;const foo46=1e9;const foo47=1.10001;const foo48=1e10;const foo49=1e10;const foo50=1e-10;const foo51=11e99;const foo52=11e99;const foo53=11e-101;const foo54=123456;const foo55=122333;const foo56=12.34;const foo57=1234e54;const foo58=1234e54;const foo59=1234e-58;const foo60=.1;const foo61=10;const foo62=5e9;const foo63=255;const foo64=255;const foo65=255;const foo66=0;const foo67=0;const foo68=0;const foo69=0;const foo70=0;const foo71=255;26..toString();4294967295..toString();4294967295..toString();668..toString();668..toString();109..toString();109..toString();1234..toString();1..toString();77..toExponential();77..toExponential();(77).toExponential();77..toExponential();77..toExponential();const hugefoo=0xe8d4a51001.test();const hugefoo1=238..test();1234..toString();1234..toString();const foo72=864e5;const foo73=65535;const foo74=65535;const foo75=Infinity;const foo76=Infinity.toString();
const exp=1e3;const Exp=1e12;const negativeExp=1e-8;const huge=0xe8d4a51001;const big=0x174876e801;const fractional=100.23002;const numeric_separators=1e12;const one=1e3;const two=1e6;const three=-1e6;const bin=85;const oct=342391;const hex=0xdeadbeef;const fractional2=1000.0001;const identifier=_1000;const negate_identifier=-_1000;const foo=.1;const foo1=+.1;const foo2=-.1;const foo3=1050;const foo4=100500;const foo5=10005e3;const foo6=100005e4;const foo7=.1;const foo8=.01;const foo9=.001;const foo10=1e-4;const foo11=1e-5;const foo12=1e-6;const foo13=24e-6;const foo14=-24e-6;const foo15=10;const foo16=100;const foo17=1e3;const foo18=1e4;const foo19=1e5;const foo20=.1;const foo21=.01;const foo22=.001;const foo23=1e-4;const foo24=1e-5;const foo25=-.1;const foo26=-.01;const foo27=-.001;const foo28=-1e-4;const foo29=-1e-5;const foo30=.001;const foo31=.00321;const foo32=321e-6;const foo33=.1;const foo34=1e-5;const foo35=0;const foo36=-0;const foo37=+0;const foo38=1543e-8;const foo39=1543e-8;const foo40=(1543e-8);const foo41={100005e4:"foo"};const foo42=0xe8d4a51caa;const foo43_=-0xe8d4a51caa;const foo43=0;const foo44=-0;const foo45=+0;const foo46=1e9;const foo47=1.10001;const foo48=1e10;const foo49=1e10;const foo50=1e-10;const foo51=11e99;const foo52=11e99;const foo53=11e-101;const foo54=123456;const foo55=122333;const foo56=12.34;const foo57=1234e54;const foo58=1234e54;const foo59=1234e-58;const foo60=.1;const foo61=10;const foo62=5e9;const foo63=255;const foo64=255;const foo65=255;const foo66=0;const foo67=0;const foo68=0;const foo69=0;const foo70=0;const foo71=255;26..toString();0xffffffff.toString();0xffffffff.toString();668..toString();668..toString();109..toString();109..toString();1234..toString();1..toString();77..toExponential();77..toExponential();(77).toExponential();77..toExponential();77..toExponential();const hugefoo=0xe8d4a51001.test();const hugefoo1=238..test();1234..toString();1234..toString();const foo72=864e5;const foo73=65535;const foo74=65535;const foo75=Infinity;const foo76=Infinity.toString();

View File

@ -23,8 +23,8 @@ export default function(r, t, e) {
var d = c[_ - 15], v = (d << 25 | d >>> 7) ^ (d << 14 | d >>> 18) ^ d >>> 3, H = c[_ - 2], p = (H << 15 | H >>> 17) ^ (H << 13 | H >>> 19) ^ H >>> 10;
c[_] = v + c[_ - 7] + p + c[_ - 16];
}
var w = h & u ^ ~h & f, A = n & o ^ n & s ^ o & s, g = (n << 30 | n >>> 2) ^ (n << 19 | n >>> 13) ^ (n << 10 | n >>> 22), y = l + ((h << 26 | h >>> 6) ^ (h << 21 | h >>> 11) ^ (h << 7 | h >>> 25)) + w + i[_] + c[_], B = g + A;
l = f, f = u, u = h, h = a + y | 0, a = s, s = o, o = n, n = y + B | 0;
var w = h & u ^ ~h & f, x = n & o ^ n & s ^ o & s, A = (n << 30 | n >>> 2) ^ (n << 19 | n >>> 13) ^ (n << 10 | n >>> 22), g = l + ((h << 26 | h >>> 6) ^ (h << 21 | h >>> 11) ^ (h << 7 | h >>> 25)) + w + i[_] + c[_], y = A + x;
l = f, f = u, u = h, h = a + g | 0, a = s, s = o, o = n, n = g + y | 0;
}
// Intermediate hash value
e[0] = e[0] + n | 0, e[1] = e[1] + o | 0, e[2] = e[2] + s | 0, e[3] = e[3] + a | 0, e[4] = e[4] + h | 0, e[5] = e[5] + u | 0, e[6] = e[6] + f | 0, e[7] = e[7] + l | 0;

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
!(function(o) {
!(function(c) {
try {
throw 0;
} catch (c) {
o = 123456789 / 0;
} catch (o) {
c = 123456789 / 0;
}
console.log(o);
console.log(c);
})();

View File

@ -4,10 +4,10 @@ var v = 42 ** -0;
var i = NaN ** 1;
var n = 2 ** Infinity;
var N = 2 ** -Infinity;
var f = (-7) ** 0.5;
var t = 2324334 ** 34343443;
var y = (-2324334) ** 34343443;
var I = 2 ** -3;
var b = 2 ** -3;
var c = 2 ** (5 - 7);
var d = 3 ** -10;
var c = (-7) ** 0.5;
var f = 2324334 ** 34343443;
var t = (-2324334) ** 34343443;
var x = 2 ** -3;
var y = 2 ** -3;
var I = 2 ** (5 - 7);
var b = 3 ** -10;

View File

@ -1,6 +1,6 @@
var a = (-7) ** 0.5;
var r = 2324334 ** 34343443;
var v = (-2324334) ** 34343443;
var b = 2 ** -3;
var c = 2 ** -3;
var d = 2 ** (5 - 7);
var x = 2 ** -3;
var b = 2 ** (5 - 7);

View File

@ -4,5 +4,5 @@ const o = 85;
const s = 342391;
const t = 3735928559;
const e = 1000.0001;
const _ = _1000;
const a = -_1000;
const d = _1000;
const _ = -_1000;

View File

@ -2,4 +2,4 @@
<div>test</div>
<script>var test2="😋",test3="😋"</script>
<div>number</div>
<script>var test4=123456789</script>
<script>var test4=0x75bcd15</script>

View File

@ -2,4 +2,4 @@
<div>test</div>
<script>var test2="\uD83D\uDE0B",test3="\uD83D\uDE0B"</script>
<div>number</div>
<script>var test4=123456789</script>
<script>var test4=0x75bcd15</script>