Title: [199635] trunk
Revision
199635
Author
[email protected]
Date
2016-04-16 18:26:07 -0700 (Sat, 16 Apr 2016)

Log Message

Web Inspector: Adopt Number.prototype.toLocaleString For All Sizes and Times
https://bugs.webkit.org/show_bug.cgi?id=152033
<rdar://problem/23815589>

Reviewed by Timothy Hatcher.

Source/WebInspectorUI:

Update string formatters to localize float and percentage strings. Hook up
console message formatters to use String.standardFormatters so that console
statements (e.g. console.log("%.3f", 3.14159)) are properly formatted.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Base/Utilities.js:
(value):
tokenizeFormatString should default to 6 digits when no precision
sub-specifier is provided.

percentageString should localize formatting, and take a fraction value
(0 to 1) instead of a percentage.

secondsToString should perform special-case formatting for zero values
("0ms") instead of the general purpose float formatter.

(value.d):
Switch to parseInt to floor floating point values and support numeric strings.
Return NaN instead of zero when passed a value that can't be converted to integer.

(value.f):
Switch to parseFloat to support numeric strings, and localize formatting.
Remove precision check, as it will never be less than zero. Return NaN
instead of zero when passed a value that can't be converted to float.

(prettyFunctionName):
Convert substitutions (an arguments object) to an array before calling join.

* UserInterface/Views/ConsoleMessageView.js:
(WebInspector.ConsoleMessageView.prototype._formatWithSubstitutionString.floatFormatter):
Use String.standardFormatters.f.

(WebInspector.ConsoleMessageView.prototype._formatWithSubstitutionString.integerFormatter):
Use String.standardFormatters.d.

* UserInterface/Views/LayoutTimelineDataGridNode.js:
(WebInspector.LayoutTimelineDataGridNode.prototype.createCellContent):
(WebInspector.LayoutTimelineDataGridNode):
Use integer formatting for pixel values.

* UserInterface/Views/ProfileDataGridNode.js:
(WebInspector.ProfileDataGridNode.prototype._recalculateData):
(WebInspector.ProfileDataGridNode.prototype._totalTimeContent):
Treat percentage as a fraction from 0 to 1.

* UserInterface/Views/ResourceDetailsSidebarPanel.js:
(WebInspector.ResourceDetailsSidebarPanel.prototype._refreshImageSizeSection):
Use integer formatting for pixel values.

LayoutTests:

Add test coverage for string formatters, and additional test cases for
Number.percentageString and Number.secondsToString.

* inspector/unit-tests/number-utilities-expected.txt:
* inspector/unit-tests/number-utilities.html:
* inspector/unit-tests/string-utilities-expected.txt: Added.
* inspector/unit-tests/string-utilities.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (199634 => 199635)


--- trunk/LayoutTests/ChangeLog	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/LayoutTests/ChangeLog	2016-04-17 01:26:07 UTC (rev 199635)
@@ -1,3 +1,19 @@
+2016-04-16  Matt Baker  <[email protected]>
+
+        Web Inspector: Adopt Number.prototype.toLocaleString For All Sizes and Times
+        https://bugs.webkit.org/show_bug.cgi?id=152033
+        <rdar://problem/23815589>
+
+        Reviewed by Timothy Hatcher.
+
+        Add test coverage for string formatters, and additional test cases for
+        Number.percentageString and Number.secondsToString.
+
+        * inspector/unit-tests/number-utilities-expected.txt:
+        * inspector/unit-tests/number-utilities.html:
+        * inspector/unit-tests/string-utilities-expected.txt: Added.
+        * inspector/unit-tests/string-utilities.html: Added.
+
 2016-04-15  Myles C. Maxfield  <[email protected]>
 
         [Font Loading] Test promise gets rejected when unknown format used

Modified: trunk/LayoutTests/inspector/unit-tests/number-utilities-expected.txt (199634 => 199635)


--- trunk/LayoutTests/inspector/unit-tests/number-utilities-expected.txt	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/LayoutTests/inspector/unit-tests/number-utilities-expected.txt	2016-04-17 01:26:07 UTC (rev 199635)
@@ -14,6 +14,7 @@
 FAIL: constrain of NaN becomes min
 
 -- Running test case: Number.secondsToString
