Finish cleanup of String::number for floating point
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Jun 2019 11:34:20 +0000 (11:34 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Jun 2019 11:34:20 +0000 (11:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198471

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode): Use String::number instead of
String::numberToStringECMAScript, since that's now the default.
* parser/ParserArena.h:
(JSC::IdentifierArena::makeNumericIdentifier): Ditto.
* runtime/JSONObject.cpp:
(JSC::Stringifier::appendStringifiedValue): Use appendNumber instead of
builder.appendECMAScriptNumber, since that's now the default.
* runtime/NumberPrototype.cpp:
(JSC::toStringWithRadix): Use String::number instead of
String::numberToStringECMAScript, since that's now the default.
(JSC::numberProtoFuncToExponential): Ditto.
(JSC::numberProtoFuncToFixed): Ditto.
(JSC::numberProtoFuncToPrecision): Ditto.
(JSC::numberToStringInternal): Ditto.
* runtime/NumericStrings.h:
(JSC::NumericStrings::add): Ditto.
* wasm/WasmBBQPlan.cpp:
(JSC::Wasm::BBQPlan::prepare): Ditto.

Source/WebCore:

* css/CSSCursorImageValue.cpp:
(WebCore::CSSCursorImageValue::customCSSText const): Use makeString instead
of StringBuilder since it is more terse and possibly more efficient as well.
* css/DOMMatrixReadOnly.cpp:
(WebCore::DOMMatrixReadOnly::toString const): Ditto.
* css/WebKitCSSMatrix.cpp:
(WebCore::WebKitCSSMatrix::toString const): Ditto.

* html/parser/HTMLParserIdioms.cpp:
(WebCore::serializeForNumberType): Use String::number instead of
String::numberToStringECMAScript since that is now the default.
* html/shadow/MediaControlElementTypes.cpp:
(WebCore::MediaControlVolumeSliderElement::setVolume): Ditto.
* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlTimelineElement::setPosition): Ditto.
* platform/Decimal.cpp:
(WebCore::Decimal::fromDouble): Ditto.

* rendering/RenderListMarker.cpp:
(WebCore::toRoman): Return a String instead of taking a StringBuilder argument.
Use LetterCase enum instead of bool for the uppercase vs. lowercase argument, to
be less mysterious at call sites. Use unsigned for string lengths since that's
what WTF::String uses.
(WebCore::toAlphabeticOrNumeric): Ditto. Also updated since SequenceType is now
an enum class.
(WebCore::toSymbolic): Use String::createUninitialized instead of StringBuilder.
Return a String instead of taking a StringBuilder argument. Straighten out the
algorithm so it's easier to understand.
(WebCore::toAlphabetic): Updated since SequenceType is now an enum class.
(WebCore::toNumeric): Ditto.
(WebCore::toHebrew): Return a String instead of taking a StringBuilder argument.
Use unsigned for string lengths since that's what WTF::String uses.
(WebCore::toArmenianUnder10000): Use unsigned and the LetterCase enum class.
(WebCore::toArmenian): Return a String instead of taking a StringBuilder argument.
Also use unsigned for string lengths since that's what WTF::String uses.
(WebCore::toGeorgian): Ditto.
(WebCore::toCJKIdeographic): Ditto.
(WebCore::listMarkerSuffix): Tweaked a comment.
(WebCore::listMarkerText): Use String return values instead of StringBuilder.
(WebCore::RenderListMarker::paint): Use String::createUninitialized instead of
StringBuilder since it's a bit more efficient. Use makeString instead of turning
single characters into strings since that's more efficient.

* svg/SVGPathUtilities.cpp:
(WebCore::buildStringFromPath): Use appendNumber instead of appendShortestFormNumber
since that is now the default.

Source/WebKit:

* NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp:
(WebKit::submitTopList): Use makeString instead of StringBuilder since it
is more terse and possibly more efficient as well.
* UIProcess/API/APIUserScript.cpp:
(API::UserScript::generateUniqueURL): Ditto.
* UIProcess/API/APIUserStyleSheet.cpp:
(API::UserStyleSheet::generateUniqueURL): Ditto.

Source/WTF:

* wtf/JSONValues.cpp:
(WTF::JSONImpl::Value::writeJSON const): Use appendNumber instead of
appendECMAScriptNumber, since that's now the default.

* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::appendNumber): Renamed from appendShortestFormNumber.
* wtf/text/StringBuilder.h: Removed appendShortestFormNumber and
appendECMAScriptNumber, replacing both with overload of appendNumber.

* wtf/text/WTFString.cpp:
(WTF::String::number): Renamed from numberToStringShortest.
* wtf/text/WTFString.h: Removed numberToStringShortest and
numberToStringECMAScript, replacing both with overload of number.

Tools:

* TestWebKitAPI/Tests/WTF/WTFString.cpp:
(TestWebKitAPI::testStringNumber): Go back to calling String::number instead of
String::numberToStringECMAScript.

* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::dumpFrameScrollPosition): Use appendNumber instead of appendECMAScriptNumber
since that is now the default.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246034 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
Source/JavaScriptCore/parser/ParserArena.h
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/NumberPrototype.cpp
Source/JavaScriptCore/runtime/NumericStrings.h
Source/JavaScriptCore/wasm/WasmBBQPlan.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/JSONValues.cpp
Source/WTF/wtf/text/StringBuilder.cpp
Source/WTF/wtf/text/StringBuilder.h
Source/WTF/wtf/text/WTFString.cpp
Source/WTF/wtf/text/WTFString.h
Source/WebCore/ChangeLog
Source/WebCore/css/CSSCursorImageValue.cpp
Source/WebCore/css/DOMMatrixReadOnly.cpp
Source/WebCore/css/WebKitCSSMatrix.cpp
Source/WebCore/html/parser/HTMLParserIdioms.cpp
Source/WebCore/html/shadow/MediaControlElementTypes.cpp
Source/WebCore/html/shadow/MediaControlElements.cpp
Source/WebCore/platform/Decimal.cpp
Source/WebCore/rendering/RenderListMarker.cpp
Source/WebCore/svg/SVGPathUtilities.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp
Source/WebKit/UIProcess/API/APIUserScript.cpp
Source/WebKit/UIProcess/API/APIUserStyleSheet.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp

index 25a5e39..3c0c918 100644 (file)
@@ -1,3 +1,30 @@
+2019-06-03  Darin Adler  <darin@apple.com>
+
+        Finish cleanup of String::number for floating point
+        https://bugs.webkit.org/show_bug.cgi?id=198471
+
+        Reviewed by Yusuke Suzuki.
+
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode): Use String::number instead of
+        String::numberToStringECMAScript, since that's now the default.
+        * parser/ParserArena.h:
+        (JSC::IdentifierArena::makeNumericIdentifier): Ditto.
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::appendStringifiedValue): Use appendNumber instead of
+        builder.appendECMAScriptNumber, since that's now the default.
+        * runtime/NumberPrototype.cpp:
+        (JSC::toStringWithRadix): Use String::number instead of
+        String::numberToStringECMAScript, since that's now the default.
+        (JSC::numberProtoFuncToExponential): Ditto.
+        (JSC::numberProtoFuncToFixed): Ditto.
+        (JSC::numberProtoFuncToPrecision): Ditto.
+        (JSC::numberToStringInternal): Ditto.
+        * runtime/NumericStrings.h:
+        (JSC::NumericStrings::add): Ditto.
+        * wasm/WasmBBQPlan.cpp:
+        (JSC::Wasm::BBQPlan::prepare): Ditto.
+
 2019-06-02  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Crash explicitly if StructureIDs are exhausted
index c7fd52a..d1cde13 100644 (file)
@@ -350,7 +350,7 @@ private:
                     if (value.isInt32())
                         return String::number(value.asInt32());
                     if (value.isNumber())
-                        return String::numberToStringECMAScript(value.asNumber());
+                        return String::number(value.asNumber());
                     if (value.isBoolean())
                         return value.asBoolean() ? "true"_s : "false"_s;
                     if (value.isNull())
@@ -421,7 +421,7 @@ private:
                         if (value.isInt32())
                             result = String::number(value.asInt32());
                         else if (value.isNumber())
-                            result = String::numberToStringECMAScript(value.asNumber());
+                            result = String::number(value.asNumber());
 
                         if (!result.isNull()) {
                             convertToLazyJSValue(m_node, LazyJSValue::newString(m_graph, result));
index 67b782d..df17be5 100644 (file)
@@ -130,7 +130,9 @@ namespace JSC {
     
     inline const Identifier& IdentifierArena::makeNumericIdentifier(VM* vm, double number)
     {
-        m_identifiers.append(Identifier::fromString(vm, String::numberToStringECMAScript(number)));
+        // FIXME: Why doesn't this use the Identifier::from overload that takes a double?
+        // Seems we are missing out on multiple optimizations by not using it.
+        m_identifiers.append(Identifier::fromString(vm, String::number(number)));
         return m_identifiers.last();
     }
 
index dd12bd3..97c1045 100644 (file)
@@ -377,7 +377,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
             if (!std::isfinite(number))
                 builder.appendLiteral("null");
             else
-                builder.appendECMAScriptNumber(number);
+                builder.appendNumber(number);
         }
         return StringifySucceeded;
     }
index ab3afd0..f69e68b 100644 (file)
@@ -395,7 +395,7 @@ String toStringWithRadix(double doubleValue, int32_t radix)
         return toStringWithRadixInternal(integerValue, radix);
 
     if (radix == 10 || !std::isfinite(doubleValue))
