Skip to content

Commit

Permalink
fix #2162: some numbers now print slightly smaller
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Apr 7, 2022
1 parent bdee212 commit 57a75a8
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@

And the reason lowering private members requires adjusting `super()` calls is because the injected private member initializers use `this`, which is only accessible after `super()` calls in the constructor.

* Print some large integers using hexadecimal when minifying ([#2162](https://github.com/evanw/esbuild/issues/2162))

When `--minify` is active, esbuild will now use one fewer byte to represent certain large integers:

```js
// Original code
x = 123456787654321;

// Old output (with --minify)
x=123456787654321;

// New output (with --minify)
x=0x704885f926b1;
```

This works because a hexadecimal representation can be shorter than a decimal representation starting at around 10<sup>12</sup> and above.

_This optimization made me realize that there's probably an opportunity to optimize printed numbers for smaller gzipped size instead of or in addition to just optimizing for minimal uncompressed byte count. The gzip algorithm does better with repetitive sequences, so for example `0xFFFFFFFF` is probably a better representation than `4294967295` even though the byte counts are the same. As far as I know, no JavaScript minifier does this optimization yet. I don't know enough about how gzip works to know if this is a good idea or what the right metric for this might be._

* Add Linux ARM64 support for Deno ([#2156](https://github.com/evanw/esbuild/issues/2156))

This release adds Linux ARM64 support to esbuild's [Deno](https://deno.land/) API implementation, which allows esbuild to be used with Deno on a Raspberry Pi.
Expand Down
9 changes: 9 additions & 0 deletions internal/js_printer/js_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2788,6 +2788,15 @@ func (p *printer) printNonNegativeFloat(absValue float64) {
}
}

// Numbers in this range can potentially be printed with one fewer byte as hex
if p.options.MinifyWhitespace && absValue >= 1_000_000_000_000 && absValue <= 0xFFFF_FFFF_FFFF_FFFF {
if asInt := uint64(absValue); absValue == float64(asInt) {
if hex := strconv.FormatUint(asInt, 16); 2+len(hex) < len(result) {
result = append(append(result[:0], '0', 'x'), hex...)
}
}
}

p.printBytes(result)
}

Expand Down
10 changes: 10 additions & 0 deletions internal/js_printer/js_printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,16 @@ func TestNumber(t *testing.T) {
expectPrinted(t, "x = -0xffff_ffff_ffff_fbff", "x = -1844674407370955e4;\n")
expectPrinted(t, "x = -0x1_0000_0000_0000_0000", "x = -18446744073709552e3;\n")
expectPrinted(t, "x = -0x1_0000_0000_0000_1000", "x = -18446744073709556e3;\n")

// Check the hex vs. decimal decision boundary when minifying
expectPrinted(t, "x = 999999999999", "x = 999999999999;\n")
expectPrinted(t, "x = 1000000000001", "x = 1000000000001;\n")
expectPrinted(t, "x = 0xFFFFFFFFFFFFF80", "x = 1152921504606846800;\n")
expectPrinted(t, "x = 0x1000000000000000", "x = 1152921504606847e3;\n")
expectPrintedMinify(t, "x = 999999999999", "x=999999999999;")
expectPrintedMinify(t, "x = 1000000000001", "x=0xe8d4a51001;")
expectPrintedMinify(t, "x = 0xFFFFFFFFFFFFF80", "x=0xfffffffffffff80;")
expectPrintedMinify(t, "x = 0x1000000000000000", "x=1152921504606847e3;")
}

func TestArray(t *testing.T) {
Expand Down

0 comments on commit 57a75a8

Please sign in to comment.