Repository: babel/minify (js)

Issue:
Number literal minification is suboptimal
Tested in the online repl:

Input:

```js
console.log(11000);
console.log(110000);
```

Expected output:

```js
console.log(11e3),console.log(11e4);
```

Actual output:

```js
console.log(11000),console.log(1.1e5);
```

Pull request:
Refactor minify-numeric-literals.
I went ahead and rewrote the test suite for minify-numeric-literals, and came across a number of issues:

- `0xa` should transform to `10`, instead of `0xa`
- `0x64` should transform to `100` instead of `1e2` (opinionated, better gzip?)
- `0o12` should transform to `10` instead of `1e1`
- `0o144` should transform to `100` instead of `1e2` (opinionated, better gzip?)
- `0b1010` should transform to `10` instead of `1e1`
- `0b1100100` should transform to `100` instead of `1e2` (opinionated, better gzip?)
- `0.123456` should transform to `.123456` instead of `0.123456`
- `1.5e3` should transform to `1500` instead of `1.5e3`
- `1e-1` should transform to `.1`  instead of `1e-1`
- `1e-2` should transform to `.01`  instead of `1e-2`
- `1e-3` should transform to `.001`  instead of `1e-3`  (opinionated, better gzip?)
- `1.5e-3` should transform to `.0015` instead of `1.5e-3`

I investigated several different ways of writing logic to solve this, but the simplest way I can find is to compare the length of `.toString()` and `.toExponential()` and to choose the shortest. Additionally I've removed the `.replaceWith` in favor of editing `path.node.extra.raw` in-place. This prevents the NumericLiteral from being re-entered immediately, but I'm unsure if this is good practice or not.

##

This PR has now been rewritten a little and incorporates the optimisations from #467.

Closes #467 and fixes #459.

Patch:
diff --git a/packages/babel-plugin-minify-numeric-literals/src/index.js b/packages/babel-plugin-minify-numeric-literals/src/index.js
index 1fa9ec9..f244700 100644
--- a/packages/babel-plugin-minify-numeric-literals/src/index.js
+++ b/packages/babel-plugin-minify-numeric-literals/src/index.js
@@ -1,24 +1,36 @@
 "use strict";
 
-module.exports = function({ types: t }) {
+module.exports = function() {
   return {
     name: "minify-numeric-literals",
     visitor: {
       NumericLiteral(path) {
         if (!path.node.extra) return;
 
-        const exponential = path.node.value
-          .toExponential()
-          .replace(/\+/g, "")
-          .replace(/e0/, "");
+        const normal = path.node.value.toString().replace(/^0\./, ".");
+        let exponential = path.node.value.toExponential().replace(/\+/g, "");
 
-        if (path.node.extra.raw.length > exponential.length) {
-          const literal = t.numericLiteral(path.node.value);
-          literal.extra = {
-            raw: exponential,
-            rawValue: path.node.value
-          };
-          path.replaceWith(literal);
+        if (exponential.indexOf(".") >= 0 && exponential.indexOf("e") >= 0) {
+          const lastChar = exponential.substr(exponential.lastIndexOf("e") + 1);
+          const dotIndex = exponential.lastIndexOf(".") + 1;
+          const subLength = exponential.substr(
+            dotIndex,
+            exponential.lastIndexOf("e") - dotIndex
+          ).length;
+          exponential = (exponential.substr(
+            0,
+            exponential.lastIndexOf("e") + 1
+          ) +
+            (lastChar - subLength))
+            .replace(".", "")
+            .replace(/e0/, "");
+        }
+
+        const replacement =
+          normal.length > exponential.length ? exponential : normal;
+
+        if (path.node.extra.raw.length > replacement.length) {
+          path.node.extra.raw = replacement;
         }
       }
     }


Test patch:
diff --git a/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js b/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js
index 5b93137..383194f 100644
--- a/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js
+++ b/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js
@@ -6,23 +6,59 @@ const thePlugin = require("../../../utils/test-transform")(
 
 describe("numeric-literals", () => {
   thePlugin(
-    "should shorten numeric literals properly",
+    "should shorten integer literals correctly",
     `
-    [10, 100, 1000, 10000, -2, -30000];
-    [1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1];
-    [0x000001, 0o23420, 0b10011100010000];
+    [1, 10, 100, 1000, 10000, -1, -10, -100, -1000, -10000];
+    [0x1, 0xa, 0x64, 0x3e8, 0xfffffff, -0x1, -0xa, -0x64, -0x3e8, -0xfffffff];
+    [0o1, 0o12, 0o144, 0o1750, -0o1, -0o12, -0o144, -0o1750];
+    [0b1, 0b1010, 0b1100100, 0b1111101000, -0b1, -0b1010, -0b1100100, -0b1111101000]
   `,
     `
-    [10, 100, 1e3, 1e4, -2, -3e4];
-    [1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1];
-    [1, 1e4, 1e4];
+    [1, 10, 100, 1e3, 1e4, -1, -10, -100, -1e3, -1e4];
+    [1, 10, 100, 1e3, 0xfffffff, -1, -10, -100, -1e3, -0xfffffff];
+    [1, 10, 100, 1e3, -1, -10, -100, -1e3];
+    [1, 10, 100, 1e3, -1, -10, -100, -1e3];
+  `
+  );
+
+  thePlugin(
+    "should shorten floats correctly",
+    `
+    [.123456, 1.23456, 12.3456, -0.123456, -1.23456, -12.3456];
+    [0.10, 0.010, 0.0010];
+  `,
+    `
+    [.123456, 1.23456, 12.3456, -.123456, -1.23456, -12.3456];
+    [.1, .01, .001];
+  `
+  );
+
+  thePlugin(
+    "should shorten existing exponential literals correctly",
+    `
+    [1e1, 1e2, 1.5e3, -1e1, -1e2, -1.5e3, 1e-1, 1e-2, 1.5e-3, 1e-4];
+    [1.5e4, 15e-2, 1.5e-4];
+  `,
+    `
+    [10, 1e2, 1500, -10, -1e2, -1500, .1, .01, .0015, 1e-4];
+    [15e3, .15, 15e-5];
+  `
+  );
+
+  thePlugin(
+    "should represent literals in exponential form when optimal",
+    `
+    [123000, 12345600000];
+  `,
+    `
+    [123e3, 123456e5];
   `
   );
 
   // TODO: this seems to be specific to how Babel output numbers
   // for some reason it adds + in the beginning
   thePlugin.skip(
-    "should have correct signs",
+    "should handle extreme float resolution correctly",
     `
     [+0.000000000001, -0.00000000001];
   `,