-        return String::numberToStringECMAScript(doubleValue);
+        return String::number(doubleValue);
 
     RadixBuffer buffer;
     return toStringWithRadixInternal(buffer, doubleValue, radix);
@@ -422,7 +422,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
 
     // Handle NaN and Infinity.
     if (!std::isfinite(x))
-        return JSValue::encode(jsNontrivialString(exec, String::numberToStringECMAScript(x)));
+        return JSValue::encode(jsNontrivialString(exec, String::number(x)));
 
     if (!inRange)
         return throwVMError(exec, scope, createRangeError(exec, "toExponential() argument must be between 0 and 20"_s));
@@ -463,7 +463,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
     // This also covers Ininity, and structure the check so that NaN
     // values are also handled by numberToString
     if (!(fabs(x) < 1e+21))
-        return JSValue::encode(jsString(exec, String::numberToStringECMAScript(x)));
+        return JSValue::encode(jsString(exec, String::number(x)));
 
     // The check above will return false for NaN or Infinity, these will be
     // handled by numberToString.
@@ -496,11 +496,11 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
 
     // To precision called with no argument is treated as ToString.
     if (isUndefined)
-        return JSValue::encode(jsString(exec, String::numberToStringECMAScript(x)));
+        return JSValue::encode(jsString(exec, String::number(x)));
 
     // Handle NaN and Infinity.
     if (!std::isfinite(x))
-        return JSValue::encode(jsNontrivialString(exec, String::numberToStringECMAScript(x)));
+        return JSValue::encode(jsNontrivialString(exec, String::number(x)));
 
     if (!inRange)
         return throwVMError(exec, scope, createRangeError(exec, "toPrecision() argument must be between 1 and 21"_s));
@@ -537,7 +537,7 @@ static ALWAYS_INLINE JSString* numberToStringInternal(VM& vm, double doubleValue
         return jsString(&vm, vm.numericStrings.add(doubleValue));
 
     if (!std::isfinite(doubleValue))
-        return jsNontrivialString(&vm, String::numberToStringECMAScript(doubleValue));
+        return jsNontrivialString(&vm, String::number(doubleValue));
 
     RadixBuffer buffer;
     return jsString(&vm, toStringWithRadixInternal(buffer, doubleValue, radix));
index 86c5c38..ca93f47 100644 (file)
@@ -39,7 +39,7 @@ public:
         if (d == entry.key && !entry.value.isNull())
             return entry.value;
         entry.key = d;
-        entry.value = String::numberToStringECMAScript(d);
+        entry.value = String::number(d);
         return entry.value;
     }
 
