From 0eaf60ee15c2f85b5cbd18ac287e8b242891a78b Mon Sep 17 00:00:00 2001 From: Taco de Wolff Date: Thu, 11 Jan 2024 11:13:44 -0300 Subject: [PATCH] JS: fix number minify and tests, see #656 --- js/js.go | 25 ++++++++++--------------- js/js_test.go | 6 +++++- js/util.go | 31 +++++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/js/js.go b/js/js.go index eed47ba93f..a8e3c9b0ee 100644 --- a/js/js.go +++ b/js/js.go @@ -882,7 +882,7 @@ func (m *jsMinifier) minifyExpr(i js.IExpr, prec js.OpPrec) { m.write(data) } case *js.LiteralExpr: - if expr.TokenType == js.DecimalToken { + if expr.TokenType == js.DecimalToken || expr.TokenType == js.IntegerToken { m.write(decimalNumber(expr.Data, m.o.Precision)) } else if expr.TokenType == js.BinaryToken { m.write(binaryNumber(expr.Data, m.o.Precision)) @@ -1018,8 +1018,11 @@ func (m *jsMinifier) minifyExpr(i js.IExpr, prec js.OpPrec) { // !"string" => !1 m.write(oneBytes) break - } else if ok && lit.TokenType == js.DecimalToken { + } else if ok && (lit.TokenType == js.DecimalToken || lit.TokenType == js.IntegerToken) { // !123 => !1 (except for !0) + if lit.Data[len(lit.Data)-1] == 'n' { + lit.Data = lit.Data[:len(lit.Data)-1] + } if num := minify.Number(lit.Data, m.o.Precision); len(num) == 1 && num[0] == '0' { m.write(zeroBytes) } else { @@ -1032,20 +1035,12 @@ func (m *jsMinifier) minifyExpr(i js.IExpr, prec js.OpPrec) { } case *js.DotExpr: if group, ok := expr.X.(*js.GroupExpr); ok { - if lit, ok := group.X.(*js.LiteralExpr); ok && lit.TokenType == js.DecimalToken { - num := minify.Number(lit.Data, m.o.Precision) - isInt := true - for _, c := range num { - if c == '.' || c == 'e' || c == 'E' { - isInt = false - break - } - } - if isInt { - m.write(num) - m.write(dotBytes) + if lit, ok := group.X.(*js.LiteralExpr); ok && (lit.TokenType == js.DecimalToken || lit.TokenType == js.IntegerToken) { + if lit.TokenType == js.DecimalToken { + m.write(minify.Number(lit.Data, m.o.Precision)) } else { - m.write(num) + m.write(lit.Data) + m.write(dotBytes) } m.write(dotBytes) m.write(expr.Y.Data) diff --git a/js/js_test.go b/js/js_test.go index c2e38181e6..1b6b97cf7c 100644 --- a/js/js_test.go +++ b/js/js_test.go @@ -31,11 +31,15 @@ func TestJS(t *testing.T) { {`1e10`, `1e10`}, {`1e-10`, `1e-10`}, {`5_000`, `5e3`}, + {`5_000n`, `5000n`}, {`0b1001`, `9`}, {`0b10_01`, `9`}, + {`0b10_01n`, `9n`}, {`0o11`, `9`}, + {`0o11n`, `9n`}, {`0x0D`, `13`}, {`0x0d`, `13`}, + {`0x0dn`, `13n`}, //{`123456787654321`, `0x704885f926b1`}, //{`4294967295`, `0xFFFFFFFF`}, // better GZIP {`+ +x`, `+ +x`}, @@ -808,7 +812,7 @@ func TestJS(t *testing.T) { {`for(var a=0;;){var b=5;for(var c=0;;);}`, `for(var b,c,a=0;;)for(b=5,c=0;;);`}, // #634 {"if(a)for(;;)\n;else b", `if(a)for(;;);else b`}, // #636 {`'\u000A\u000D'`, "`\n\r`"}, // #653 - {`for(!a;b;c);`, "`\n\r`"}, // #656 + {`for(!a;b;c);`, "for(!a;b;c);"}, // #656 } m := minify.New() diff --git a/js/util.go b/js/util.go index d1582a3e78..97fb7ecf28 100644 --- a/js/util.go +++ b/js/util.go @@ -1355,23 +1355,31 @@ func minifyRegExp(b []byte) []byte { return b } -func removeUnderscores(b []byte) []byte { +func removeUnderscoresAndSuffix(b []byte) ([]byte, bool) { for i := 0; i < len(b); i++ { if b[i] == '_' { b = append(b[:i], b[i+1:]...) i-- } } - return b + if 0 < len(b) && b[len(b)-1] == 'n' { + return b[:len(b)-1], true + } + return b, false } func decimalNumber(b []byte, prec int) []byte { - b = removeUnderscores(b) + var suffix bool + b, suffix = removeUnderscoresAndSuffix(b) + if suffix { + return append(b, 'n') + } return minify.Number(b, prec) } func binaryNumber(b []byte, prec int) []byte { - b = removeUnderscores(b) + var suffix bool + b, suffix = removeUnderscoresAndSuffix(b) if len(b) <= 2 || 65 < len(b) { return b } @@ -1387,11 +1395,15 @@ func binaryNumber(b []byte, prec int) []byte { n /= 10 i-- } + if suffix { + return append(b, 'n') + } return minify.Number(b, prec) } func octalNumber(b []byte, prec int) []byte { - b = removeUnderscores(b) + var suffix bool + b, suffix = removeUnderscoresAndSuffix(b) if len(b) <= 2 || 23 < len(b) { return b } @@ -1407,11 +1419,15 @@ func octalNumber(b []byte, prec int) []byte { n /= 10 i-- } + if suffix { + return append(b, 'n') + } return minify.Number(b, prec) } func hexadecimalNumber(b []byte, prec int) []byte { - b = removeUnderscores(b) + var suffix bool + b, suffix = removeUnderscoresAndSuffix(b) if len(b) <= 2 || 12 < len(b) || len(b) == 12 && ('D' < b[2] && b[2] <= 'F' || 'd' < b[2]) { return b } @@ -1433,5 +1449,8 @@ func hexadecimalNumber(b []byte, prec int) []byte { n /= 10 i-- } + if suffix { + return append(b, 'n') + } return minify.Number(b, prec) }