+PASS: normal resolution of 0ms should be ms with no decimals
 PASS: normal resolution of sub 1ms should be ms
 PASS: normal resolution of sub 10ms should be ms
 PASS: normal resolution of sub 100ms should be ms
@@ -25,6 +26,7 @@
 PASS: normal resolution of greater than 1hr but sub 1 day should be hrs
 PASS: normal resolution of greater than 1 day should be days
 PASS: normal resolution of greater than 1 day should be days
+PASS: high resolution of 0ms should be ms with no decimals
 PASS: high resolution of sub 1ms should be ms with decimals
 PASS: high resolution of sub 10ms should be ms with decimals
 PASS: high resolution of sub 100ms should be ms with decimals
@@ -46,3 +48,6 @@
 PASS: high resolution of sub 10mb should be megabytes
 PASS: high resolution of greater than 10mb should be megabytes
 
+-- Running test case: Number.percentageString
+PASS: precision should default to 1 if unspecified
+

Modified: trunk/LayoutTests/inspector/unit-tests/number-utilities.html (199634 => 199635)


--- trunk/LayoutTests/inspector/unit-tests/number-utilities.html	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/LayoutTests/inspector/unit-tests/number-utilities.html	2016-04-17 01:26:07 UTC (rev 199635)
@@ -32,6 +32,7 @@
         name: "Number.secondsToString",
         test: () => {
             // Normal resolution.
+            InspectorTest.expectThat(Number.secondsToString(0, false) === "0ms", "normal resolution of 0ms should be ms with no decimals");
             InspectorTest.expectThat(Number.secondsToString(0.000123456, false) === "0.12ms", "normal resolution of sub 1ms should be ms");
             InspectorTest.expectThat(Number.secondsToString(0.00123456, false) === "1.23ms", "normal resolution of sub 10ms should be ms");
             InspectorTest.expectThat(Number.secondsToString(0.0123456, false) === "12.3ms", "normal resolution of sub 100ms should be ms");
@@ -45,6 +46,7 @@
             InspectorTest.expectThat(Number.secondsToString(1234567, false) === "14.3 days", "normal resolution of greater than 1 day should be days");
 
             // High resolution.
+            InspectorTest.expectThat(Number.secondsToString(0, true) === "0ms", "high resolution of 0ms should be ms with no decimals");
             InspectorTest.expectThat(Number.secondsToString(0.000123456, true) === "0.123ms", "high resolution of sub 1ms should be ms with decimals");
             InspectorTest.expectThat(Number.secondsToString(0.00123456, true) === "1.235ms", "high resolution of sub 10ms should be ms with decimals");
             InspectorTest.expectThat(Number.secondsToString(0.0123456, true) === "12.35ms", "high resolution of sub 100ms should be ms with decimals");
@@ -82,6 +84,15 @@
         }
     });
 
+    suite.addTestCase({
+        name: "Number.percentageString",
+        test: () => {
+            InspectorTest.expectThat(Number.percentageString(1 / 3) === "33.3%", "precision should default to 1 if unspecified");
+
+            return true;
+        }
+    });
+
     suite.runTestCasesAndFinish();
 }
 </script>

Added: trunk/LayoutTests/inspector/unit-tests/string-utilities-expected.txt (0 => 199635)


--- trunk/LayoutTests/inspector/unit-tests/string-utilities-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/string-utilities-expected.txt	2016-04-17 01:26:07 UTC (rev 199635)
@@ -0,0 +1,22 @@
+
+== Running test suite: StringUtilities
+-- Running test case: String.format
+PASS: float format specifier with no sub-specifier should show 6 decimal digits
+PASS: float format specifier with precision 0 should show 0 decimal digits
+PASS: float format specifier with precision 1 should show 1 decimal digit
+PASS: float format specifier with precision 2 should show 2 decimal digits
+PASS: float format specifier with precision 3 should show 3 decimal digits
+PASS: float format specifier with precision 4 should show 4 decimal digits
+PASS: float format specifier with precision 5 should show 5 decimal digits
+PASS: float format specifier with precision 6 should show 6 decimal digits
+PASS: float format specifier with precision 7 should show 7 decimal digits
+PASS: float format specifier with precision 8 should show 8 decimal digits
+PASS: float format specifier with precision 9 should show 9 decimal digits
+PASS: float format specifier with string argument should attempt conversion to float
+PASS: float format specifier with Infinity argument should show "∞"
+PASS: float format specifier with NaN argument should show "NaN"
+PASS: integer format specifier with float argument should convert to integer
+PASS: integer format specifier with string argument should attempt conversion to integer
+PASS: integer format specifier with Infinity argument should show "NaN"
+PASS: integer format specifier with NaN argument should show "NaN"
+