index fe09d33..0b38f9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,7 +45,7 @@
 #include <wtf/MonotonicTime.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/SystemTracing.h>
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 
 namespace JSC { namespace Wasm {
 
@@ -151,11 +151,7 @@ void BBQPlan::prepare()
 
     auto tryReserveCapacity = [this] (auto& vector, size_t size, const char* what) {
         if (UNLIKELY(!vector.tryReserveCapacity(size))) {
-            StringBuilder builder;
-            builder.appendLiteral("Failed allocating enough space for ");
-            builder.appendNumber(size);
-            builder.append(what);
-            fail(holdLock(m_lock), builder.toString());
+            fail(holdLock(m_lock), WTF::makeString("Failed allocating enough space for ", size, what));
             return false;
         }
         return true;
index 8346686..1c0a101 100644 (file)
@@ -1,3 +1,24 @@
+2019-06-03  Darin Adler  <darin@apple.com>
+
+        Finish cleanup of String::number for floating point
+        https://bugs.webkit.org/show_bug.cgi?id=198471
+
+        Reviewed by Yusuke Suzuki.
+
+        * wtf/JSONValues.cpp:
+        (WTF::JSONImpl::Value::writeJSON const): Use appendNumber instead of
+        appendECMAScriptNumber, since that's now the default.
+
+        * wtf/text/StringBuilder.cpp:
+        (WTF::StringBuilder::appendNumber): Renamed from appendShortestFormNumber.
+        * wtf/text/StringBuilder.h: Removed appendShortestFormNumber and
+        appendECMAScriptNumber, replacing both with overload of appendNumber.
+
+        * wtf/text/WTFString.cpp:
+        (WTF::String::number): Renamed from numberToStringShortest.
+        * wtf/text/WTFString.h: Removed numberToStringShortest and
+        numberToStringECMAScript, replacing both with overload of number.
+
 2019-06-02  Keith Miller  <keith_miller@apple.com>
 
         Reenable Gigacage on ARM64.
index 829acca..8681a88 100644 (file)
@@ -680,7 +680,7 @@ void Value::writeJSON(StringBuilder& output) const
         if (!std::isfinite(m_value.number))
             output.appendLiteral("null");
         else
-            output.appendECMAScriptNumber(m_value.number);
+            output.appendNumber(m_value.number);
         break;
     }
     default:
index e3d3542..da1d4a4 100644 (file)
@@ -415,13 +415,13 @@ void StringBuilder::appendFixedPrecisionNumber(double number, unsigned precision
     append(numberToFixedPrecisionString(number, precision, buffer, policy == TruncateTrailingZeros));
 }
 
-void StringBuilder::appendShortestFormNumber(float number)
+void StringBuilder::appendNumber(float number)
 {
     NumberToStringBuffer buffer;
     append(numberToString(number, buffer));
 }
 
-void StringBuilder::appendShortestFormNumber(double number)
+void StringBuilder::appendNumber(double number)
 {
     NumberToStringBuffer buffer;
     append(numberToString(number, buffer));
index ebaf73e..fe4c532 100644 (file)
@@ -222,21 +222,14 @@ public:
     WTF_EXPORT_PRIVATE void appendNumber(unsigned long);
     WTF_EXPORT_PRIVATE void appendNumber(long long);
     WTF_EXPORT_PRIVATE void appendNumber(unsigned long long);
-    // FIXME: Change to call appendShortestFormNumber.
-    void appendNumber(float) = delete;
-    void appendNumber(double) = delete;
+    WTF_EXPORT_PRIVATE void appendNumber(float);
+    WTF_EXPORT_PRIVATE void appendNumber(double);
 
-    WTF_EXPORT_PRIVATE void appendShortestFormNumber(float);
-    WTF_EXPORT_PRIVATE void appendShortestFormNumber(double);
     WTF_EXPORT_PRIVATE void appendFixedPrecisionNumber(float, unsigned precision = 6, TrailingZerosTruncatingPolicy = TruncateTrailingZeros);
     WTF_EXPORT_PRIVATE void appendFixedPrecisionNumber(double, unsigned precision = 6, TrailingZerosTruncatingPolicy = TruncateTrailingZeros);
     WTF_EXPORT_PRIVATE void appendFixedWidthNumber(float, unsigned decimalPlaces);
     WTF_EXPORT_PRIVATE void appendFixedWidthNumber(double, unsigned decimalPlaces);
 
-    // FIXME: Delete in favor of the name appendShortestFormNumber or just appendNumber.
-    void appendECMAScriptNumber(float) = delete;
-    void appendECMAScriptNumber(double);
-
     String toString()
     {
         if (!m_string.isNull()) {
@@ -394,11 +387,6 @@ ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>()
     return m_bufferCharacters16;
 }
 
-inline void StringBuilder::appendECMAScriptNumber(double number)
-{
-    appendShortestFormNumber(number);
-}
-
 template <typename CharType>
 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length)
 {
index f5acba8..e5c18fe 100644 (file)
@@ -491,13 +491,13 @@ String String::numberToStringFixedPrecision(double number, unsigned precision, T
     return numberToFixedPrecisionString(number, precision, buffer, trailingZerosTruncatingPolicy == TruncateTrailingZeros);
 }
 
-String String::numberToStringShortest(float number)
+String String::number(float number)
 {
     NumberToStringBuffer buffer;
     return numberToString(number, buffer);
 }
 
-String String::numberToStringShortest(double number)
+String String::number(double number)
 {
     NumberToStringBuffer buffer;
     return numberToString(number, buffer);
index 007ac57..9a753ad 100644 (file)
@@ -124,12 +124,10 @@ public:
     WTF_EXPORT_PRIVATE String(ASCIILiteral);
 
     // Construct a string from a constant string literal.
-    // This constructor is the "big" version, as it put the length in the function call and generate bigger code.
+    // This is the "big" version: puts the length in the function call and generates bigger code.
     enum ConstructFromLiteralTag { ConstructFromLiteral };
     template<unsigned characterCount> String(const char (&characters)[characterCount], ConstructFromLiteralTag) : m_impl(StringImpl::createFromLiteral<characterCount>(characters)) { }
 
-    // FIXME: Why do we have to define these explicitly given that we just want the default versions?
-    // We have verified empirically that we do.
     String(const String&) = default;
     String(String&&) = default;
     String& operator=(const String&) = default;
@@ -179,21 +177,14 @@ public:
     WTF_EXPORT_PRIVATE static String number(unsigned long);
     WTF_EXPORT_PRIVATE static String number(long long);
     WTF_EXPORT_PRIVATE static String number(unsigned long long);
-    // FIXME: Change to call numberToStringShortest.
-    static String number(float) = delete;
-    static String number(double) = delete;
+    WTF_EXPORT_PRIVATE static String number(float);
+    WTF_EXPORT_PRIVATE static String number(double);
 
-    WTF_EXPORT_PRIVATE static String numberToStringShortest(float);
-    WTF_EXPORT_PRIVATE static String numberToStringShortest(double);
     WTF_EXPORT_PRIVATE static String numberToStringFixedPrecision(float, unsigned precision = 6, TrailingZerosTruncatingPolicy = TruncateTrailingZeros);
     WTF_EXPORT_PRIVATE static String numberToStringFixedPrecision(double, unsigned precision = 6, TrailingZerosTruncatingPolicy = TruncateTrailingZeros);
     WTF_EXPORT_PRIVATE static String numberToStringFixedWidth(float, unsigned decimalPlaces);
     WTF_EXPORT_PRIVATE static String numberToStringFixedWidth(double, unsigned decimalPlaces);
 
-    // FIXME: Delete in favor of the name numberToStringShortest or just number.
-    static String numberToStringECMAScript(float) = delete;
-    static String numberToStringECMAScript(double);
-
     // Find a single character or string, also with match function & latin1 forms.
     size_t find(UChar character, unsigned start = 0) const { return m_impl ? m_impl->find(character, start) : notFound; }
 
@@ -654,11 +645,6 @@ template<unsigned length> inline bool startsWithLettersIgnoringASCIICase(const S
     return startsWithLettersIgnoringASCIICase(string.impl(), lowercaseLetters);
 }
 
-inline String String::numberToStringECMAScript(double number)
-{
-    return numberToStringShortest(number);
-}
-
 inline namespace StringLiterals {
 
 inline String operator"" _str(const char* characters, size_t)
index 826bf28..5fdf650 100644 (file)
@@ -1,3 +1,57 @@
+2019-06-03  Darin Adler  <darin@apple.com>
+
+        Finish cleanup of String::number for floating point
+        https://bugs.webkit.org/show_bug.cgi?id=198471
+
+        Reviewed by Yusuke Suzuki.
+
+        * css/CSSCursorImageValue.cpp:
+        (WebCore::CSSCursorImageValue::customCSSText const): Use makeString instead
+        of StringBuilder since it is more terse and possibly more efficient as well.
+        * css/DOMMatrixReadOnly.cpp:
+        (WebCore::DOMMatrixReadOnly::toString const): Ditto.
+        * css/WebKitCSSMatrix.cpp:
+        (WebCore::WebKitCSSMatrix::toString const): Ditto.
+
+        * html/parser/HTMLParserIdioms.cpp:
+        (WebCore::serializeForNumberType): Use String::number instead of
+        String::numberToStringECMAScript since that is now the default.
+        * html/shadow/MediaControlElementTypes.cpp:
+        (WebCore::MediaControlVolumeSliderElement::setVolume): Ditto.
+        * html/shadow/MediaControlElements.cpp:
+        (WebCore::MediaControlTimelineElement::setPosition): Ditto.
+        * platform/Decimal.cpp:
+        (WebCore::Decimal::fromDouble): Ditto.
+
+        * rendering/RenderListMarker.cpp:
+        (WebCore::toRoman): Return a String instead of taking a StringBuilder argument.
+        Use LetterCase enum instead of bool for the uppercase vs. lowercase argument, to
+        be less mysterious at call sites. Use unsigned for string lengths since that's
+        what WTF::String uses.
+        (WebCore::toAlphabeticOrNumeric): Ditto. Also updated since SequenceType is now
+        an enum class.
+        (WebCore::toSymbolic): Use String::createUninitialized instead of StringBuilder.
+        Return a String instead of taking a StringBuilder argument. Straighten out the
+        algorithm so it's easier to understand.
+        (WebCore::toAlphabetic): Updated since SequenceType is now an enum class.
+        (WebCore::toNumeric): Ditto.
+        (WebCore::toHebrew): Return a String instead of taking a StringBuilder argument.
+        Use unsigned for string lengths since that's what WTF::String uses.
+        (WebCore::toArmenianUnder10000): Use unsigned and the LetterCase enum class.
+        (WebCore::toArmenian): Return a String instead of taking a StringBuilder argument.
+        Also use unsigned for string lengths since that's what WTF::String uses.
+        (WebCore::toGeorgian): Ditto.
+        (WebCore::toCJKIdeographic): Ditto.
+        (WebCore::listMarkerSuffix): Tweaked a comment.
+        (WebCore::listMarkerText): Use String return values instead of StringBuilder.
+        (WebCore::RenderListMarker::paint): Use String::createUninitialized instead of
+        StringBuilder since it's a bit more efficient. Use makeString instead of turning
+        single characters into strings since that's more efficient.
+
+        * svg/SVGPathUtilities.cpp:
+        (WebCore::buildStringFromPath): Use appendNumber instead of appendShortestFormNumber
+        since that is now the default.
+
 2019-06-03  Zan Dobersek  <zdobersek@igalia.com>
 
         [Nicosia] Disable async scrolling until implemented
index 33a529e..f157aaf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2006 Rob Buis <buis@kde.org>
  *           (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -54,15 +54,10 @@ CSSCursorImageValue::~CSSCursorImageValue()
 
 String CSSCursorImageValue::customCSSText() const
 {
-    StringBuilder result;
-    result.append(m_imageValue.get().cssText());
-    if (m_hasHotSpot) {
-        result.append(' ');
-        result.appendNumber(m_hotSpot.x());
-        result.append(' ');
-        result.appendNumber(m_hotSpot.y());
-    }
-    return result.toString();
+    String text = m_imageValue.get().cssText();
+    if (!m_hasHotSpot)
+        return text;
+    return makeString(text, ' ', m_hotSpot.x(), ' ', m_hotSpot.y());
 }
 
 // FIXME: Should this function take a TreeScope instead?
index 656641b..5d8955d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -404,56 +404,10 @@ ExceptionOr<String> DOMMatrixReadOnly::toString() const
     if (!m_matrix.containsOnlyFiniteValues())
         return Exception { InvalidStateError, "Matrix contains non-finite values"_s };
 
-    StringBuilder builder;
-    if (is2D()) {
-        builder.appendLiteral("matrix(");
-        builder.appendECMAScriptNumber(m_matrix.a());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.b());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.c());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.d());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.e());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.f());
-    } else {
-        builder.appendLiteral("matrix3d(");
-        builder.appendECMAScriptNumber(m_matrix.m11());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m12());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m13());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m14());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m21());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m22());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m23());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m24());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m31());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m32());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m33());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m34());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m41());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m42());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m43());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m44());
-    }
-    builder.append(')');
-    return builder.toString();
+    if (is2D())
+        return makeString("matrix(", m_matrix.a(), ", ", m_matrix.b(), ", ", m_matrix.c(), ", ", m_matrix.d(), ", ", m_matrix.e(), ", ", m_matrix.f(), ')');
+
+    return makeString("matrix3d(", m_matrix.m11(), ", ", m_matrix.m12(), ", ", m_matrix.m13(), ", ", m_matrix.m14(), ", ", m_matrix.m21(), ", ", m_matrix.m22(), ", ", m_matrix.m23(), ", ", m_matrix.m24(), ", ", m_matrix.m31(), ", ", m_matrix.m32(), ", ", m_matrix.m33(), ", ", m_matrix.m34(), ", ", m_matrix.m41(), ", ", m_matrix.m42(), ", ", m_matrix.m43(), ", ", m_matrix.m44(), ')');
 }
 
 } // namespace WebCore
index 2b301e9..d3e8600 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,7 +35,7 @@
 #include "TransformFunctions.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/MathExtras.h>
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 
 namespace WebCore {
 
@@ -203,56 +203,10 @@ ExceptionOr<String> WebKitCSSMatrix::toString() const
     if (!m_matrix.containsOnlyFiniteValues())
         return Exception { InvalidStateError, "Matrix contains non-finite values"_s };
 
-    StringBuilder builder;
-    if (m_matrix.isAffine()) {
-        builder.appendLiteral("matrix(");
-        builder.appendECMAScriptNumber(m_matrix.a());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.b());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.c());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.d());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.e());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.f());
-    } else {
-        builder.appendLiteral("matrix3d(");
-        builder.appendECMAScriptNumber(m_matrix.m11());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m12());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m13());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m14());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m21());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m22());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m23());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m24());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m31());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m32());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m33());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m34());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m41());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m42());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m43());
-        builder.appendLiteral(", ");
-        builder.appendECMAScriptNumber(m_matrix.m44());
-    }
-    builder.append(')');
-    return builder.toString();
+    if (m_matrix.isAffine())
+        return makeString("matrix(", m_matrix.a(), ", ", m_matrix.b(), ", ", m_matrix.c(), ", ", m_matrix.d(), ", ", m_matrix.e(), ", ", m_matrix.f(), ')');
+
+    return makeString("matrix3d(", m_matrix.m11(), ", ", m_matrix.m12(), ", ", m_matrix.m13(), ", ", m_matrix.m14(), ", ", m_matrix.m21(), ", ", m_matrix.m22(), ", ", m_matrix.m23(), ", ", m_matrix.m24(), ", ", m_matrix.m31(), ", ", m_matrix.m32(), ", ", m_matrix.m33(), ", ", m_matrix.m34(), ", ", m_matrix.m41(), ", ", m_matrix.m42(), ", ", m_matrix.m43(), ", ", m_matrix.m44(), ')');
 }
 
 } // namespace WebCore
index 3991e75..5442e0c 100644 (file)
@@ -89,7 +89,7 @@ String serializeForNumberType(double number)
 {
     // According to HTML5, "the best representation of the number n as a floating
     // point number" is a string produced by applying ToString() to n.
-    return String::numberToStringECMAScript(number);
+    return String::number(number);
 }
 
 Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbackValue)
