Bug 1406311 - memoize number formatters in devtools l10n.js;r=ochameau draft
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 06 Oct 2017 14:59:39 +0200
changeset 680928 4f27feffb8fe6c2206354051406b8ca3cc693dca
parent 680783 ae1f637c955d04703ea67975f658054c88809f9c
child 680929 e9cb0cbb6bedd29a506f36fe35eb37772a82ce3c
push id84682
push userjdescottes@mozilla.com
push dateMon, 16 Oct 2017 16:12:33 +0000
reviewersochameau
bugs1406311
milestone58.0a1
Bug 1406311 - memoize number formatters in devtools l10n.js;r=ochameau MozReview-Commit-ID: 7YIeimLREGg
devtools/shared/l10n.js
--- a/devtools/shared/l10n.js
+++ b/devtools/shared/l10n.js
@@ -30,16 +30,32 @@ const reqShared = require.context("raw!d
                                   true, /^.*\.properties$/);
 const reqClient = require.context("raw!devtools/client/locales/",
                                   true, /^.*\.properties$/);
 const reqShim = require.context("raw!devtools/shim/locales/",
                                   true, /^.*\.properties$/);
 const reqGlobal = require.context("raw!toolkit/locales/",
                                   true, /^.*\.properties$/);
 
+// Map used to memoize Number formatters.
+const numberFormatters = new Map();
+const getNumberFormatter = function (decimals) {
+  let formatter = numberFormatters.get(decimals);
+  if (!formatter) {
+    // Create and memoize a formatter for the provided decimals
+    formatter = Intl.NumberFormat(undefined, {
+      maximumFractionDigits: decimals,
+      minimumFractionDigits: decimals
+    });
+    numberFormatters.set(decimals, formatter);
+  }
+
+  return formatter;
+};
+
 /**
  * Memoized getter for properties files that ensures a given url is only required and
  * parsed once.
  *
  * @param {String} url
  *        The URL of the properties file to parse.
  * @return {Object} parsed properties mapped in an object.
  */
@@ -139,28 +155,28 @@ LocalizationHelper.prototype = {
     if (number === (number|0)) {
       return number;
     }
     // If this isn't a number (and yes, `isNaN(null)` is false), return zero.
     if (isNaN(number) || number === null) {
       return "0";
     }
 
-    let localized = number.toLocaleString();
+    // Localize the number using a memoized Intl.NumberFormat formatter.
+    let localized = getNumberFormatter(decimals).format(number);
 
-    // If no grouping or decimal separators are available, bail out, because
-    // padding with zeros at the end of the string won't make sense anymore.
-    if (!localized.match(/[^\d]/)) {
-      return localized;
+    // Convert the localized number to a number again.
+    let localizedNumber = localized * 1;
+    // Check if this number is now equal to an integer.
+    if (localizedNumber === (localizedNumber|0)) {
+    // If it is, remove the fraction part.
+      return getNumberFormatter(0).format(localizedNumber);
     }
 
-    return number.toLocaleString(undefined, {
-      maximumFractionDigits: decimals,
-      minimumFractionDigits: decimals
-    });
+    return localized;
   }
 };
 
 function getPropertiesForNode(node) {
   let bundleEl = node.closest("[data-localization-bundle]");
   if (!bundleEl) {
     return null;
   }