author | Cameron McCormack <cam@mcc.id.au> |
Mon, 07 Jan 2019 02:50:05 +0000 | |
changeset 452676 | a52b66841df98457965924c2810e2a6396df896d |
parent 452675 | 2c87990aee062f3008c9e0ab792d8b6ef9c9215e |
child 452677 | 029414a7448afe97b06f3f5a9c96ceaae93c44e3 |
push id | 110948 |
push user | opoprus@mozilla.com |
push date | Mon, 07 Jan 2019 10:02:58 +0000 |
treeherder | mozilla-inbound@67d8b5c47323 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | njn |
bugs | 1517354 |
milestone | 66.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
toolkit/components/aboutmemory/content/aboutMemory.js | file | annotate | diff | comparison | revisions |
--- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -1541,18 +1541,96 @@ const kFrac1Style = { * Formats an int as a human-readable string. * * @param aN * The integer to format. * @param aOptions * Optional options object. * @return A human-readable string representing the int. */ -function formatNum(aN, aOptions) { - return aN.toLocaleString("en-US", aOptions); +function formatNum(aN, aOptions = {}) { + // Unfortunately toLocaleString is slow, so we implement a restricted + // version of it that just handles the formatting options we need in the + // above kFooStyle options objects. If toLocaleString becomes faster in the + // future, this code can be replaced with: + // + // return aN.toLocaleString("en-US", aOptions); + + if (Number.isNaN(aN)) { + return "NaN"; + } + + if (aN == Infinity) { + return "∞"; + } + + if (aN == -Infinity) { + return "-∞"; + } + + // Extract options and apply defaults. + let style = aOptions.style || "decimal"; + let percent = style == "percent"; + let minIntegerDigits = aOptions.minimumIntegerDigits || 1; + let minFractionDigits = aOptions.minimumFractionDigits || 0; + let maxFractionDigits = aOptions.maximumFractionDigits || (percent ? 1 : 3); + assert(style == "decimal" || style == "percent", "unsupported style value"); + + // Store the sign and work on the absolute number from here on. + let formattedNum = aN < 0 ? "-" : ""; + + // Delegate most of the number formatting work to toFixed and then work + // on the resulting string. + let fixedNum = Math.abs(aN * (percent ? 100 : 1)).toFixed(maxFractionDigits); + + // Split the fixed precision number into its integer and fractional parts. + let decimalPointIndex = fixedNum.indexOf("."); + let integerPart; + let fractionalPart; + if (decimalPointIndex == -1) { + integerPart = fixedNum; + fractionalPart = ""; + } else { + integerPart = fixedNum.substring(0, decimalPointIndex); + fractionalPart = fixedNum.substring(decimalPointIndex + 1); + } + + // Apply minimum and maximum digit lengths. + integerPart = integerPart.padStart(minIntegerDigits, "0"); + fractionalPart = fractionalPart.padEnd(minFractionDigits, "0"); + + let zeroIndex = fractionalPart.length; + while (zeroIndex > minFractionDigits && + fractionalPart[zeroIndex - 1] == "0") { + --zeroIndex; + } + fractionalPart = fractionalPart.substring(0, zeroIndex); + + // Insert grouping separators in the integer part. + let i = (integerPart.length % 3) || 3; + let groupedIntegerPart = integerPart.substring(0, i); + while (i < integerPart.length) { + groupedIntegerPart += ","; + groupedIntegerPart += integerPart.substring(i, i + 3); + i += 3; + } + + // Construct the formatted number. + formattedNum += groupedIntegerPart; + if (fractionalPart != "") { + formattedNum += "."; + formattedNum += fractionalPart; + } + + // Add suffix if needed. + if (percent) { + formattedNum += "%"; + } + + return formattedNum; } /** * Converts a byte count to an appropriate string representation. * * @param aBytes * The byte count. * @return The string representation.