index d2891a7..26aaa15 100644 (file)
@@ -242,7 +242,7 @@ bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents()
 void MediaControlVolumeSliderElement::setVolume(double volume)
 {
     if (value().toDouble() != volume)
-        setValue(String::numberToStringECMAScript(volume));
+        setValue(String::number(volume));
 }
 
 void MediaControlVolumeSliderElement::setClearMutedOnUserInteraction(bool clearMute)
index 7fa4ab6..089e139 100644 (file)
@@ -909,7 +909,7 @@ bool MediaControlTimelineElement::willRespondToMouseClickEvents()
 
 void MediaControlTimelineElement::setPosition(double currentTime)
 {
-    setValue(String::numberToStringECMAScript(currentTime));
+    setValue(String::number(currentTime));
 }
 
 void MediaControlTimelineElement::setDuration(double duration)
index b1ac659..0b21104 100644 (file)
@@ -681,8 +681,11 @@ Decimal Decimal::floor() const
 
 Decimal Decimal::fromDouble(double doubleValue)
 {
-    if (std::isfinite(doubleValue))
-        return fromString(String::numberToStringECMAScript(doubleValue));
+    if (std::isfinite(doubleValue)) {
+        // FIXME: Change fromString to take a StringView instead of a String and then
+        // use a fixed size stack buffer instead of allocating and deallocating a string.
+        return fromString(String::number(doubleValue));
+    }
 
     if (std::isinf(doubleValue))
         return infinity(doubleValue < 0 ? Negative : Positive);
index 4f78f83..ce019ba 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
  * Copyright (C) 2010 Daniel Bates (dbates@intudata.com)
  *
@@ -34,7 +34,7 @@
 #include "RenderView.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/StackStats.h>
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 #include <wtf/unicode/CharacterNames.h>
 
 namespace WebCore {
@@ -45,9 +45,10 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(RenderListMarker);
 
 const int cMarkerPadding = 7;
 
-enum SequenceType { NumericSequence, AlphabeticSequence };
+enum class LetterCase { Lower, Upper };
+enum class SequenceType { Numeric, Alphabetic };
 
-static NEVER_INLINE void toRoman(StringBuilder& builder, int number, bool upper)
+static NEVER_INLINE String toRoman(int number, LetterCase letterCase)
 {
     // FIXME: CSS3 describes how to make this work for much larger numbers,
     // using overbars and special characters. It also specifies the characters
@@ -56,13 +57,13 @@ static NEVER_INLINE void toRoman(StringBuilder& builder, int number, bool upper)
 
     // Big enough to store largest roman number less than 3999 which
     // is 3888 (MMMDCCCLXXXVIII)
-    const int lettersSize = 15;
+    constexpr unsigned lettersSize = 15;
     LChar letters[lettersSize];
 
-    int length = 0;
+    unsigned length = 0;
     const LChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
     const LChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
-    const LChar* digits = upper ? udigits : ldigits;
+    const LChar* digits = letterCase == LetterCase::Upper ? udigits : ldigits;
     int d = 0;
     do {
         int num = number % 10;
@@ -80,22 +81,22 @@ static NEVER_INLINE void toRoman(StringBuilder& builder, int number, bool upper)
     } while (number);
 
     ASSERT(length <= lettersSize);
-    builder.append(&letters[lettersSize - length], length);
+    return String { &letters[lettersSize - length], length };
 }
 
-template <typename CharacterType>
-static inline void toAlphabeticOrNumeric(StringBuilder& builder, int number, const CharacterType* sequence, unsigned sequenceSize, SequenceType type)
+template<typename CharacterType>
+static inline String toAlphabeticOrNumeric(int number, const CharacterType* sequence, unsigned sequenceSize, SequenceType type)
 {
     ASSERT(sequenceSize >= 2);
 
     // Taking sizeof(number) in the expression below doesn't work with some compilers.
-    const int lettersSize = sizeof(int) * 8 + 1; // Binary is the worst case; requires one character per bit plus a minus sign.
+    constexpr unsigned lettersSize = sizeof(int) * 8 + 1; // Binary is the worst case; requires one character per bit plus a minus sign.
 
     CharacterType letters[lettersSize];
 
     bool isNegativeNumber = false;
     unsigned numberShadow = number;
-    if (type == AlphabeticSequence) {
+    if (type == SequenceType::Alphabetic) {
         ASSERT(number > 0);
         --numberShadow;
     } else if (number < 0) {
@@ -103,9 +104,9 @@ static inline void toAlphabeticOrNumeric(StringBuilder& builder, int number, con
         isNegativeNumber = true;
     }
     letters[lettersSize - 1] = sequence[numberShadow % sequenceSize];
-    int length = 1;
+    unsigned length = 1;
 
-    if (type == AlphabeticSequence) {
+    if (type == SequenceType::Alphabetic) {
         while ((numberShadow /= sequenceSize) > 0) {
             --numberShadow;
             letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize];
@@ -118,52 +119,54 @@ static inline void toAlphabeticOrNumeric(StringBuilder& builder, int number, con
         letters[lettersSize - ++length] = hyphenMinus;
 
     ASSERT(length <= lettersSize);
-    builder.append(&letters[lettersSize - length], length);
+    return String { &letters[lettersSize - length], length };
 }
 
-template <typename CharacterType>
-static NEVER_INLINE void toSymbolic(StringBuilder& builder, int number, const CharacterType* symbols, unsigned symbolsSize)
+template<typename CharacterType>
+static NEVER_INLINE String toSymbolic(int number, const CharacterType* symbols, unsigned symbolsSize)
 {
     ASSERT(number > 0);
     ASSERT(symbolsSize >= 1);
-    unsigned numberShadow = number;
-    --numberShadow;
 
-    // The asterisks list-style-type is the worst case; we show |numberShadow| asterisks.
-    builder.append(symbols[numberShadow % symbolsSize]);
-    unsigned numSymbols = numberShadow / symbolsSize;
-    while (numSymbols--)
-        builder.append(symbols[numberShadow % symbolsSize]);
+    // The asterisks list-style-type is the worst case; we show |number| asterisks.
+    CharacterType symbol = symbols[(number - 1) % symbolsSize];
+    unsigned count = (number - 1) / symbolsSize + 1;
+
+    CharacterType* characters;
+    String result = String::createUninitialized(count, characters);
+    for (unsigned i = 0; i < count; ++i)
+        characters[i] = symbol;
+    return result;
 }
 
-template <typename CharacterType>
-static NEVER_INLINE void toAlphabetic(StringBuilder& builder, int number, const CharacterType* alphabet, unsigned alphabetSize)
+template<typename CharacterType>
+static NEVER_INLINE String toAlphabetic(int number, const CharacterType* alphabet, unsigned alphabetSize)
 {
-    toAlphabeticOrNumeric(builder, number, alphabet, alphabetSize, AlphabeticSequence);
+    return toAlphabeticOrNumeric(number, alphabet, alphabetSize, SequenceType::Alphabetic);
 }
 
-template <typename CharacterType>
-static NEVER_INLINE void toNumeric(StringBuilder& builder, int number, const CharacterType* numerals, unsigned numeralsSize)
+template<typename CharacterType>
+static NEVER_INLINE String toNumeric(int number, const CharacterType* numerals, unsigned numeralsSize)
 {
-    toAlphabeticOrNumeric(builder, number, numerals, numeralsSize, NumericSequence);
+    return toAlphabeticOrNumeric(number, numerals, numeralsSize, SequenceType::Numeric);
 }
 
-template <typename CharacterType, size_t size>
-static inline void toAlphabetic(StringBuilder& builder, int number, const CharacterType(&alphabet)[size])
+template<typename CharacterType, size_t size>
+static inline String toAlphabetic(int number, const CharacterType(&alphabet)[size])
 {
-    toAlphabetic(builder, number, alphabet, size);
+    return toAlphabetic(number, alphabet, size);
 }
 
-template <typename CharacterType, size_t size>
-static inline void toNumeric(StringBuilder& builder, int number, const CharacterType(&alphabet)[size])
+template<typename CharacterType, size_t size>
+static inline String toNumeric(int number, const CharacterType(&alphabet)[size])
 {
-    toNumeric(builder, number, alphabet, size);
+    return toNumeric(number, alphabet, size);
 }
 
-template <typename CharacterType, size_t size>
-static inline void toSymbolic(StringBuilder& builder, int number, const CharacterType(&alphabet)[size])
+template<typename CharacterType, size_t size>
+static inline String toSymbolic(int number, const CharacterType(&alphabet)[size])
 {    
-    toSymbolic(builder, number, alphabet, size);
+    return toSymbolic(number, alphabet, size);
 }
 
 static NEVER_INLINE int toHebrewUnder1000(int number, UChar letters[5])
@@ -194,21 +197,20 @@ static NEVER_INLINE int toHebrewUnder1000(int number, UChar letters[5])
     return length;
 }
 
-static NEVER_INLINE void toHebrew(StringBuilder& builder, int number)
+static NEVER_INLINE String toHebrew(int number)
 {
     // FIXME: CSS3 mentions ways to make this work for much larger numbers.
     ASSERT(number >= 0 && number <= 999999);
 
     if (number == 0) {
         static const UChar hebrewZero[3] = { 0x05D0, 0x05E4, 0x05E1 };
-        builder.append(hebrewZero, 3);
-        return;
+        return String { hebrewZero, 3 };
     }
 
-    const int lettersSize = 11; // big enough for two 5-digit sequences plus a quote mark between
+    constexpr unsigned lettersSize = 11; // big enough for two 5-digit sequences plus a quote mark between
     UChar letters[lettersSize];
 
-    int length;
+    unsigned length;
     if (number < 1000)
         length = 0;
     else {
@@ -219,15 +221,15 @@ static NEVER_INLINE void toHebrew(StringBuilder& builder, int number)
     length += toHebrewUnder1000(number, letters + length);
 
     ASSERT(length <= lettersSize);
-    builder.append(letters, length);
+    return String { letters, length };
 }
 
-static NEVER_INLINE int toArmenianUnder10000(int number, bool upper, bool addCircumflex, UChar letters[9])
+static NEVER_INLINE unsigned toArmenianUnder10000(int number, LetterCase letterCase, bool addCircumflex, UChar letters[9])
 {
     ASSERT(number >= 0 && number < 10000);
-    int length = 0;
+    unsigned length = 0;
 
-    int lowerOffset = upper ? 0 : 0x0030;
+    int lowerOffset = letterCase == LetterCase::Upper ? 0 : 0x0030;
 
     if (int thousands = number / 1000) {
         if (thousands == 7) {
@@ -262,28 +264,28 @@ static NEVER_INLINE int toArmenianUnder10000(int number, bool upper, bool addCir
     return length;
 }
 
-static NEVER_INLINE void toArmenian(StringBuilder& builder, int number, bool upper)
+static NEVER_INLINE String toArmenian(int number, LetterCase letterCase)
 {
     ASSERT(number >= 1 && number <= 99999999);
 
-    const int lettersSize = 18; // twice what toArmenianUnder10000 needs
+    constexpr unsigned lettersSize = 18; // twice what toArmenianUnder10000 needs
     UChar letters[lettersSize];
 
-    int length = toArmenianUnder10000(number / 10000, upper, true, letters);
-    length += toArmenianUnder10000(number % 10000, upper, false, letters + length);
+    unsigned length = toArmenianUnder10000(number / 10000, letterCase, true, letters);
+    length += toArmenianUnder10000(number % 10000, letterCase, false, letters + length);
 
     ASSERT(length <= lettersSize);
-    builder.append(letters, length);
+    return String { letters, length };
 }
 
-static NEVER_INLINE void toGeorgian(StringBuilder& builder, int number)
+static NEVER_INLINE String toGeorgian(int number)
 {
     ASSERT(number >= 1 && number <= 19999);
 
-    const int lettersSize = 5;
+    constexpr unsigned lettersSize = 5;
     UChar letters[lettersSize];
 
-    int length = 0;
+    unsigned length = 0;
 
     if (number > 9999)
         letters[length++] = 0x10F5;
@@ -317,12 +319,12 @@ static NEVER_INLINE void toGeorgian(StringBuilder& builder, int number)
     }
 
     ASSERT(length <= lettersSize);
-    builder.append(letters, length);
+    return String { letters, length };
 }
 
 // The table uses the order from the CSS3 specification:
 // first 3 group markers, then 3 digit markers, then ten digits.
-static NEVER_INLINE void toCJKIdeographic(StringBuilder& builder, int number, const UChar table[16])
+static NEVER_INLINE String toCJKIdeographic(int number, const UChar table[16])
 {
     ASSERT(number >= 0);
 
@@ -334,13 +336,11 @@ static NEVER_INLINE void toCJKIdeographic(StringBuilder& builder, int number, co
         digit5, digit6, digit7, digit8, digit9
     };
 
-    if (number == 0) {
-        builder.append(table[digit0 - 1]);
-        return;
-    }
+    if (!number)
+        return String { &table[digit0 - 1] , 1 };
 
-    const int groupLength = 8; // 4 digits, 3 digit markers, and a group marker
-    const int bufferLength = 4 * groupLength;
+    constexpr unsigned groupLength = 8; // 4 digits, 3 digit markers, and a group marker
+    constexpr unsigned bufferLength = 4 * groupLength;
     AbstractCJKChar buffer[bufferLength] = { noChar };
 
     for (int i = 0; i < 4; ++i) {
@@ -381,16 +381,15 @@ static NEVER_INLINE void toCJKIdeographic(StringBuilder& builder, int number, co
             group[4] = noChar;
         }
 
-        if (number == 0)
+        if (!number)
             break;
     }
 
-    // Convert into characters, omitting consecutive runs of digit0 and
-    // any trailing digit0.
-    int length = 0;
+    // Convert into characters, omitting consecutive runs of digit0 and trailing digit0.
+    unsigned length = 0;
     UChar characters[bufferLength];
     AbstractCJKChar last = noChar;
-    for (int i = 0; i < bufferLength; ++i) {
+    for (unsigned i = 0; i < bufferLength; ++i) {
         AbstractCJKChar a = buffer[i];
         if (a != noChar) {
             if (a != digit0 || last != digit0)
@@ -401,7 +400,7 @@ static NEVER_INLINE void toCJKIdeographic(StringBuilder& builder, int number, co
     if (last == digit0)
         --length;
 
-    builder.append(characters, length);
+    return String { characters, length };
 }
 
 static ListStyleType effectiveListMarkerType(ListStyleType type, int value)
@@ -506,7 +505,7 @@ static ListStyleType effectiveListMarkerType(ListStyleType type, int value)
 static UChar listMarkerSuffix(ListStyleType type, int value)
 {
     // If the list-style-type cannot represent |value| because it's outside its
-    // ordinal range then we fall back to some list style that can represent |value|.
+    // ordinal range then we fall back to another list style that can represent |value|.
     ListStyleType effectiveType = effectiveListMarkerType(type, value);
 
     // Note, the following switch statement has been explicitly
@@ -604,76 +603,62 @@ static UChar listMarkerSuffix(ListStyleType type, int value)
 
 String listMarkerText(ListStyleType type, int value)
 {
-    StringBuilder builder;
-
-    // If the list-style-type, say hebrew, cannot represent |value| because it's outside
-    // its ordinal range then we fallback to some list style that can represent |value|.
+    // If the list-style-type cannot represent |value| because it's outside its
+    // ordinal range then we fall back to another list style that can represent |value|.
     switch (effectiveListMarkerType(type, value)) {
     case ListStyleType::None:
         return emptyString();
 
     case ListStyleType::Asterisks: {
         static const LChar asterisksSymbols[1] = { 0x2A };
-        toSymbolic(builder, value, asterisksSymbols);
-        break;
+        return toSymbolic(value, asterisksSymbols);
     }
     // We use the same characters for text security.
     // See RenderText::setInternalString.
     case ListStyleType::Circle:
-        builder.append(whiteBullet);
-        break;
+        return String { &whiteBullet, 1 };
     case ListStyleType::Disc:
-        builder.append(bullet);
-        break;
+        return String { &bullet, 1 };
     case ListStyleType::Footnotes: {
         static const UChar footnotesSymbols[4] = { 0x002A, 0x2051, 0x2020, 0x2021 };
-        toSymbolic(builder, value, footnotesSymbols);
-        break;
+        return toSymbolic(value, footnotesSymbols);
     }
     case ListStyleType::Square:
-        // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE
-        // instead, but I think this looks better.
-        builder.append(blackSquare);
-        break;
+        // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE instead,
+        // but we used this because we thought it looked better.
+        return String { &blackSquare, 1 };
 
     case ListStyleType::Decimal:
-        builder.appendNumber(value);
-        break;
+        return String::number(value);
 
     case ListStyleType::DecimalLeadingZero:
-        if (value < -9 || value > 9) {
-            builder.appendNumber(value);
-            break;
+        if (value >= 0 && value <= 9) {
+            LChar characters[2] = { '0', static_cast<LChar>('0' + value) }; // 00 to 09
+            return String { characters, 2 };
         }
-        if (value < 0) {
-            builder.appendLiteral("-0");
-            builder.appendNumber(-value); // -01 to -09
-            break;
+        if (value >= -9 && value <= -1) {
+            LChar characters[3] = { '-', '0', static_cast<LChar>('0' - value) }; // -01 to -09
+            return String { characters, 3 };
         }
-        builder.append('0');
-        builder.appendNumber(value); // 00 to 09
-        break;
+        return String::number(value);
 
     case ListStyleType::ArabicIndic: {
         static const UChar arabicIndicNumerals[10] = {
             0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669
         };
-        toNumeric(builder, value, arabicIndicNumerals);
-        break;
+        return toNumeric(value, arabicIndicNumerals);
     }
 
     case ListStyleType::Binary: {
         static const LChar binaryNumerals[2] = { '0', '1' };
-        toNumeric(builder, value, binaryNumerals);
-        break;
+        return toNumeric(value, binaryNumerals);
     }
 
     case ListStyleType::Bengali: {
         static const UChar bengaliNumerals[10] = {
             0x09E6, 0x09E7, 0x09E8, 0x09E9, 0x09EA, 0x09EB, 0x09EC, 0x09ED, 0x09EE, 0x09EF
         };
-        toNumeric(builder, value, bengaliNumerals);
-        break;
+        return toNumeric(value, bengaliNumerals);
     }
 
     case ListStyleType::Cambodian:
@@ -681,121 +666,104 @@ String listMarkerText(ListStyleType type, int value)
         static const UChar khmerNumerals[10] = {
             0x17E0, 0x17E1, 0x17E2, 0x17E3, 0x17E4, 0x17E5, 0x17E6, 0x17E7, 0x17E8, 0x17E9
         };
-        toNumeric(builder, value, khmerNumerals);
-        break;
+        return toNumeric(value, khmerNumerals);
     }
     case ListStyleType::Devanagari: {
         static const UChar devanagariNumerals[10] = {
             0x0966, 0x0967, 0x0968, 0x0969, 0x096A, 0x096B, 0x096C, 0x096D, 0x096E, 0x096F
         };
-        toNumeric(builder, value, devanagariNumerals);
-        break;
+        return toNumeric(value, devanagariNumerals);
     }
     case ListStyleType::Gujarati: {
         static const UChar gujaratiNumerals[10] = {
             0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA, 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
         };
-        toNumeric(builder, value, gujaratiNumerals);
-        break;
+        return toNumeric(value, gujaratiNumerals);
     }
     case ListStyleType::Gurmukhi: {
         static const UChar gurmukhiNumerals[10] = {
             0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A, 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
         };
-        toNumeric(builder, value, gurmukhiNumerals);
-        break;
+        return toNumeric(value, gurmukhiNumerals);
     }
     case ListStyleType::Kannada: {
         static const UChar kannadaNumerals[10] = {
             0x0CE6, 0x0CE7, 0x0CE8, 0x0CE9, 0x0CEA, 0x0CEB, 0x0CEC, 0x0CED, 0x0CEE, 0x0CEF
         };
-        toNumeric(builder, value, kannadaNumerals);
-        break;
+        return toNumeric(value, kannadaNumerals);
     }
     case ListStyleType::LowerHexadecimal: {
         static const LChar lowerHexadecimalNumerals[16] = {
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
         };
-        toNumeric(builder, value, lowerHexadecimalNumerals);
-        break;
+        return toNumeric(value, lowerHexadecimalNumerals);
     }
     case ListStyleType::Lao: {
         static const UChar laoNumerals[10] = {
             0x0ED0, 0x0ED1, 0x0ED2, 0x0ED3, 0x0ED4, 0x0ED5, 0x0ED6, 0x0ED7, 0x0ED8, 0x0ED9
         };
-        toNumeric(builder, value, laoNumerals);
-        break;
+        return toNumeric(value, laoNumerals);
     }
     case ListStyleType::Malayalam: {
         static const UChar malayalamNumerals[10] = {
             0x0D66, 0x0D67, 0x0D68, 0x0D69, 0x0D6A, 0x0D6B, 0x0D6C, 0x0D6D, 0x0D6E, 0x0D6F
         };
-        toNumeric(builder, value, malayalamNumerals);
-        break;
+        return toNumeric(value, malayalamNumerals);
     }
     case ListStyleType::Mongolian: {
         static const UChar mongolianNumerals[10] = {
             0x1810, 0x1811, 0x1812, 0x1813, 0x1814, 0x1815, 0x1816, 0x1817, 0x1818, 0x1819
         };
-        toNumeric(builder, value, mongolianNumerals);
-        break;
+        return toNumeric(value, mongolianNumerals);
     }
     case ListStyleType::Myanmar: {
         static const UChar myanmarNumerals[10] = {
             0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049
         };
-        toNumeric(builder, value, myanmarNumerals);
-        break;
+        return toNumeric(value, myanmarNumerals);
     }
     case ListStyleType::Octal: {
         static const LChar octalNumerals[8] = {
             '0', '1', '2', '3', '4', '5', '6', '7'
         };
-        toNumeric(builder, value, octalNumerals);
-        break;
+        return toNumeric(value, octalNumerals);
     }
     case ListStyleType::Oriya: {
         static const UChar oriyaNumerals[10] = {
             0x0B66, 0x0B67, 0x0B68, 0x0B69, 0x0B6A, 0x0B6B, 0x0B6C, 0x0B6D, 0x0B6E, 0x0B6F
         };
-        toNumeric(builder, value, oriyaNumerals);
-        break;
+        return toNumeric(value, oriyaNumerals);
     }
     case ListStyleType::Persian:
     case ListStyleType::Urdu: {
         static const UChar urduNumerals[10] = {
             0x06F0, 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5, 0x06F6, 0x06F7, 0x06F8, 0x06F9
         };
-        toNumeric(builder, value, urduNumerals);
-        break;
+        return toNumeric(value, urduNumerals);
     }
     case ListStyleType::Telugu: {
         static const UChar teluguNumerals[10] = {
             0x0C66, 0x0C67, 0x0C68, 0x0C69, 0x0C6A, 0x0C6B, 0x0C6C, 0x0C6D, 0x0C6E, 0x0C6F
         };
-        toNumeric(builder, value, teluguNumerals);
-        break;
+        return toNumeric(value, teluguNumerals);
     }
     case ListStyleType::Tibetan: {
         static const UChar tibetanNumerals[10] = {
             0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24, 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
         };
-        toNumeric(builder, value, tibetanNumerals);
-        break;
+        return toNumeric(value, tibetanNumerals);
     }
     case ListStyleType::Thai: {
         static const UChar thaiNumerals[10] = {
             0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59
         };
-        toNumeric(builder, value, thaiNumerals);
-        break;
+        return toNumeric(value, thaiNumerals);
     }
     case ListStyleType::UpperHexadecimal: {
         static const LChar upperHexadecimalNumerals[16] = {
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
         };
-        toNumeric(builder, value, upperHexadecimalNumerals);
-        break;
+        return toNumeric(value, upperHexadecimalNumerals);
     }
 
     case ListStyleType::LowerAlpha:
@@ -804,8 +772,7 @@ String listMarkerText(ListStyleType type, int value)
             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
             'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
         };
-        toAlphabetic(builder, value, lowerLatinAlphabet);
-        break;
+        return toAlphabetic(value, lowerLatinAlphabet);
     }
     case ListStyleType::UpperAlpha:
     case ListStyleType::UpperLatin: {
@@ -813,8 +780,7 @@ String listMarkerText(ListStyleType type, int value)
             'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
             'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
         };
-        toAlphabetic(builder, value, upperLatinAlphabet);
-        break;
+        return toAlphabetic(value, upperLatinAlphabet);
     }
     case ListStyleType::LowerGreek: {
         static const UChar lowerGreekAlphabet[24] = {
@@ -822,8 +788,7 @@ String listMarkerText(ListStyleType type, int value)
             0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
             0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9
         };
-        toAlphabetic(builder, value, lowerGreekAlphabet);
-        break;
+        return toAlphabetic(value, lowerGreekAlphabet);
     }
 
     case ListStyleType::Hiragana: {
@@ -837,8 +802,7 @@ String listMarkerText(ListStyleType type, int value)
             0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x308A,
             0x308B, 0x308C, 0x308D, 0x308F, 0x3090, 0x3091, 0x3092, 0x3093
         };
-        toAlphabetic(builder, value, hiraganaAlphabet);
-        break;
+        return toAlphabetic(value, hiraganaAlphabet);
     }
     case ListStyleType::HiraganaIroha: {
         // FIXME: This table comes from the CSS3 draft, and is probably
@@ -851,8 +815,7 @@ String listMarkerText(ListStyleType type, int value)
             0x3053, 0x3048, 0x3066, 0x3042, 0x3055, 0x304D, 0x3086, 0x3081,
             0x307F, 0x3057, 0x3091, 0x3072, 0x3082, 0x305B, 0x3059
         };
-        toAlphabetic(builder, value, hiraganaIrohaAlphabet);
-        break;
+        return toAlphabetic(value, hiraganaIrohaAlphabet);
     }
     case ListStyleType::Katakana: {
         // FIXME: This table comes from the CSS3 draft, and is probably
@@ -865,8 +828,7 @@ String listMarkerText(ListStyleType type, int value)
             0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA,
             0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0x30F3
         };
-        toAlphabetic(builder, value, katakanaAlphabet);
-        break;
+        return toAlphabetic(value, katakanaAlphabet);
     }
     case ListStyleType::KatakanaIroha: {
         // FIXME: This table comes from the CSS3 draft, and is probably
@@ -879,8 +841,7 @@ String listMarkerText(ListStyleType type, int value)
             0x30B3, 0x30A8, 0x30C6, 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1,
             0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x30B9
         };
-        toAlphabetic(builder, value, katakanaIrohaAlphabet);
-        break;
+        return toAlphabetic(value, katakanaIrohaAlphabet);
     }
 
     case ListStyleType::Afar:
@@ -890,8 +851,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1260, 0x1270, 0x1290,
             0x12A0, 0x12A8, 0x12C8, 0x12D0, 0x12E8, 0x12F0, 0x1308, 0x1338, 0x1348
         };
-        toAlphabetic(builder, value, ethiopicHalehameAaErAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameAaErAlphabet);
     }
     case ListStyleType::Amharic:
     case ListStyleType::EthiopicHalehameAmEt: {
@@ -901,8 +861,7 @@ String listMarkerText(ListStyleType type, int value)
             0x12C8, 0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320,
             0x1328, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicHalehameAmEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameAmEtAlphabet);
     }
     case ListStyleType::AmharicAbegede:
     case ListStyleType::EthiopicAbegedeAmEt: {
@@ -912,24 +871,21 @@ String listMarkerText(ListStyleType type, int value)
             0x1298, 0x1220, 0x12D0, 0x1348, 0x1338, 0x1240, 0x1228, 0x1230, 0x1238,
             0x1270, 0x1278, 0x1280, 0x1340, 0x1330, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicAbegedeAmEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicAbegedeAmEtAlphabet);
     }
     case ListStyleType::CjkEarthlyBranch: {
         static const UChar cjkEarthlyBranchAlphabet[12] = {
             0x5B50, 0x4E11, 0x5BC5, 0x536F, 0x8FB0, 0x5DF3, 0x5348, 0x672A, 0x7533,
             0x9149, 0x620C, 0x4EA5
         };
-        toAlphabetic(builder, value, cjkEarthlyBranchAlphabet);
-        break;
+        return toAlphabetic(value, cjkEarthlyBranchAlphabet);
     }
     case ListStyleType::CjkHeavenlyStem: {
         static const UChar cjkHeavenlyStemAlphabet[10] = {
             0x7532, 0x4E59, 0x4E19, 0x4E01, 0x620A, 0x5DF1, 0x5E9A, 0x8F9B, 0x58EC,
             0x7678
         };
-        toAlphabetic(builder, value, cjkHeavenlyStemAlphabet);
-        break;
+        return toAlphabetic(value, cjkHeavenlyStemAlphabet);
     }
     case ListStyleType::Ethiopic:
     case ListStyleType::EthiopicHalehameGez: {
@@ -938,8 +894,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1270, 0x1280, 0x1290, 0x12A0, 0x12A8, 0x12C8, 0x12D0, 0x12D8, 0x12E8,
             0x12F0, 0x1308, 0x1320, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicHalehameGezAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameGezAlphabet);
     }
     case ListStyleType::EthiopicAbegede:
     case ListStyleType::EthiopicAbegedeGez: {
@@ -948,24 +903,21 @@ String listMarkerText(ListStyleType type, int value)
             0x12E8, 0x12A8, 0x1208, 0x1218, 0x1290, 0x1220, 0x12D0, 0x1348, 0x1338,
             0x1240, 0x1228, 0x1230, 0x1270, 0x1280, 0x1340, 0x1330, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicAbegedeGezAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicAbegedeGezAlphabet);
     }
     case ListStyleType::HangulConsonant: {
         static const UChar hangulConsonantAlphabet[14] = {
             0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142, 0x3145, 0x3147, 0x3148,
             0x314A, 0x314B, 0x314C, 0x314D, 0x314E
         };
-        toAlphabetic(builder, value, hangulConsonantAlphabet);
-        break;
+        return toAlphabetic(value, hangulConsonantAlphabet);
     }
     case ListStyleType::Hangul: {
         static const UChar hangulAlphabet[14] = {
             0xAC00, 0xB098, 0xB2E4, 0xB77C, 0xB9C8, 0xBC14, 0xC0AC, 0xC544, 0xC790,
             0xCC28, 0xCE74, 0xD0C0, 0xD30C, 0xD558
         };
-        toAlphabetic(builder, value, hangulAlphabet);
-        break;
+        return toAlphabetic(value, hangulAlphabet);
     }
     case ListStyleType::Oromo:
     case ListStyleType::EthiopicHalehameOmEt: {
@@ -974,8 +926,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12C8, 0x12E8, 0x12F0, 0x12F8,
             0x1300, 0x1308, 0x1320, 0x1328, 0x1338, 0x1330, 0x1348
         };
-        toAlphabetic(builder, value, ethiopicHalehameOmEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameOmEtAlphabet);
     }
     case ListStyleType::Sidama:
     case ListStyleType::EthiopicHalehameSidEt: {
@@ -984,8 +935,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1270, 0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12C8, 0x12E8, 0x12F0,
             0x12F8, 0x1300, 0x1308, 0x1320, 0x1328, 0x1338, 0x1330, 0x1348
         };
-        toAlphabetic(builder, value, ethiopicHalehameSidEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameSidEtAlphabet);
     }
     case ListStyleType::Somali:
     case ListStyleType::EthiopicHalehameSoEt: {
@@ -994,8 +944,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1270, 0x1290, 0x12A0, 0x12A8, 0x12B8, 0x12C8, 0x12D0, 0x12E8, 0x12F0,
             0x1300, 0x1308, 0x1338, 0x1348
         };
-        toAlphabetic(builder, value, ethiopicHalehameSoEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameSoEtAlphabet);
     }
     case ListStyleType::Tigre:
     case ListStyleType::EthiopicHalehameTig: {
@@ -1004,8 +953,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1270, 0x1278, 0x1290, 0x12A0, 0x12A8, 0x12C8, 0x12D0, 0x12D8, 0x12E8,
             0x12F0, 0x1300, 0x1308, 0x1320, 0x1328, 0x1338, 0x1330, 0x1348, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicHalehameTigAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameTigAlphabet);
     }
     case ListStyleType::TigrinyaEr:
     case ListStyleType::EthiopicHalehameTiEr: {
@@ -1015,8 +963,7 @@ String listMarkerText(ListStyleType type, int value)
             0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320, 0x1328,
             0x1330, 0x1338, 0x1348, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicHalehameTiErAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameTiErAlphabet);
     }
     case ListStyleType::TigrinyaErAbegede:
     case ListStyleType::EthiopicAbegedeTiEr: {
@@ -1026,8 +973,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1298, 0x12D0, 0x1348, 0x1338, 0x1240, 0x1250, 0x1228, 0x1230, 0x1238,
             0x1270, 0x1278, 0x1330, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicAbegedeTiErAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicAbegedeTiErAlphabet);
     }
     case ListStyleType::TigrinyaEt:
     case ListStyleType::EthiopicHalehameTiEt: {
@@ -1037,8 +983,7 @@ String listMarkerText(ListStyleType type, int value)
             0x12B8, 0x12C8, 0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308,
             0x1320, 0x1328, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicHalehameTiEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicHalehameTiEtAlphabet);
     }
     case ListStyleType::TigrinyaEtAbegede:
     case ListStyleType::EthiopicAbegedeTiEt: {
@@ -1048,8 +993,7 @@ String listMarkerText(ListStyleType type, int value)
             0x1298, 0x1220, 0x12D0, 0x1348, 0x1338, 0x1240, 0x1250, 0x1228, 0x1230,
             0x1238, 0x1270, 0x1278, 0x1280, 0x1340, 0x1330, 0x1350
         };