Added: trunk/LayoutTests/inspector/unit-tests/string-utilities.html (0 => 199635)


--- trunk/LayoutTests/inspector/unit-tests/string-utilities.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/string-utilities.html	2016-04-17 01:26:07 UTC (rev 199635)
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+    let suite = InspectorTest.createSyncSuite("StringUtilities");
+
+    suite.addTestCase({
+        name: "String.format",
+        test: () => {
+            InspectorTest.expectThat("%f".format(1.23456789) === "1.234568", "float format specifier with no sub-specifier should show 6 decimal digits");
+            InspectorTest.expectThat("%.0f".format(1.23456789) === "1", "float format specifier with precision 0 should show 0 decimal digits");
+            InspectorTest.expectThat("%.1f".format(1.23456789) === "1.2", "float format specifier with precision 1 should show 1 decimal digit");
+            InspectorTest.expectThat("%.2f".format(1.23456789) === "1.23", "float format specifier with precision 2 should show 2 decimal digits");
+            InspectorTest.expectThat("%.3f".format(1.23456789) === "1.235", "float format specifier with precision 3 should show 3 decimal digits");
+            InspectorTest.expectThat("%.4f".format(1.23456789) === "1.2346", "float format specifier with precision 4 should show 4 decimal digits");
+            InspectorTest.expectThat("%.5f".format(1.23456789) === "1.23457", "float format specifier with precision 5 should show 5 decimal digits");
+            InspectorTest.expectThat("%.6f".format(1.23456789) === "1.234568", "float format specifier with precision 6 should show 6 decimal digits");
+            InspectorTest.expectThat("%.7f".format(1.23456789) === "1.2345679", "float format specifier with precision 7 should show 7 decimal digits");
+            InspectorTest.expectThat("%.8f".format(1.23456789) === "1.23456789", "float format specifier with precision 8 should show 8 decimal digits");
+            InspectorTest.expectThat("%.9f".format(1.23456789) === "1.234567890", "float format specifier with precision 9 should show 9 decimal digits");
+            InspectorTest.expectThat("%f".format("1.23456789") === "1.234568", "float format specifier with string argument should attempt conversion to float");
+            InspectorTest.expectThat("%f".format(Infinity) === "\u221E", "float format specifier with Infinity argument should show \"\u221E\"");
+            InspectorTest.expectThat("%f".format(NaN) === "NaN", "float format specifier with NaN argument should show \"NaN\"");
+
+            InspectorTest.expectThat("%d".format(137.1) === "137", "integer format specifier with float argument should convert to integer");
+            InspectorTest.expectThat("%d".format("137") === "137", "integer format specifier with string argument should attempt conversion to integer");
+            InspectorTest.expectThat("%d".format(Infinity) === "NaN", "integer format specifier with Infinity argument should show \"NaN\"");
+            InspectorTest.expectThat("%d".format(NaN) === "NaN", "integer format specifier with NaN argument should show \"NaN\"");
+            return true;
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onLoad_="runTest()">
+</body>
+</html>

Modified: trunk/Source/WebInspectorUI/ChangeLog (199634 => 199635)


--- trunk/Source/WebInspectorUI/ChangeLog	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/ChangeLog	2016-04-17 01:26:07 UTC (rev 199635)
@@ -1,5 +1,62 @@
 2016-04-16  Matt Baker  <[email protected]>
 
+        Web Inspector: Adopt Number.prototype.toLocaleString For All Sizes and Times
+        https://bugs.webkit.org/show_bug.cgi?id=152033
+        <rdar://problem/23815589>
+
+        Reviewed by Timothy Hatcher.
+
+        Update string formatters to localize float and percentage strings. Hook up
+        console message formatters to use String.standardFormatters so that console
+        statements (e.g. console.log("%.3f", 3.14159)) are properly formatted.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Base/Utilities.js:
+        (value):
+        tokenizeFormatString should default to 6 digits when no precision
+        sub-specifier is provided.
+
+        percentageString should localize formatting, and take a fraction value
+        (0 to 1) instead of a percentage.
+
+        secondsToString should perform special-case formatting for zero values
+        ("0ms") instead of the general purpose float formatter.
+
+        (value.d):
+        Switch to parseInt to floor floating point values and support numeric strings.
+        Return NaN instead of zero when passed a value that can't be converted to integer.
+
+        (value.f):
+        Switch to parseFloat to support numeric strings, and localize formatting.
+        Remove precision check, as it will never be less than zero. Return NaN
+        instead of zero when passed a value that can't be converted to float.
+
+        (prettyFunctionName):
+        Convert substitutions (an arguments object) to an array before calling join.
+
+        * UserInterface/Views/ConsoleMessageView.js:
+        (WebInspector.ConsoleMessageView.prototype._formatWithSubstitutionString.floatFormatter):
+        Use String.standardFormatters.f.
+
+        (WebInspector.ConsoleMessageView.prototype._formatWithSubstitutionString.integerFormatter):
+        Use String.standardFormatters.d.
+
+        * UserInterface/Views/LayoutTimelineDataGridNode.js:
+        (WebInspector.LayoutTimelineDataGridNode.prototype.createCellContent):
+        (WebInspector.LayoutTimelineDataGridNode):
+        Use integer formatting for pixel values.
+
+        * UserInterface/Views/ProfileDataGridNode.js:
+        (WebInspector.ProfileDataGridNode.prototype._recalculateData):
+        (WebInspector.ProfileDataGridNode.prototype._totalTimeContent):
+        Treat percentage as a fraction from 0 to 1.
+
+        * UserInterface/Views/ResourceDetailsSidebarPanel.js:
+        (WebInspector.ResourceDetailsSidebarPanel.prototype._refreshImageSizeSection):
+        Use integer formatting for pixel values.
+
+2016-04-16  Matt Baker  <[email protected]>
+
         display:inline on the tbody is causing the width of the iframe to be shrunk to the minimum size of its text.
         https://bugs.webkit.org/show_bug.cgi?id=15666
 

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (199634 => 199635)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2016-04-17 01:26:07 UTC (rev 199635)
@@ -23,8 +23,8 @@
 localizedStrings["%d \xd7 %d pixels"] = "%d \xd7 %d pixels";
 localizedStrings["%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)"] = "%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)";
 localizedStrings["%d matches"] = "%d matches";
-localizedStrings["%fpx"] = "%fpx";
-localizedStrings["%fpx\xB2"] = "%fpx\xB2";
+localizedStrings["%dpx"] = "%dpx";
+localizedStrings["%dpx\xB2"] = "%dpx\xB2";
 localizedStrings["%s (computed)"] = "%s (computed)";
 localizedStrings["%s (default)"] = "%s (default)";
 localizedStrings["%s (hidden)"] = "%s (hidden)";

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (199634 => 199635)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2016-04-17 01:26:07 UTC (rev 199635)
@@ -640,15 +640,17 @@
                 }
             }
 
-            var precision = -1;
+            const defaultPrecision = 6;
+
+            let precision = defaultPrecision;
             if (format[index] === ".") {
                 // This is a precision specifier. If no digit follows the ".",
-                // then the precision should be zero.
+                // then use the default precision of six digits (ISO C99 specification).
                 ++index;
 
                 precision = parseInt(format.substring(index), 10);
                 if (isNaN(precision))
-                    precision = 0;
+                    precision = defaultPrecision;
 
                 while (!isNaN(format[index]))
                     ++index;
@@ -715,14 +717,21 @@
     value: {
         d: function(substitution)
         {
-            return !isNaN(substitution) ? substitution : 0;
+            return parseInt(substitution);
         },
 
         f: function(substitution, token)
         {
-            if (substitution && token.precision > -1)
-                substitution = substitution.toFixed(token.precision);
-            return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
+            let value = parseFloat(substitution);
+            if (isNaN(value))
+                return NaN;
+
+            let options = {
+                minimumFractionDigits: token.precision,
+                maximumFractionDigits: token.precision,
+                useGrouping: false
+            };
+            return value.toLocaleString(undefined, options);
         },
 
         s: function(substitution)
@@ -741,7 +750,7 @@
 
         function prettyFunctionName()
         {
-            return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
+            return "String.format(\"" + format + "\", \"" + Array.from(substitutions).join("\", \"") + "\")";
         }
 
         function warn(msg)
@@ -912,10 +921,10 @@
 
 Object.defineProperty(Number, "percentageString",
 {
-    value: function(percent, precision = 1)
+    value: function(fraction, precision = 1)
     {
-        console.assert(percent >= 0 && percent <= 100);
-        return percent.toFixed(precision) + "%";
+        console.assert(fraction >= 0 && fraction <= 1);
+        return fraction.toLocaleString(undefined, {minimumFractionDigits: precision, style: "percent"});
     }
 });
 
@@ -936,6 +945,8 @@
     value: function(seconds, higherResolution)
     {
         let ms = seconds * 1000;
+        if (!ms)
+            return WebInspector.UIString("%.0fms").format(0);
 
         if (Math.abs(ms) < 10) {
             if (higherResolution)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js (199634 => 199635)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js	2016-04-17 01:26:07 UTC (rev 199635)
@@ -599,18 +599,16 @@
             return obj.description;
         }
 
-        function floatFormatter(obj)
+        function floatFormatter(obj, token)
         {
-            if (typeof obj.value !== "number")
-                return parseFloat(obj.description);
-            return obj.value;
+            let value = typeof obj.value === "number" ? obj.value : obj.description;
+            return String.standardFormatters.f(value, token);
         }
 
         function integerFormatter(obj)
         {
-            if (typeof obj.value !== "number")
-                return parseInt(obj.description);
-            return Math.floor(obj.value);
+            let value = typeof obj.value === "number" ? obj.value : obj.description;
+            return String.standardFormatters.d(value);
         }
 
         var currentStyle = null;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js (199634 => 199635)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js	2016-04-17 01:26:07 UTC (rev 199635)
@@ -68,10 +68,10 @@
 
         case "width":
         case "height":
-            return isNaN(value) ? emDash : WebInspector.UIString("%fpx").format(value);
+            return isNaN(value) ? emDash : WebInspector.UIString("%dpx").format(value);
 
         case "area":
-            return isNaN(value) ? emDash : WebInspector.UIString("%fpx²").format(value);
+            return isNaN(value) ? emDash : WebInspector.UIString("%dpx²").format(value);
 
         case "startTime":
             return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ProfileDataGridNode.js (199634 => 199635)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ProfileDataGridNode.js	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ProfileDataGridNode.js	2016-04-17 01:26:07 UTC (rev 199635)
@@ -188,14 +188,14 @@
 
         let totalTime = duration;
         let selfTime = leafDuration + this._extraSelfTimeFromChargedChildren;
-        let percent = (totalTime / this._tree.totalSampleTime) * 100;
+        let fraction = totalTime / this._tree.totalSampleTime;
 
-        this._data = {totalTime, selfTime, percent};
+        this._data = {totalTime, selfTime, fraction};
     }
 
     _totalTimeContent()
     {
-        let {totalTime, percent} = this._data;
+        let {totalTime, fraction} = this._data;
 
         let fragment = document.createDocumentFragment();
         let timeElement = fragment.appendChild(document.createElement("span"));
@@ -203,7 +203,7 @@
         timeElement.textContent = Number.secondsToMillisecondsString(totalTime);
         let percentElement = fragment.appendChild(document.createElement("span"));
         percentElement.classList.add("percentage");
-        percentElement.textContent = Number.percentageString(percent);
+        percentElement.textContent = Number.percentageString(fraction);
         return fragment;
     }
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceDetailsSidebarPanel.js (199634 => 199635)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceDetailsSidebarPanel.js	2016-04-17 01:20:00 UTC (rev 199634)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceDetailsSidebarPanel.js	2016-04-17 01:26:07 UTC (rev 199635)
@@ -416,8 +416,8 @@
 
         // Get the metrics for this resource and fill in the metrics rows with that information.
         resource.getImageSize(function(size) {
-            this._imageWidthRow.value = WebInspector.UIString("%fpx").format(size.width);
-            this._imageHeightRow.value = WebInspector.UIString("%fpx").format(size.height);
+            this._imageWidthRow.value = WebInspector.UIString("%dpx").format(size.width);
+            this._imageHeightRow.value = WebInspector.UIString("%dpx").format(size.height);
         }.bind(this));
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to