-        toAlphabetic(builder, value, ethiopicAbegedeTiEtAlphabet);
-        break;
+        return toAlphabetic(value, ethiopicAbegedeTiEtAlphabet);
     }
     case ListStyleType::UpperGreek: {
         static const UChar upperGreekAlphabet[24] = {
@@ -1057,8 +1001,7 @@ String listMarkerText(ListStyleType type, int value)
             0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3,
             0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9
         };
-        toAlphabetic(builder, value, upperGreekAlphabet);
-        break;
+        return toAlphabetic(value, upperGreekAlphabet);
     }
     case ListStyleType::LowerNorwegian: {
         static const LChar lowerNorwegianAlphabet[29] = {
@@ -1067,8 +1010,7 @@ String listMarkerText(ListStyleType type, int value)
             0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xE6,
             0xF8, 0xE5
         };
-        toAlphabetic(builder, value, lowerNorwegianAlphabet);
-        break;
+        return toAlphabetic(value, lowerNorwegianAlphabet);
     }
     case ListStyleType::UpperNorwegian: {
         static const LChar upperNorwegianAlphabet[29] = {
@@ -1077,8 +1019,7 @@ String listMarkerText(ListStyleType type, int value)
             0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xC6,
             0xD8, 0xC5
         };
-        toAlphabetic(builder, value, upperNorwegianAlphabet);
-        break;
+        return toAlphabetic(value, upperNorwegianAlphabet);
     }
     case ListStyleType::CJKIdeographic: {
         static const UChar traditionalChineseInformalTable[16] = {
@@ -1087,36 +1028,30 @@ String listMarkerText(ListStyleType type, int value)
             0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB,
             0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D
         };
-        toCJKIdeographic(builder, value, traditionalChineseInformalTable);
-        break;
+        return toCJKIdeographic(value, traditionalChineseInformalTable);
     }
 
     case ListStyleType::LowerRoman:
-        toRoman(builder, value, false);
-        break;
+        return toRoman(value, LetterCase::Lower);
     case ListStyleType::UpperRoman:
-        toRoman(builder, value, true);
-        break;
+        return toRoman(value, LetterCase::Upper);
 
+    // A CSS3 draft said that "armenian" means "lower-armenian". But the CSS2.1 test
+    // suite contains uppercase test results for "armenian"; our behavior matches that.
     case ListStyleType::Armenian:
     case ListStyleType::UpperArmenian:
-        // CSS3 says "armenian" means "lower-armenian".
-        // But the CSS2.1 test suite contains uppercase test results for "armenian",
-        // so we'll match the test suite.
-        toArmenian(builder, value, true);
-        break;
+        return toArmenian(value, LetterCase::Upper);
     case ListStyleType::LowerArmenian:
-        toArmenian(builder, value, false);
-        break;
+        return toArmenian(value, LetterCase::Lower);
+
     case ListStyleType::Georgian:
-        toGeorgian(builder, value);
-        break;
+        return toGeorgian(value);
     case ListStyleType::Hebrew:
-        toHebrew(builder, value);
-        break;
+        return toHebrew(value);
     }
 
-    return builder.toString();
+    ASSERT_NOT_REACHED();
+    return emptyString();
 }
 
 RenderListMarker::RenderListMarker(RenderListItem& listItem, RenderStyle&& style)
@@ -1350,32 +1285,35 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
     else {
         const UChar suffix = listMarkerSuffix(type, m_listItem->value());
 
-        // Text is not arbitrary. We can judge whether it's RTL from the first character,
-        // and we only need to handle the direction U_RIGHT_TO_LEFT for now.
-        bool textNeedsReversing = u_charDirection(m_text[0]) == U_RIGHT_TO_LEFT;
-        String toDraw;
-        if (textNeedsReversing) {
+        // FIXME: Could use a Vector with inline capacity instead of String to avoid
+        // memory allocation here.
+        String textToDraw;
+
+        // Since marker text is not arbitrary, we can judge its direction just by
+        // checking the first character, and only need to handle U_RIGHT_TO_LEFT.
+        // FIXME: Could check more efficiently than u_charDirection, since we know
+        // only certain characters are used and only need to check for U_RIGHT_TO_LEFT.
+        if (u_charDirection(m_text[0]) == U_RIGHT_TO_LEFT) {
             unsigned length = m_text.length();
-            StringBuilder buffer;
-            buffer.reserveCapacity(length + 2);
+            UChar* characters;
+            textToDraw = String::createUninitialized(length + 2, characters);
             if (!style().isLeftToRightDirection()) {
-                buffer.append(space);
-                buffer.append(suffix);
+                *characters++ = space;
+                *characters++ = suffix;
             }
             for (unsigned i = 0; i < length; ++i)
-                buffer.append(m_text[length - i - 1]);
+                *characters++ = m_text[length - i - 1];
             if (style().isLeftToRightDirection()) {
-                buffer.append(suffix);
-                buffer.append(space);
+                *characters++ = suffix;
+                *characters++ = space;
             }
-            toDraw = buffer.toString();
         } else {
             if (style().isLeftToRightDirection())
-                toDraw = m_text + String(&suffix, 1) + String(&space, 1);
+                textToDraw = makeString(m_text, suffix, space);
             else
-                toDraw = String(&space, 1) + String(&suffix, 1) + m_text;
+                textToDraw = makeString(space, suffix, m_text);
         }
-        textRun.setText(StringView(toDraw));
+        textRun.setText(textToDraw);
 
         context.drawText(font, textRun, textOrigin);
     }
@@ -1568,8 +1506,8 @@ void RenderListMarker::computePreferredLogicalWidths()
     case ListStyleType::Footnotes: {
         TextRun run = RenderBlock::constructTextRun(m_text, style());
         logicalWidth = font.width(run); // no suffix for these types
-    }
         break;
+    }
     case ListStyleType::Circle:
     case ListStyleType::Disc:
     case ListStyleType::Square:
index 4b79c1f..db8f929 100644 (file)
@@ -60,39 +60,39 @@ String buildStringFromPath(const Path& path)
             switch (element.type) {
             case PathElementMoveToPoint:
                 builder.append('M');
-                builder.appendShortestFormNumber(element.points[0].x());
+                builder.appendNumber(element.points[0].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[0].y());
+                builder.appendNumber(element.points[0].y());
                 break;
             case PathElementAddLineToPoint:
                 builder.append('L');
-                builder.appendShortestFormNumber(element.points[0].x());
+                builder.appendNumber(element.points[0].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[0].y());
+                builder.appendNumber(element.points[0].y());
                 break;
             case PathElementAddQuadCurveToPoint:
                 builder.append('Q');
-                builder.appendShortestFormNumber(element.points[0].x());
+                builder.appendNumber(element.points[0].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[0].y());
+                builder.appendNumber(element.points[0].y());
                 builder.append(',');
-                builder.appendShortestFormNumber(element.points[1].x());
+                builder.appendNumber(element.points[1].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[1].y());
+                builder.appendNumber(element.points[1].y());
                 break;
             case PathElementAddCurveToPoint:
                 builder.append('C');
-                builder.appendShortestFormNumber(element.points[0].x());
+                builder.appendNumber(element.points[0].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[0].y());
+                builder.appendNumber(element.points[0].y());
                 builder.append(',');
-                builder.appendShortestFormNumber(element.points[1].x());
+                builder.appendNumber(element.points[1].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[1].y());
+                builder.appendNumber(element.points[1].y());
                 builder.append(',');
-                builder.appendShortestFormNumber(element.points[2].x());
+                builder.appendNumber(element.points[2].x());
                 builder.append(' ');
-                builder.appendShortestFormNumber(element.points[2].y());
+                builder.appendNumber(element.points[2].y());
                 break;
             case PathElementCloseSubpath:
                 builder.append('Z');
index 49e77d5..3638a06 100644 (file)
@@ -1,3 +1,18 @@
+2019-06-03  Darin Adler  <darin@apple.com>
+
+        Finish cleanup of String::number for floating point
+        https://bugs.webkit.org/show_bug.cgi?id=198471
+
+        Reviewed by Yusuke Suzuki.
+
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp:
+        (WebKit::submitTopList): Use makeString instead of StringBuilder since it
+        is more terse and possibly more efficient as well.
+        * UIProcess/API/APIUserScript.cpp:
+        (API::UserScript::generateUniqueURL): Ditto.
+        * UIProcess/API/APIUserStyleSheet.cpp:
+        (API::UserStyleSheet::generateUniqueURL): Ditto.
+
 2019-06-03  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         REGRESSION(r240862) [WinCairo][WK2] position:fixed elements don't show
index 2ab5f07..7539158 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,7 +37,7 @@
 #include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/RunLoop.h>
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 
 namespace WebKit {
 using namespace WebCore;
@@ -159,11 +159,8 @@ static void submitTopList(unsigned numberOfResourcesFromTheTop, const Vector<Pre
     unsigned topNumberOfTimesAccessedAsFirstPartyDueToUserInteraction = median(sortedPrevalentResourcesWithoutUserInteraction, 0, numberOfResourcesFromTheTop - 1, numberOfTimesAccessedAsFirstPartyDueToUserInteractionGetter);
     unsigned topNumberOfTimesAccessedAsFirstPartyDueToStorageAccessAPI = median(sortedPrevalentResourcesWithoutUserInteraction, 0, numberOfResourcesFromTheTop - 1, numberOfTimesAccessedAsFirstPartyDueToStorageAccessAPIGetter);
 
-    StringBuilder preambleBuilder;
-    preambleBuilder.appendLiteral("top");
-    preambleBuilder.appendNumber(numberOfResourcesFromTheTop);
-    String descriptionPreamble = preambleBuilder.toString();
-    
+    String descriptionPreamble = makeString("top", numberOfResourcesFromTheTop);
+
     store.sendDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), descriptionPreamble + "PrevalentResourcesWithUserInteraction",
         topPrevalentResourcesWithUserInteraction, significantFiguresForLoggedValues, ShouldSample::No);
     store.sendDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), descriptionPreamble + "SubframeUnderTopFrameOrigins",
index 4022efd..e7cec44 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "APIUserScript.h"
 
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 
 namespace API {
 
 WTF::URL UserScript::generateUniqueURL()
 {
     static uint64_t identifier;
-
-    StringBuilder urlStringBuilder;
-    urlStringBuilder.appendLiteral("user-script:");
-    urlStringBuilder.appendNumber(++identifier);
-    return { { }, urlStringBuilder.toString() };
+    return { { }, makeString("user-script:", ++identifier) };
 }
 
 UserScript::UserScript(WebCore::UserScript userScript, API::UserContentWorld& world)
index 3ea461f..fd69b83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "APIUserStyleSheet.h"
 
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 
 namespace API {
 
 WTF::URL UserStyleSheet::generateUniqueURL()
 {
     static uint64_t identifier;
-
-    StringBuilder urlStringBuilder;
-    urlStringBuilder.appendLiteral("user-style-sheet:");
-    urlStringBuilder.appendNumber(++identifier);
-    return { { }, urlStringBuilder.toString() };
+    return { { }, makeString("user-style-sheet:", ++identifier) };
 }
 
 UserStyleSheet::UserStyleSheet(WebCore::UserStyleSheet userStyleSheet, API::UserContentWorld& world)
index b3e8af7..d7a6e3d 100644 (file)
@@ -1,3 +1,18 @@
+2019-06-03  Darin Adler  <darin@apple.com>
+
+        Finish cleanup of String::number for floating point
+        https://bugs.webkit.org/show_bug.cgi?id=198471
+
+        Reviewed by Yusuke Suzuki.
+
+        * TestWebKitAPI/Tests/WTF/WTFString.cpp:
+        (TestWebKitAPI::testStringNumber): Go back to calling String::number instead of
+        String::numberToStringECMAScript.
+
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::dumpFrameScrollPosition): Use appendNumber instead of appendECMAScriptNumber
+        since that is now the default.
+
 2019-06-02  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         [WinCairo][MiniBrowser] WKViewSetIsInWindow should be called
index 7a057dc..7ad2028 100644 (file)
@@ -172,7 +172,7 @@ TEST(WTF, StringNumberFixedWidth)
 static inline const char* testStringNumber(double number)
 {
     static char testBuffer[100] = { };
-    std::strncpy(testBuffer, String::numberToStringECMAScript(number).utf8().data(), 99);
+    std::strncpy(testBuffer, String::number(number).utf8().data(), 99);
     return testBuffer;
 }
 
index 4001f86..dc9de16 100644 (file)
@@ -782,9 +782,9 @@ static void dumpFrameScrollPosition(WKBundleFrameRef frame, StringBuilder& strin
         stringBuilder.appendLiteral("' ");
     }
     stringBuilder.appendLiteral("scrolled to ");
-    stringBuilder.appendECMAScriptNumber(x);
+    stringBuilder.appendNumber(x);
     stringBuilder.append(',');
-    stringBuilder.appendECMAScriptNumber(y);
+    stringBuilder.appendNumber(y);
     stringBuilder.append('\n');
 }