[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

barraclough at apple.com barraclough at apple.com
Wed Dec 22 12:31:07 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 798f064da7752d65c560089bae9d7f5c64cf5d33
Author: barraclough at apple.com <barraclough at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Aug 25 01:04:31 2010 +0000

    JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=44487
    
    Reviewed by Oliver Hunt.
    
    Number.toExponential/toFixed/toPrecision all contain a spaghetti of duplicated
    code & unnecessary complexity. Add a new DecimalNumber class to encapsulate
    double to string conversion, share the implementations of rounding &
    decimal-fraction/exponential formatting.
    
    * JavaScriptCore.exp:
        Update exports.
    
    * runtime/NumberPrototype.cpp:
    (JSC::toThisNumber):
    (JSC::getIntegerArgumentInRange):
        Helper methods used in implementing toExponential/toFixed/toString.
    (JSC::numberProtoFuncToExponential):
    (JSC::numberProtoFuncToFixed):
    (JSC::numberProtoFuncToPrecision):
        Reimplemented using new DecimalNumber class.
    
    * runtime/UString.cpp:
    (JSC::UString::number):
        Updated to call numberToString.
    
    * wtf/DecimalNumber.h: Added.
    (WTF::):
    (WTF::DecimalNumber::DecimalNumber):
    (WTF::DecimalNumber::toStringDecimal):
    (WTF::DecimalNumber::toStringExponential):
    (WTF::DecimalNumber::sign):
    (WTF::DecimalNumber::exponent):
    (WTF::DecimalNumber::significand):
    (WTF::DecimalNumber::precision):
    (WTF::DecimalNumber::init):
    (WTF::DecimalNumber::isZero):
    (WTF::DecimalNumber::roundToPrecision):
        New class to perform double to string conversion.
        Has three constructors, which allow conversion with no rounding,
        rounding to significant-figures, or rounding to decimal-places,
        and two methods for formatting strings, either using decimal
        fraction or exponential encoding. Internal implementation uses
        pre-rounding of the values before calling dtoa rather than
        relying on dtoa to correctly round, which does not produce
        fully accurate results. Hopefully we can address this in the
        near future.
    
    * wtf/dtoa.cpp:
    (WTF::intPow10):
    * wtf/dtoa.h:
        intPow10 is used internally by DecimalNumber.
    
    * wtf/text/WTFString.cpp:
    (WTF::copyToString):
    (WTF::nanOrInfToString):
        Used internally in numberToString for NaN/Infinity handling.
    (WTF::numberToString):
        Added new method to convert doubles to strings.
    
    * wtf/text/WTFString.h:
        Added declaration for numberToString. This is here because
        we should switch over to using this for all double to string
        conversion in WebCore (see section 2.4.4.3 of the HTML5 spec).
    
    JavaScriptGlue: https://bugs.webkit.org/show_bug.cgi?id=44487
    
    Reviewed by Oliver Hunt.
    
    * ForwardingHeaders/wtf/text/WTFString.h: Added.
    
    WebCore: https://bugs.webkit.org/show_bug.cgi?id=44487
    
    Reviewed by Oliver Hunt.
    
    * html/LegacyHTMLTreeBuilder.cpp:
    (WebCore::serializeForNumberType):
        Update function call to numberToString.
    
    LayoutTests: Bug 44487 - Clean up NumberPrototype.cpp
    
    Reviewed by Oliver Hunt.
    
    This patch changes some layout test results - in all these cases we were
    not previously accurate to spec defined behaviour, and we are still not
    - but overall this changes reduces the overall magnitude of error due to
    rounding differences. The underlying problem is that we should be using
    dtoa to generate results to a specified accuracy, rather than relying on
    pre-rounding the input values. We should look at reenabling our dtoa
    implementation to work in this fashion as a separate change.
    
    * fast/js/kde/Number-expected.txt:
    * fast/js/kde/script-tests/Number.js:
    * fast/js/number-toExponential-expected.txt:
    * fast/js/number-tofixed-expected.txt:
    * fast/js/number-toprecision-expected.txt:
    * fast/js/script-tests/number-toExponential.js:
    * fast/js/script-tests/number-tofixed.js:
    * fast/js/script-tests/number-toprecision.js:
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65959 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index d96f9cd..cb5bd43 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,69 @@
+2010-08-23  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        https://bugs.webkit.org/show_bug.cgi?id=44487
+
+        Number.toExponential/toFixed/toPrecision all contain a spaghetti of duplicated
+        code & unnecessary complexity. Add a new DecimalNumber class to encapsulate
+        double to string conversion, share the implementations of rounding &
+        decimal-fraction/exponential formatting.
+
+        * JavaScriptCore.exp:
+            Update exports.
+
+        * runtime/NumberPrototype.cpp:
+        (JSC::toThisNumber):
+        (JSC::getIntegerArgumentInRange):
+            Helper methods used in implementing toExponential/toFixed/toString.
+        (JSC::numberProtoFuncToExponential):
+        (JSC::numberProtoFuncToFixed):
+        (JSC::numberProtoFuncToPrecision):
+            Reimplemented using new DecimalNumber class.
+            
+        * runtime/UString.cpp:
+        (JSC::UString::number):
+            Updated to call numberToString.
+
+        * wtf/DecimalNumber.h: Added.
+        (WTF::):
+        (WTF::DecimalNumber::DecimalNumber):
+        (WTF::DecimalNumber::toStringDecimal):
+        (WTF::DecimalNumber::toStringExponential):
+        (WTF::DecimalNumber::sign):
+        (WTF::DecimalNumber::exponent):
+        (WTF::DecimalNumber::significand):
+        (WTF::DecimalNumber::precision):
+        (WTF::DecimalNumber::init):
+        (WTF::DecimalNumber::isZero):
+        (WTF::DecimalNumber::roundToPrecision):
+            New class to perform double to string conversion.
+            Has three constructors, which allow conversion with no rounding,
+            rounding to significant-figures, or rounding to decimal-places,
+            and two methods for formatting strings, either using decimal
+            fraction or exponential encoding. Internal implementation uses
+            pre-rounding of the values before calling dtoa rather than
+            relying on dtoa to correctly round, which does not produce
+            fully accurate results. Hopefully we can address this in the
+            near future.
+
+        * wtf/dtoa.cpp:
+        (WTF::intPow10):
+        * wtf/dtoa.h:
+            intPow10 is used internally by DecimalNumber.
+            
+        * wtf/text/WTFString.cpp:
+        (WTF::copyToString):
+        (WTF::nanOrInfToString):
+            Used internally in numberToString for NaN/Infinity handling.
+        (WTF::numberToString):
+            Added new method to convert doubles to strings.
+
+        * wtf/text/WTFString.h:
+            Added declaration for numberToString. This is here because
+            we should switch over to using this for all double to string
+            conversion in WebCore (see section 2.4.4.3 of the HTML5 spec).
+
 2010-08-24  Oliver Hunt  <oliver at apple.com>
 
         Reviewed by Geoff Garen.
diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp
index 4131e23..4542730 100644
--- a/JavaScriptCore/JavaScriptCore.exp
+++ b/JavaScriptCore/JavaScriptCore.exp
@@ -377,6 +377,7 @@ __ZN3WTF13currentThreadEv
 __ZN3WTF13tryFastCallocEmm
 __ZN3WTF13tryFastMallocEm
 __ZN3WTF14fastMallocSizeEPKv
+__ZN3WTF14numberToStringEdRA96_t
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF15ThreadCondition9broadcastEv
@@ -411,7 +412,6 @@ __ZN3WTF23dayInMonthFromDayInYearEib
 __ZN3WTF23waitForThreadCompletionEjPPv
 __ZN3WTF27releaseFastMallocFreeMemoryEv
 __ZN3WTF28setMainThreadCallbacksPausedEb
-__ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 511a7a0..e11672c 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -200,6 +200,7 @@
 		8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8626BECE11928E3900782FAB /* StringStatics.cpp */; };
 		8627E5EB11F1281900A313B5 /* PageAllocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8627E5E911F1281900A313B5 /* PageAllocation.cpp */; };
 		8627E5EC11F1281900A313B5 /* PageAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8627E5EA11F1281900A313B5 /* PageAllocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 862AF4B512239C7B0024E5B8 /* DecimalNumber.h */; };
 		863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		86565742115BE3DA00291F40 /* CString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86565740115BE3DA00291F40 /* CString.cpp */; };
 		86565743115BE3DA00291F40 /* CString.h in Headers */ = {isa = PBXBuildFile; fileRef = 86565741115BE3DA00291F40 /* CString.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -785,6 +786,7 @@
 		8626BECE11928E3900782FAB /* StringStatics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringStatics.cpp; path = text/StringStatics.cpp; sourceTree = "<group>"; };
 		8627E5E911F1281900A313B5 /* PageAllocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageAllocation.cpp; sourceTree = "<group>"; };
 		8627E5EA11F1281900A313B5 /* PageAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageAllocation.h; sourceTree = "<group>"; };
+		862AF4B512239C7B0024E5B8 /* DecimalNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecimalNumber.h; sourceTree = "<group>"; };
 		863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerCodeRef.h; sourceTree = "<group>"; };
 		86565740115BE3DA00291F40 /* CString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CString.cpp; path = text/CString.cpp; sourceTree = "<group>"; };
 		86565741115BE3DA00291F40 /* CString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CString.h; path = text/CString.h; sourceTree = "<group>"; };
@@ -1438,6 +1440,7 @@
 				180B9AF00F16C569009BDBC5 /* CurrentTime.h */,
 				41359CF40FDD89CB00206180 /* DateMath.cpp */,
 				41359CF50FDD89CB00206180 /* DateMath.h */,
+				862AF4B512239C7B0024E5B8 /* DecimalNumber.h */,
 				5186111D0CC824830081412B /* Deque.h */,
 				938C4F6B0CA06BCE00D9310A /* DisallowCType.h */,
 				651F6412039D5B5F0078395C /* dtoa.cpp */,
@@ -2233,6 +2236,7 @@
 				DDE82AD81209D955005C1756 /* GCHandle.h in Headers */,
 				86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */,
 				86B6DA0212132B9A000D316F /* StringConcatenate.h in Headers */,
+				862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2326,6 +2330,7 @@
 			isa = PBXProject;
 			buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
 			compatibilityVersion = "Xcode 2.4";
+			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				English,
diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp
index 80b7ce0..1a74375 100644
--- a/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -29,8 +29,8 @@
 #include "Operations.h"
 #include "PrototypeFunction.h"
 #include "StringBuilder.h"
-#include "dtoa.h"
 #include <wtf/Assertions.h>
+#include <wtf/DecimalNumber.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
 
@@ -66,75 +66,140 @@ NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject,
 
 // ECMA 15.7.4.2 - 15.7.4.7
 
-static UString integerPartNoExp(double d)
+static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, double &x)
 {
-    int decimalPoint;
-    int sign;
-    char result[80];
-    WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL);
-    bool resultIsInfOrNan = (decimalPoint == 9999);
-    size_t length = strlen(result);
-
-    StringBuilder builder;
-    builder.append(sign ? "-" : "");
-    if (resultIsInfOrNan)
-        builder.append((const char*)result);
-    else if (decimalPoint <= 0)
-        builder.append("0");
-    else {
-        Vector<char, 1024> buf(decimalPoint + 1);
-
-        if (static_cast<int>(length) <= decimalPoint) {
-            ASSERT(decimalPoint < 1024);
-            memcpy(buf.data(), result, length);
-            memset(buf.data() + length, '0', decimalPoint - length);
-        } else
-            strncpy(buf.data(), result, decimalPoint);
-        buf[decimalPoint] = '\0';
-
-        builder.append((const char*)(buf.data()));
+    JSValue v = thisValue.getJSNumber();
+    if (UNLIKELY(!v))
+        return false;
+    x = v.uncheckedGetNumber();
+    return true;
+}
+
+static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, int high, int& result, bool& isUndefined)
+{
+    result = 0;
+    isUndefined = false;
+
+    JSValue argument0 = exec->argument(0);
+    if (argument0.isUndefined()) {
+        isUndefined = true;
+        return true;
     }
 
-    return builder.build();
+    double asDouble = argument0.toInteger(exec);
+    if (asDouble < low || asDouble > high)
+        return false;
+
+    result = static_cast<int>(asDouble);
+    return true;
 }
 
-static UString charSequence(char c, int count)
+// toExponential converts a number to a string, always formatting as an expoential.
+// This method takes an optional argument specifying a number of *decimal places*
+// to round the significand to (or, put another way, this method optionally rounds
+// to argument-plus-one significant figures).
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
 {
-    Vector<char, 2048> buf(count + 1, c);
-    buf[count] = '\0';
+    // Get x (the double value of this, which should be a Number).
+    double x;
+    if (!toThisNumber(exec->hostThisValue(), x))
+        return throwVMTypeError(exec);
+
+    // Get the argument. 
+    int decimalPlacesInExponent;
+    bool isUndefined;
+    if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlacesInExponent, isUndefined))
+        return throwVMError(exec, createRangeError(exec, "toExponential() argument must be between 0 and 20"));
 
-    return UString(buf.data());
+    // Handle NaN and Infinity.
+    if (isnan(x) || isinf(x))
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // Round if the argument is not undefined, always format as exponential.
+    NumberToStringBuffer buffer;
+    unsigned length = isUndefined
+        ? DecimalNumber(x).toStringExponential(buffer)
+        : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer);
+
+    return JSValue::encode(jsString(exec, UString(buffer, length)));
 }
 
-static double intPow10(int e)
+// toFixed converts a number to a string, always formatting as an a decimal fraction.
+// This method takes an argument specifying a number of decimal places to round the
+// significand to. However when converting large values (1e+21 and above) this
+// method will instead fallback to calling ToString. 
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
 {
-    // This function uses the "exponentiation by squaring" algorithm and
-    // long double to quickly and precisely calculate integer powers of 10.0.
-
-    // This is a handy workaround for <rdar://problem/4494756>
-
-    if (e == 0)
-        return 1.0;
-
-    bool negative = e < 0;
-    unsigned exp = negative ? -e : e;
-
-    long double result = 10.0;
-    bool foundOne = false;
-    for (int bit = 31; bit >= 0; bit--) {
-        if (!foundOne) {
-            if ((exp >> bit) & 1)
-                foundOne = true;
-        } else {
-            result = result * result;
-            if ((exp >> bit) & 1)
-                result = result * 10.0;
-        }
-    }
+    // Get x (the double value of this, which should be a Number).
+    JSValue thisValue = exec->hostThisValue();
+    JSValue v = thisValue.getJSNumber();
+    if (!v)
+        return throwVMTypeError(exec);
+    double x = v.uncheckedGetNumber();
+
+    // Get the argument. 
+    int decimalPlaces;
+    bool isUndefined; // This is ignored; undefined treated as 0.
+    if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlaces, isUndefined))
+        return throwVMError(exec, createRangeError(exec, "toFixed() argument must be between 0 and 20"));
+
+    // 15.7.4.5.7 states "If x >= 10^21, then let m = ToString(x)"
+    // 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, UString::number(x)));
+
+    // The check above will return false for NaN or Infinity, these will be
+    // handled by numberToString.
+    ASSERT(!isnan(x) && !isinf(x));
+
+    // Convert to decimal with rounding, and format as decimal.
+    NumberToStringBuffer buffer;
+    unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer);
+    return JSValue::encode(jsString(exec, UString(buffer, length)));
+}
 
-    if (negative)
-        return static_cast<double>(1.0 / result);
-    return static_cast<double>(result);
+// toPrecision converts a number to a string, takeing an argument specifying a
+// number of significant figures to round the significand to. For positive
+// exponent, all values that can be represented using a decimal fraction will
+// be, e.g. when rounding to 3 s.f. any value up to 999 will be formated as a
+// decimal, whilst 1000 is converted to the exponential representation 1.00e+3.
+// For negative exponents values >= 1e-6 are formated as decimal fractions,
+// with smaller values converted to exponential representation.
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
+{
+    // Get x (the double value of this, which should be a Number).
+    JSValue thisValue = exec->hostThisValue();
+    JSValue v = thisValue.getJSNumber();
+    if (!v)
+        return throwVMTypeError(exec);
+    double x = v.uncheckedGetNumber();
+
+    // Get the argument. 
+    int significantFigures;
+    bool isUndefined;
+    if (!getIntegerArgumentInRange(exec, 1, 21, significantFigures, isUndefined))
+        return throwVMError(exec, createRangeError(exec, "toPrecision() argument must be between 1 and 21"));
+
+    // To precision called with no argument is treated as ToString.
+    if (isUndefined)
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // Handle NaN and Infinity.
+    if (isnan(x) || isinf(x))
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // Convert to decimal with rounding.
+    DecimalNumber number(x, RoundingSignificantFigures, significantFigures);
+    // If number is in the range 1e-6 <= x < pow(10, significantFigures) then format
+    // as decimal. Otherwise, format the number as an exponential.  Decimal format
+    // demands a minimum of (exponent + 1) digits to represent a number, for example
+    // 1234 (1.234e+3) requires 4 digits. (See ECMA-262 15.7.4.7.10.c)
+    NumberToStringBuffer buffer;
+    unsigned length = number.exponent() >= -6 && number.exponent() < significantFigures
+        ? number.toStringDecimal(buffer)
+        : number.toStringExponential(buffer);
+    return JSValue::encode(jsString(exec, UString(buffer, length)));
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
@@ -243,237 +308,4 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
     return JSValue::encode(v);
 }
 
-EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
-{
-    JSValue thisValue = exec->hostThisValue();
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwVMTypeError(exec);
-
-    JSValue fractionDigits = exec->argument(0);
-    double df = fractionDigits.toInteger(exec);
-    if (!(df >= 0 && df <= 20))
-        return throwVMError(exec, createRangeError(exec, "toFixed() digits argument must be between 0 and 20"));
-    int f = static_cast<int>(df);
-
-    double x = v.uncheckedGetNumber();
-    if (isnan(x))
-        return JSValue::encode(jsNontrivialString(exec, "NaN"));
-
-    UString s;
-    if (x < 0) {
-        s = "-";
-        x = -x;
-    } else {
-        s = "";
-        if (x == -0.0)
-            x = 0;
-    }
-
-    if (x >= pow(10.0, 21.0))
-        return JSValue::encode(jsString(exec, makeString(s, UString::number(x))));
-
-    const double tenToTheF = pow(10.0, f);
-    double n = floor(x * tenToTheF);
-    if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))
-        n++;
-
-    UString m = integerPartNoExp(n);
-
-    int k = m.length();
-    if (k <= f) {
-        StringBuilder z;
-        for (int i = 0; i < f + 1 - k; i++)
-            z.append('0');
-        z.append(m);
-        m = z.build();
-        k = f + 1;
-        ASSERT(k == static_cast<int>(m.length()));
-    }
-    int kMinusf = k - f;
-
-    if (kMinusf < static_cast<int>(m.length()))
-        return JSValue::encode(jsString(exec, makeString(s, m.substringSharingImpl(0, kMinusf), ".", m.substringSharingImpl(kMinusf))));
-    return JSValue::encode(jsString(exec, makeString(s, m.substringSharingImpl(0, kMinusf))));
-}
-
-static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
-{
-    if (fractionalDigits <= 0)
-        return;
-
-    int fDigitsInResult = static_cast<int>(resultLength) - 1;
-    buf[i++] = '.';
-    if (fDigitsInResult > 0) {
-        if (fractionalDigits < fDigitsInResult) {
-            strncpy(buf + i, result + 1, fractionalDigits);
-            i += fractionalDigits;
-        } else {
-            ASSERT(i + resultLength - 1 < 80);
-            memcpy(buf + i, result + 1, resultLength - 1);
-            i += static_cast<int>(resultLength) - 1;
-        }
-    }
-
-    for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)
-        buf[i++] = '0';
-}
-
-static void exponentialPartToString(char* buf, int& i, int decimalPoint)
-{
-    buf[i++] = 'e';
-    // decimalPoint can't be more than 3 digits decimal given the
-    // nature of float representation
-    int exponential = decimalPoint - 1;
-    buf[i++] = (exponential >= 0) ? '+' : '-';
-    if (exponential < 0)
-        exponential *= -1;
-    if (exponential >= 100)
-        buf[i++] = static_cast<char>('0' + exponential / 100);
-    if (exponential >= 10)
-        buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
-    buf[i++] = static_cast<char>('0' + exponential % 10);
-}
-
-EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
-{
-    JSValue thisValue = exec->hostThisValue();
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwVMTypeError(exec);
-
-    double x = v.uncheckedGetNumber();
-
-    if (isnan(x) || isinf(x))
-        return JSValue::encode(jsString(exec, UString::number(x)));
-
-    JSValue fractionalDigitsValue = exec->argument(0);
-    double df = fractionalDigitsValue.toInteger(exec);
-    if (!(df >= 0 && df <= 20))
-        return throwVMError(exec, createRangeError(exec, "toExponential() argument must between 0 and 20"));
-    int fractionalDigits = static_cast<int>(df);
-    bool includeAllDigits = fractionalDigitsValue.isUndefined();
-
-    int decimalAdjust = 0;
-    if (x && !includeAllDigits) {
-        double logx = floor(log10(fabs(x)));
-        x /= pow(10.0, logx);
-        const double tenToTheF = pow(10.0, fractionalDigits);
-        double fx = floor(x * tenToTheF) / tenToTheF;
-        double cx = ceil(x * tenToTheF) / tenToTheF;
-
-        if (fabs(fx - x) < fabs(cx - x))
-            x = fx;
-        else
-            x = cx;
-
-        decimalAdjust = static_cast<int>(logx);
-    }
-
-    if (isnan(x))
-        return JSValue::encode(jsNontrivialString(exec, "NaN"));
-
-    if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0
-        x = 0;
-
-    int decimalPoint;
-    int sign;
-    char result[80];
-    WTF::dtoa(result, x, 0, &decimalPoint, &sign, NULL);
-    size_t resultLength = strlen(result);
-    decimalPoint += decimalAdjust;
-
-    int i = 0;
-    char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)
-    if (sign)
-        buf[i++] = '-';
-
-    // ? 9999 is the magical "result is Inf or NaN" value.  what's 999??
-    if (decimalPoint == 999) {
-        ASSERT(i + resultLength < 80);
-        memcpy(buf + i, result, resultLength);
-        buf[i + resultLength] = '\0';
-    } else {
-        buf[i++] = result[0];
-
-        if (includeAllDigits)
-            fractionalDigits = static_cast<int>(resultLength) - 1;
-
-        fractionalPartToString(buf, i, result, resultLength, fractionalDigits);
-        exponentialPartToString(buf, i, decimalPoint);
-        buf[i++] = '\0';
-    }
-    ASSERT(i <= 80);
-
-    return JSValue::encode(jsString(exec, buf));
-}
-
-EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
-{
-    JSValue thisValue = exec->hostThisValue();
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwVMTypeError(exec);
-
-    double doublePrecision = exec->argument(0).toIntegerPreserveNaN(exec);
-    double x = v.uncheckedGetNumber();
-    if (exec->argument(0).isUndefined() || isnan(x) || isinf(x))
-        return JSValue::encode(jsString(exec, v.toString(exec)));
-
-    UString s;
-    if (x < 0) {
-        s = "-";
-        x = -x;
-    } else
-        s = "";
-
-    if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
-        return throwVMError(exec, createRangeError(exec, "toPrecision() argument must be between 1 and 21"));
-    int precision = static_cast<int>(doublePrecision);
-
-    int e = 0;
-    UString m;
-    if (x) {
-        e = static_cast<int>(log10(x));
-        double tens = intPow10(e - precision + 1);
-        double n = floor(x / tens);
-        if (n < intPow10(precision - 1)) {
-            e = e - 1;
-            tens = intPow10(e - precision + 1);
-            n = floor(x / tens);
-        }
-
-        if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))
-            ++n;
-        // maintain n < 10^(precision)
-        if (n >= intPow10(precision)) {
-            n /= 10.0;
-            e += 1;
-        }
-        ASSERT(intPow10(precision - 1) <= n);
-        ASSERT(n < intPow10(precision));
-
-        m = integerPartNoExp(n);
-        if (e < -6 || e >= precision) {
-            if (m.length() > 1)
-                m = makeString(m.substringSharingImpl(0, 1), ".", m.substringSharingImpl(1));
-            if (e >= 0)
-                return JSValue::encode(jsMakeNontrivialString(exec, s, m, "e+", UString::number(e)));
-            return JSValue::encode(jsMakeNontrivialString(exec, s, m, "e-", UString::number(-e)));
-        }
-    } else {
-        m = charSequence('0', precision);
-        e = 0;
-    }
-
-    if (e == precision - 1)
-        return JSValue::encode(jsString(exec, makeString(s, m)));
-    if (e >= 0) {
-        if (e + 1 < static_cast<int>(m.length()))
-            return JSValue::encode(jsString(exec, makeString(s, m.substringSharingImpl(0, e + 1), ".", m.substringSharingImpl(e + 1))));
-        return JSValue::encode(jsString(exec, makeString(s, m)));
-    }
-    return JSValue::encode(jsMakeNontrivialString(exec, s, "0.", charSequence('0', -(e + 1)), m));
-}
-
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp
index 78e349b..7362950 100644
--- a/JavaScriptCore/runtime/UString.cpp
+++ b/JavaScriptCore/runtime/UString.cpp
@@ -26,7 +26,6 @@
 
 #include "JSGlobalObjectFunctions.h"
 #include "Collector.h"
-#include "dtoa.h"
 #include "Identifier.h"
 #include "Operations.h"
 #include <ctype.h>
@@ -39,6 +38,7 @@
 #include <wtf/MathExtras.h>
 #include <wtf/StringExtras.h>
 #include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
 #include <wtf/unicode/UTF8.h>
 
 #if HAVE(STRINGS_H)
@@ -198,10 +198,8 @@ UString UString::number(long l)
 
 UString UString::number(double d)
 {
-    DtoaBuffer buffer;
-    unsigned length;
-    doubleToStringInJavaScriptFormat(d, buffer, &length);
-    return UString(buffer, length);
+    NumberToStringBuffer buffer;
+    return StringImpl::create(buffer, numberToString(d, buffer));
 }
 
 UString UString::substringSharingImpl(unsigned offset, unsigned length) const
diff --git a/JavaScriptCore/wtf/DecimalNumber.h b/JavaScriptCore/wtf/DecimalNumber.h
new file mode 100644
index 0000000..f60e853
--- /dev/null
+++ b/JavaScriptCore/wtf/DecimalNumber.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DecimalNumber_h
+#define DecimalNumber_h
+
+#include <math.h>
+#include <wtf/dtoa.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+enum RoundingSignificantFiguresType { RoundingSignificantFigures };
+enum RoundingDecimalPlacesType { RoundingDecimalPlaces };
+
+class DecimalNumber {
+public:
+    DecimalNumber(double d)
+    {
+        bool sign = d < 0; // This (correctly) ignores the sign on -0.0.
+        init(sign, d);
+    }
+
+    // If our version of dtoa could round to a given number of significant figures then
+    // we could remove the pre-rounding code from here.  We could also do so just by
+    // calling dtoa and post-rounding, however currently this is slower, since it forces
+    // dtoa to generate a higher presision result.
+    DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures)
+    {
+        ASSERT(!isnan(d) && !isinf(d));
+        ASSERT(significantFigures && significantFigures <= 21);
+
+        bool sign = d < 0; // This (correctly) ignores the sign on -0.0.
+        d = fabs(d); // make d positive before going any further.
+
+        int adjust = 0;
+        if (d) {
+            // To round a number we align it such that the correct number of digits are
+            // to the left of the decimal point, then floor/ceil.  For example, to round
+            // 13579 to 3 s.f. we first adjust it to 135.79, use floor/ceil to obtain the
+            // values 135/136, and then select 136 (since this is closest to 135.79).
+            // There are currently (exp + 1) digits to the left of the decimal point,
+            // and we want thsi to be significantFigures, so we're going to adjust the
+            // exponent by ((exp + 1) - significantFigures).  Adjust is effectively
+            // a count of how many decimal digits to right-shift the number by.
+            int exp = static_cast<int>(floor(log10(d)));
+            adjust = (exp + 1) - significantFigures;
+
+            // If the adjust value might be positive or negative - or zero.  If zero, then
+            // nothing to do! - the number is already appropriately aligned.  If adjust
+            // is positive then divide d by 10^adjust.  If adjust is negative multiply d
+            // by 10^-adjust. This is mathematically the same, but avoids two fp divides
+            // (one inside intPow10, where the power is negative).
+            if (adjust > 0)
+                d /= intPow10(adjust);
+            else if (adjust < 0)
+                d *= intPow10(-adjust);
+
+            // Try rounding up & rounding down, select whichever is closest (rounding up if equal distance).
+            double floorOfD = floor(d);
+            double ceilOfD = floorOfD + 1;
+            d = (fabs(ceilOfD - d) <= fabs(floorOfD - d)) ? ceilOfD : floorOfD;
+
+            // The number's exponent has been altered - but don't change it back!  We can
+            // just run dtoa on the modified value, and adjust the exponent afterward to
+            // account for this.
+        }
+
+        init(sign, d);
+
+        // We alterered the value when rounding it - modify the exponent to adjust for this,
+        // but don't mess with the exponent of zero.
+        if (!isZero())
+            m_exponent += adjust;
+
+        // Make sure the significand does not contain more digits than requested.
+        roundToPrecision(significantFigures);
+    }
+
+    // If our version of dtoa could round to a given number of decimal places then we
+    // could remove the pre-rounding code from here.  We could also do so just by calling
+    // dtoa and post-rounding, however currently this is slower, since it forces dtoa to
+    // generate a higher presision result.
+    DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces)
+    {
+        ASSERT(!isnan(d) && !isinf(d));
+        ASSERT(decimalPlaces <= 20);
+
+        bool sign = d < 0; // This (correctly) ignores the sign on -0.0.
+        d = fabs(d); // Make d positive before going any further.
+
+        ASSERT(d < 1e+21); // We don't currently support rounding to decimal places for values >= 1e+21.
+
+        // Adjust the number by increasing the exponent by decimalPlaces, such
+        // that we can round to this number of decimal places jsing floor.
+        if (decimalPlaces)
+            d *= intPow10(decimalPlaces);
+        // Try rounding up & rounding down, select whichever is closest (rounding up if equal distance).
+        double floorOfD = floor(d);
+        double ceilOfD = floorOfD + 1;
+        d = (fabs(ceilOfD - d) <= fabs(floorOfD - d)) ? ceilOfD : floorOfD;
+        // The number's exponent has been altered - but don't change it back!  We can
+        // just run dtoa on the modified value, and adjust the exponent afterward to
+        // account for this.
+
+        init(sign, d);
+
+        // We rouned the value before calling dtoa, so the result should not be fractional.
+        ASSERT(m_exponent >= 0);
+
+        // We alterered the value when rounding it - modify the exponent to adjust for this,
+        // but don't mess with the exponent of zero.
+        if (!isZero())
+            m_exponent -= decimalPlaces;
+
+        // The value was < 1e+21 before we started, should still be.
+        ASSERT(m_exponent < 21);
+
+        unsigned significantFigures = 1 + m_exponent + decimalPlaces;
+        ASSERT(significantFigures && significantFigures <= 41);
+        roundToPrecision(significantFigures);
+    }
+
+    unsigned toStringDecimal(NumberToStringBuffer& buffer)
+    {
+        // Should always be at least one digit to add to the string!
+        ASSERT(m_precision);
+        UChar* next = buffer;
+
+        // if the exponent is negative the number decimal representation is of the form:
+        // [<sign>]0.[<zeros>]<significand>
+        if (m_exponent < 0) {
+            unsigned zeros = -m_exponent - 1;
+
+            if (m_sign)
+                *next++ = '-';
+            *next++ = '0';
+            *next++ = '.';
+            for (unsigned i = 0; i < zeros; ++i)
+                *next++ = '0';
+            for (unsigned i = 0; i < m_precision; ++i)
+                *next++ = m_significand[i];
+
+            return next - buffer;
+        }
+
+        unsigned digitsBeforeDecimalPoint = m_exponent + 1;
+
+        // If the precision is <= than the number of digits to get up to the decimal
+        // point, then there is no fractional part, number is of the form:
+        // [<sign>]<significand>[<zeros>]
+        if (m_precision <= digitsBeforeDecimalPoint) {
+            if (m_sign)
+                *next++ = '-';
+            for (unsigned i = 0; i < m_precision; ++i)
+                *next++ = m_significand[i];
+            for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i)
+                *next++ = '0';
+
+            return next - buffer;
+        }
+
+        // If we get here, number starts before the decimal point, and ends after it,
+        // as such is of the form:
+        // [<sign>]<significand-begin>.<significand-end>
+
+        if (m_sign)
+            *next++ = '-';
+        for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i)
+            *next++ = m_significand[i];
+        *next++ = '.';
+        for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i)
+            *next++ = m_significand[i];
+
+        return next - buffer;
+    }
+
+    unsigned toStringExponential(NumberToStringBuffer &buffer)
+    {
+        // Should always be at least one digit to add to the string!
+        ASSERT(m_precision);
+
+        UChar* next = buffer;
+
+        // Add the sign
+        if (m_sign)
+            *next++ = '-';
+
+        // Add the significand
+        *next++ = m_significand[0];
+        if (m_precision > 1) {
+            *next++ = '.';
+            for (unsigned i = 1; i < m_precision; ++i)
+                *next++ = m_significand[i];
+        }
+
+        // Add "e+" or "e-"
+        *next++ = 'e';
+        int exponent;
+        if (m_exponent >= 0) {
+            *next++ = '+';
+            exponent = m_exponent;
+        } else {
+            *next++ = '-';
+            exponent = -m_exponent;
+        }
+
+        // Add the exponent
+        if (exponent >= 100)
+            *next++ = '0' + exponent / 100;
+        if (exponent >= 10)
+            *next++ = '0' + (exponent % 100) / 10;
+        *next++ = '0' + exponent % 10;
+
+        return next - buffer;
+    }
+
+    bool sign() { return m_sign; }
+    int exponent() { return m_exponent; }
+    const char* significand() { return m_significand; } // significand contains precision characters, is not null-terminated.
+    unsigned precision() { return m_precision; }
+
+private:
+    void init(bool sign, double d)
+    {
+        ASSERT(!isnan(d) && !isinf(d));
+
+        int decimalPoint;
+        int signUnused;
+        char* resultEnd = 0;
+        WTF::dtoa(m_significand, d, 0, &decimalPoint, &signUnused, &resultEnd);
+
+        m_sign = sign;
+        m_precision = resultEnd - m_significand;
+        m_exponent = decimalPoint - 1;
+
+        // No values other than zero should have a leading zero.
+        ASSERT(m_significand[0] != '0' || m_precision == 1);
+        // Zero should always have exponent 0.
+        ASSERT(m_significand[0] != '0' || !m_exponent);
+    }
+
+    bool isZero()
+    {
+        return m_significand[0] == '0';
+    }
+
+    // We pre-round the values to dtoa - which leads to it generating faster results.
+    // But dtoa won't have zero padded the significand to the precision we require,
+    // and also might have produced too many digits if rounding went wrong somehow.
+    // Adjust for this.
+    void roundToPrecision(unsigned significantFigures)
+    {
+        ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer));
+
+        // If there are too few of too many digits in the significand then add more, or remove some!
+        for (unsigned i = m_precision; i < significantFigures; ++i)
+            m_significand[i] = '0';
+        m_precision = significantFigures;
+    }
+
+    bool m_sign;
+    int m_exponent;
+    DtoaBuffer m_significand;
+    unsigned m_precision;
+};
+
+} // namespace WTF
+
+using WTF::DecimalNumber;
+using WTF::RoundingSignificantFigures;
+using WTF::RoundingDecimalPlaces;
+
+#endif // DecimalNumber_h
diff --git a/JavaScriptCore/wtf/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp
index f7e19bf..31ef51b 100644
--- a/JavaScriptCore/wtf/dtoa.cpp
+++ b/JavaScriptCore/wtf/dtoa.cpp
@@ -2285,83 +2285,35 @@ ret:
         *rve = s;
 }
 
-static ALWAYS_INLINE void append(char*& next, const char* src, unsigned size)
+double intPow10(int e)
 {
-    for (unsigned i = 0; i < size; ++i)
-        *next++ = *src++;
-}
+    // This function uses the "exponentiation by squaring" algorithm and
+    // long double to quickly and precisely calculate integer powers of 10.0.
 
-void doubleToStringInJavaScriptFormat(double d, DtoaBuffer buffer, unsigned* resultLength)
-{
-    ASSERT(buffer);
+    // This is a handy workaround for <rdar://problem/4494756>
 
-    // avoid ever printing -NaN, in JS conceptually there is only one NaN value
-    if (isnan(d)) {
-        append(buffer, "NaN", 3);
-        if (resultLength)
-            *resultLength = 3;
-        return;
-    }
-    // -0 -> "0"
-    if (!d) {
-        buffer[0] = '0';
-        if (resultLength)
-            *resultLength = 1;
-        return;
-    }
+    if (!e)
+        return 1.0;
 
-    int decimalPoint;
-    int sign;
+    bool negative = e < 0;
+    unsigned exp = negative ? -e : e;
 
-    DtoaBuffer result;
-    char* resultEnd = 0;
-    WTF::dtoa(result, d, 0, &decimalPoint, &sign, &resultEnd);
-    int length = resultEnd - result;
-
-    char* next = buffer;
-    if (sign)
-        *next++ = '-';
-
-    if (decimalPoint <= 0 && decimalPoint > -6) {
-        *next++ = '0';
-        *next++ = '.';
-        for (int j = decimalPoint; j < 0; j++)
-            *next++ = '0';
-        append(next, result, length);
-    } else if (decimalPoint <= 21 && decimalPoint > 0) {
-        if (length <= decimalPoint) {
-            append(next, result, length);
-            for (int j = 0; j < decimalPoint - length; j++)
-                *next++ = '0';
+    long double result = 10.0;
+    bool foundOne = false;
+    for (int bit = 31; bit >= 0; bit--) {
+        if (!foundOne) {
+            if ((exp >> bit) & 1)
+                foundOne = true;
         } else {
-            append(next, result, decimalPoint);
-            *next++ = '.';
-            append(next, result + decimalPoint, length - decimalPoint);
-        }
-    } else if (result[0] < '0' || result[0] > '9')
-        append(next, result, length);
-    else {
-        *next++ = result[0];
-        if (length > 1) {
-            *next++ = '.';
-            append(next, result + 1, length - 1);
+            result = result * result;
+            if ((exp >> bit) & 1)
+                result = result * 10.0;
         }
+    }
 
-        *next++ = 'e';
-        *next++ = (decimalPoint >= 0) ? '+' : '-';
-        // decimalPoint can't be more than 3 digits decimal given the
-        // nature of float representation
-        int exponential = decimalPoint - 1;
-        if (exponential < 0)
-            exponential = -exponential;
-        if (exponential >= 100)
-            *next++ = static_cast<char>('0' + exponential / 100);
-        if (exponential >= 10)
-            *next++ = static_cast<char>('0' + (exponential % 100) / 10);
-        *next++ = static_cast<char>('0' + exponential % 10);
-    }
-    if (resultLength)
-        *resultLength = next - buffer;
+    if (negative)
+        return static_cast<double>(1.0 / result);
+    return static_cast<double>(result);
 }
 
 } // namespace WTF
diff --git a/JavaScriptCore/wtf/dtoa.h b/JavaScriptCore/wtf/dtoa.h
index e0938ff..43c343b 100644
--- a/JavaScriptCore/wtf/dtoa.h
+++ b/JavaScriptCore/wtf/dtoa.h
@@ -35,15 +35,10 @@ double strtod(const char* s00, char** se);
 
 typedef char DtoaBuffer[80];
 void dtoa(DtoaBuffer result, double d, int ndigits, int* decpt, int* sign, char** rve);
-
-// dtoa() for ECMA-262 'ToString Applied to the Number Type.'
-// The *resultLength will have the length of the resultant string in bufer.
-// The resultant string isn't terminated by 0.
-void doubleToStringInJavaScriptFormat(double, DtoaBuffer, unsigned* resultLength);
+double intPow10(int);
 
 } // namespace WTF
 
 using WTF::DtoaBuffer;
-using WTF::doubleToStringInJavaScriptFormat;
 
 #endif // WTF_dtoa_h
diff --git a/JavaScriptCore/wtf/text/WTFString.cpp b/JavaScriptCore/wtf/text/WTFString.cpp
index 7d44d21..bbff576 100644
--- a/JavaScriptCore/wtf/text/WTFString.cpp
+++ b/JavaScriptCore/wtf/text/WTFString.cpp
@@ -25,10 +25,10 @@
 #include <limits>
 #include <stdarg.h>
 #include <wtf/ASCIICType.h>
-#include <wtf/text/CString.h>
+#include <wtf/DecimalNumber.h>
 #include <wtf/StringExtras.h>
 #include <wtf/Vector.h>
-#include <wtf/dtoa.h>
+#include <wtf/text/CString.h>
 #include <wtf/unicode/UTF8.h>
 #include <wtf/unicode/Unicode.h>
 
@@ -947,6 +947,41 @@ float charactersToFloat(const UChar* data, size_t length, bool* ok)
     return static_cast<float>(charactersToDouble(data, length, ok));
 }
 
+static unsigned copyToString(const char* string, unsigned length, NumberToStringBuffer& buffer)
+{
+    for (unsigned i = 0; i < length; ++i)
+        buffer[i] = string[i];
+    return length;
+}
+
+static NEVER_INLINE unsigned nanOrInfToString(double x, NumberToStringBuffer& buffer)
+{
+    ASSERT(isnan(x) || isinf(x));
+    if (isnan(x))
+        return copyToString("NaN", 3, buffer);
+    if (x < 0)
+        return copyToString("-Infinity", 9, buffer);
+    return copyToString("Infinity", 8, buffer);
+}
+
+// toString converts a number to a string without rounding. For values in the range
+// 1e-6 <= x < 1e+21 the result is formatted as a decimal, with values outside of
+// this range being formatted as an exponential.
+unsigned numberToString(double x, NumberToStringBuffer& buffer)
+{
+    // Handle NaN and Infinity.
+    if (UNLIKELY(isnan(x) || isinf(x)))
+        return nanOrInfToString(x, buffer);
+
+    // Convert to decimal, no rounding.
+    DecimalNumber number(x);
+
+    // Format as decimal or exponential, depending on the exponent.
+    return number.exponent() >= -6 && number.exponent() < 21
+        ? number.toStringDecimal(buffer)
+        : number.toStringExponential(buffer);
+}
+
 } // namespace WTF
 
 #ifndef NDEBUG
diff --git a/JavaScriptCore/wtf/text/WTFString.h b/JavaScriptCore/wtf/text/WTFString.h
index fafef12..8a6bab6 100644
--- a/JavaScriptCore/wtf/text/WTFString.h
+++ b/JavaScriptCore/wtf/text/WTFString.h
@@ -52,6 +52,10 @@ class BString;
 
 namespace WTF {
 
+// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits.
+typedef UChar NumberToStringBuffer[96];
+unsigned numberToString(double, NumberToStringBuffer&);
+
 class CString;
 
 // Declarations of string operations
@@ -453,4 +457,7 @@ using WTF::charactersToInt;
 using WTF::charactersToFloat;
 using WTF::charactersToDouble;
 
+using WTF::NumberToStringBuffer;
+using WTF::numberToString;
+
 #endif
diff --git a/JavaScriptGlue/ChangeLog b/JavaScriptGlue/ChangeLog
index fe04083..895e484 100644
--- a/JavaScriptGlue/ChangeLog
+++ b/JavaScriptGlue/ChangeLog
@@ -1,3 +1,11 @@
+2010-08-23  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        https://bugs.webkit.org/show_bug.cgi?id=44487
+
+        * ForwardingHeaders/wtf/text/WTFString.h: Added.
+
 2010-08-24  Oliver Hunt  <oliver at apple.com>
 
         Reviewed by Geoff Garen.
diff --git a/JavaScriptGlue/ForwardingHeaders/wtf/text/WTFString.h b/JavaScriptGlue/ForwardingHeaders/wtf/text/WTFString.h
new file mode 100644
index 0000000..8addade
--- /dev/null
+++ b/JavaScriptGlue/ForwardingHeaders/wtf/text/WTFString.h
@@ -0,0 +1 @@
+#include <JavaScriptCore/WTFString.h>
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 5591ed4..851de08 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,26 @@
+2010-08-23  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Bug 44487 - Clean up NumberPrototype.cpp
+
+        This patch changes some layout test results - in all these cases we were
+        not previously accurate to spec defined behaviour, and we are still not
+        - but overall this changes reduces the overall magnitude of error due to
+        rounding differences. The underlying problem is that we should be using
+        dtoa to generate results to a specified accuracy, rather than relying on
+        pre-rounding the input values. We should look at reenabling our dtoa
+        implementation to work in this fashion as a separate change.
+
+        * fast/js/kde/Number-expected.txt:
+        * fast/js/kde/script-tests/Number.js:
+        * fast/js/number-toExponential-expected.txt:
+        * fast/js/number-tofixed-expected.txt:
+        * fast/js/number-toprecision-expected.txt:
+        * fast/js/script-tests/number-toExponential.js:
+        * fast/js/script-tests/number-tofixed.js:
+        * fast/js/script-tests/number-toprecision.js:
+
 2010-08-24  Eric Seidel  <eric at webkit.org>
 
         Reviewed by Adam Barth.
diff --git a/LayoutTests/fast/js/kde/Number-expected.txt b/LayoutTests/fast/js/kde/Number-expected.txt
index 8ecb8aa..cb50804 100644
--- a/LayoutTests/fast/js/kde/Number-expected.txt
+++ b/LayoutTests/fast/js/kde/Number-expected.txt
@@ -188,11 +188,11 @@ PASS Number(123.4567890123456789012).toExponential(12) is "1.234567890123e+2"
 PASS Number(123.4567890123456789012).toExponential(13) is "1.2345678901235e+2"
 PASS Number(123.4567890123456789012).toExponential(14) is "1.23456789012346e+2"
 PASS Number(123.4567890123456789012).toExponential(15) is "1.234567890123457e+2"
-PASS Number(123.4567890123456789012).toExponential(16) is "1.2345678901234570e+2"
-PASS Number(123.4567890123456789012).toExponential(17) is "1.23456789012345700e+2"
-PASS Number(123.4567890123456789012).toExponential(18) is "1.234567890123457100e+2"
-PASS Number(123.4567890123456789012).toExponential(19) is "1.2345678901234570000e+2"
-PASS Number(123.4567890123456789012).toExponential(20) is "1.23456789012345700000e+2"
+PASS Number(123.4567890123456789012).toExponential(16) is "1.2345678901234568e+2"
+PASS Number(123.4567890123456789012).toExponential(17) is "1.23456789012345680e+2"
+PASS Number(123.4567890123456789012).toExponential(18) is "1.234567890123456800e+2"
+PASS Number(123.4567890123456789012).toExponential(19) is "1.2345678901234567000e+2"
+PASS Number(123.4567890123456789012).toExponential(20) is "1.23456789012345680000e+2"
 PASS try { Number(123.4567890123456789012).toExponential(21) } catch (e) { String(e).indexOf('Range') >= 0; } is true
 PASS Number(-123.4567890123456789012).toExponential() is "-1.2345678901234568e+2"
 PASS try { Number(-123.4567890123456789012).toExponential(-1) } catch (e) { String(e).indexOf('Range') >= 0; } is true
@@ -212,11 +212,11 @@ PASS Number(-123.4567890123456789012).toExponential(12) is "-1.234567890123e+2"
 PASS Number(-123.4567890123456789012).toExponential(13) is "-1.2345678901235e+2"
 PASS Number(-123.4567890123456789012).toExponential(14) is "-1.23456789012346e+2"
 PASS Number(-123.4567890123456789012).toExponential(15) is "-1.234567890123457e+2"
-PASS Number(-123.4567890123456789012).toExponential(16) is "-1.2345678901234570e+2"
-PASS Number(-123.4567890123456789012).toExponential(17) is "-1.23456789012345700e+2"
-PASS Number(-123.4567890123456789012).toExponential(18) is "-1.234567890123457100e+2"
-PASS Number(-123.4567890123456789012).toExponential(19) is "-1.2345678901234570000e+2"
-PASS Number(-123.4567890123456789012).toExponential(20) is "-1.23456789012345700000e+2"
+PASS Number(-123.4567890123456789012).toExponential(16) is "-1.2345678901234568e+2"
+PASS Number(-123.4567890123456789012).toExponential(17) is "-1.23456789012345680e+2"
+PASS Number(-123.4567890123456789012).toExponential(18) is "-1.234567890123456800e+2"
+PASS Number(-123.4567890123456789012).toExponential(19) is "-1.2345678901234567000e+2"
+PASS Number(-123.4567890123456789012).toExponential(20) is "-1.23456789012345680000e+2"
 PASS try { Number(-123.4567890123456789012).toExponential(21) } catch (e) { String(e).indexOf('Range') >= 0; } is true
 PASS Number(.0000000000000000000001).toExponential() is "1e-22"
 PASS Number(.0000000000000000000012).toExponential() is "1.2e-21"
@@ -348,11 +348,11 @@ PASS Number(0.0001234567890123456789012345).toPrecision(13) is "0.00012345678901
 PASS Number(0.0001234567890123456789012345).toPrecision(14) is "0.00012345678901235"
 PASS Number(0.0001234567890123456789012345).toPrecision(15) is "0.000123456789012346"
 PASS Number(0.0001234567890123456789012345).toPrecision(16) is "0.0001234567890123457"
-PASS Number(0.0001234567890123456789012345).toPrecision(17) is "0.00012345678901234568"
-PASS Number(0.0001234567890123456789012345).toPrecision(18) is "0.000123456789012345680"
-PASS Number(0.0001234567890123456789012345).toPrecision(19) is "0.0001234567890123456800"
-PASS Number(0.0001234567890123456789012345).toPrecision(20) is "0.00012345678901234567000"
-PASS Number(0.0001234567890123456789012345).toPrecision(21) is "0.000123456789012345680000"
+FAIL Number(0.0001234567890123456789012345).toPrecision(17) should be 0.00012345678901234567. Was 0.00012345678901234568.
+FAIL Number(0.0001234567890123456789012345).toPrecision(18) should be 0.000123456789012345671. Was 0.000123456789012345660.
+FAIL Number(0.0001234567890123456789012345).toPrecision(19) should be 0.0001234567890123456713. Was 0.0001234567890123456800.
+FAIL Number(0.0001234567890123456789012345).toPrecision(20) should be 0.00012345678901234567130. Was 0.00012345678901234565000.
+FAIL Number(0.0001234567890123456789012345).toPrecision(21) should be 0.000123456789012345671297. Was 0.000123456789012345670000.
 PASS Number(12345.67890123456789012345).toPrecision() is "12345.678901234567"
 PASS Number(12345.67890123456789012345).toPrecision(1) is "1e+4"
 PASS Number(12345.67890123456789012345).toPrecision(2) is "1.2e+4"
@@ -373,7 +373,7 @@ PASS Number(12345.67890123456789012345).toPrecision(16) is "12345.67890123457"
 PASS Number(12345.67890123456789012345).toPrecision(17) is "12345.678901234568"
 PASS Number(12345.67890123456789012345).toPrecision(18) is "12345.6789012345660"
 PASS Number(12345.67890123456789012345).toPrecision(19) is "12345.67890123456800"
-PASS Number(12345.67890123456789012345).toPrecision(20) is "12345.678901234565000"
+PASS Number(12345.67890123456789012345).toPrecision(20) is "12345.678901234567000"
 PASS Number(12345.67890123456789012345).toPrecision(21) is "12345.6789012345670000"
 PASS Number(-.0000000012345).toPrecision(2) is "-1.2e-9"
 PASS Number(-.000000012345).toPrecision(2) is "-1.2e-8"
@@ -408,11 +408,11 @@ PASS Number(-0.0001234567890123456789012345).toPrecision(13) is "-0.000123456789
 PASS Number(-0.0001234567890123456789012345).toPrecision(14) is "-0.00012345678901235"
 PASS Number(-0.0001234567890123456789012345).toPrecision(15) is "-0.000123456789012346"
 PASS Number(-0.0001234567890123456789012345).toPrecision(16) is "-0.0001234567890123457"
-PASS Number(-0.0001234567890123456789012345).toPrecision(17) is "-0.00012345678901234568"
-PASS Number(-0.0001234567890123456789012345).toPrecision(18) is "-0.000123456789012345680"
-PASS Number(-0.0001234567890123456789012345).toPrecision(19) is "-0.0001234567890123456800"
-PASS Number(-0.0001234567890123456789012345).toPrecision(20) is "-0.00012345678901234567000"
-PASS Number(-0.0001234567890123456789012345).toPrecision(21) is "-0.000123456789012345680000"
+FAIL Number(-0.0001234567890123456789012345).toPrecision(17) should be -0.00012345678901234567. Was -0.00012345678901234568.
+FAIL Number(-0.0001234567890123456789012345).toPrecision(18) should be -0.000123456789012345671. Was -0.000123456789012345660.
+FAIL Number(-0.0001234567890123456789012345).toPrecision(19) should be -0.0001234567890123456713. Was -0.0001234567890123456800.
+FAIL Number(-0.0001234567890123456789012345).toPrecision(20) should be -0.00012345678901234567130. Was -0.00012345678901234565000.
+FAIL Number(-0.0001234567890123456789012345).toPrecision(21) should be -0.000123456789012345671297. Was -0.000123456789012345670000.
 PASS Number(-12345.67890123456789012345).toPrecision() is "-12345.678901234567"
 PASS Number(-12345.67890123456789012345).toPrecision(1) is "-1e+4"
 PASS Number(-12345.67890123456789012345).toPrecision(2) is "-1.2e+4"
@@ -433,7 +433,7 @@ PASS Number(-12345.67890123456789012345).toPrecision(16) is "-12345.67890123457"
 PASS Number(-12345.67890123456789012345).toPrecision(17) is "-12345.678901234568"
 PASS Number(-12345.67890123456789012345).toPrecision(18) is "-12345.6789012345660"
 PASS Number(-12345.67890123456789012345).toPrecision(19) is "-12345.67890123456800"
-PASS Number(-12345.67890123456789012345).toPrecision(20) is "-12345.678901234565000"
+PASS Number(-12345.67890123456789012345).toPrecision(20) is "-12345.678901234567000"
 PASS Number(-12345.67890123456789012345).toPrecision(21) is "-12345.6789012345670000"
 PASS Number(0).toPrecision() is "0"
 PASS Number(0).toPrecision(1) is "0"
diff --git a/LayoutTests/fast/js/kde/script-tests/Number.js b/LayoutTests/fast/js/kde/script-tests/Number.js
index 47b2ca3..05db865 100644
--- a/LayoutTests/fast/js/kde/script-tests/Number.js
+++ b/LayoutTests/fast/js/kde/script-tests/Number.js
@@ -203,11 +203,11 @@ shouldBe("Number(123.4567890123456789012).toExponential(12)","\"1.234567890123e+
 shouldBe("Number(123.4567890123456789012).toExponential(13)","\"1.2345678901235e+2\"");
 shouldBe("Number(123.4567890123456789012).toExponential(14)","\"1.23456789012346e+2\"");
 shouldBe("Number(123.4567890123456789012).toExponential(15)","\"1.234567890123457e+2\"");
-shouldBe("Number(123.4567890123456789012).toExponential(16)","\"1.2345678901234570e+2\"");
-shouldBe("Number(123.4567890123456789012).toExponential(17)","\"1.23456789012345700e+2\"");
-shouldBe("Number(123.4567890123456789012).toExponential(18)","\"1.234567890123457100e+2\"");
-shouldBe("Number(123.4567890123456789012).toExponential(19)","\"1.2345678901234570000e+2\"");
-shouldBe("Number(123.4567890123456789012).toExponential(20)","\"1.23456789012345700000e+2\"");
+shouldBe("Number(123.4567890123456789012).toExponential(16)","\"1.2345678901234568e+2\"");
+shouldBe("Number(123.4567890123456789012).toExponential(17)","\"1.23456789012345680e+2\"");
+shouldBe("Number(123.4567890123456789012).toExponential(18)","\"1.234567890123456800e+2\"");
+shouldBe("Number(123.4567890123456789012).toExponential(19)","\"1.2345678901234567000e+2\"");
+shouldBe("Number(123.4567890123456789012).toExponential(20)","\"1.23456789012345680000e+2\"");
 shouldBeTrue("try { Number(123.4567890123456789012).toExponential(21) } catch (e) { String(e).indexOf('Range') >= 0; }");
 shouldBe("Number(-123.4567890123456789012).toExponential()","\"-1.2345678901234568e+2\"");
 shouldBeTrue("try { Number(-123.4567890123456789012).toExponential(-1) } catch (e) { String(e).indexOf('Range') >= 0; }");
@@ -227,11 +227,11 @@ shouldBe("Number(-123.4567890123456789012).toExponential(12)","\"-1.234567890123
 shouldBe("Number(-123.4567890123456789012).toExponential(13)","\"-1.2345678901235e+2\"");
 shouldBe("Number(-123.4567890123456789012).toExponential(14)","\"-1.23456789012346e+2\"");
 shouldBe("Number(-123.4567890123456789012).toExponential(15)","\"-1.234567890123457e+2\"");
-shouldBe("Number(-123.4567890123456789012).toExponential(16)","\"-1.2345678901234570e+2\"");
-shouldBe("Number(-123.4567890123456789012).toExponential(17)","\"-1.23456789012345700e+2\"");
-shouldBe("Number(-123.4567890123456789012).toExponential(18)","\"-1.234567890123457100e+2\"");
-shouldBe("Number(-123.4567890123456789012).toExponential(19)","\"-1.2345678901234570000e+2\"");
-shouldBe("Number(-123.4567890123456789012).toExponential(20)","\"-1.23456789012345700000e+2\"");
+shouldBe("Number(-123.4567890123456789012).toExponential(16)","\"-1.2345678901234568e+2\"");
+shouldBe("Number(-123.4567890123456789012).toExponential(17)","\"-1.23456789012345680e+2\"");
+shouldBe("Number(-123.4567890123456789012).toExponential(18)","\"-1.234567890123456800e+2\"");
+shouldBe("Number(-123.4567890123456789012).toExponential(19)","\"-1.2345678901234567000e+2\"");
+shouldBe("Number(-123.4567890123456789012).toExponential(20)","\"-1.23456789012345680000e+2\"");
 shouldBeTrue("try { Number(-123.4567890123456789012).toExponential(21) } catch (e) { String(e).indexOf('Range') >= 0; }");
 shouldBe("Number(.0000000000000000000001).toExponential()","\"1e-22\"");
 shouldBe("Number(.0000000000000000000012).toExponential()","\"1.2e-21\"");
@@ -364,11 +364,11 @@ shouldBe("Number(0.0001234567890123456789012345).toPrecision(13)","\"0.000123456
 shouldBe("Number(0.0001234567890123456789012345).toPrecision(14)","\"0.00012345678901235\"");
 shouldBe("Number(0.0001234567890123456789012345).toPrecision(15)","\"0.000123456789012346\"");
 shouldBe("Number(0.0001234567890123456789012345).toPrecision(16)","\"0.0001234567890123457\"");
-shouldBe("Number(0.0001234567890123456789012345).toPrecision(17)","\"0.00012345678901234568\"");
-shouldBe("Number(0.0001234567890123456789012345).toPrecision(18)","\"0.000123456789012345680\"");
-shouldBe("Number(0.0001234567890123456789012345).toPrecision(19)","\"0.0001234567890123456800\"");
-shouldBe("Number(0.0001234567890123456789012345).toPrecision(20)","\"0.00012345678901234567000\"");
-shouldBe("Number(0.0001234567890123456789012345).toPrecision(21)","\"0.000123456789012345680000\"");
+shouldBe("Number(0.0001234567890123456789012345).toPrecision(17)","\"0.00012345678901234567\"");
+shouldBe("Number(0.0001234567890123456789012345).toPrecision(18)","\"0.000123456789012345671\"");
+shouldBe("Number(0.0001234567890123456789012345).toPrecision(19)","\"0.0001234567890123456713\"");
+shouldBe("Number(0.0001234567890123456789012345).toPrecision(20)","\"0.00012345678901234567130\"");
+shouldBe("Number(0.0001234567890123456789012345).toPrecision(21)","\"0.000123456789012345671297\"");
 shouldBe("Number(12345.67890123456789012345).toPrecision()","\"12345.678901234567\"");
 shouldBe("Number(12345.67890123456789012345).toPrecision(1)","\"1e+4\"");
 shouldBe("Number(12345.67890123456789012345).toPrecision(2)","\"1.2e+4\"");
@@ -389,7 +389,7 @@ shouldBe("Number(12345.67890123456789012345).toPrecision(16)","\"12345.678901234
 shouldBe("Number(12345.67890123456789012345).toPrecision(17)","\"12345.678901234568\"");
 shouldBe("Number(12345.67890123456789012345).toPrecision(18)","\"12345.6789012345660\"");
 shouldBe("Number(12345.67890123456789012345).toPrecision(19)","\"12345.67890123456800\"");
-shouldBe("Number(12345.67890123456789012345).toPrecision(20)","\"12345.678901234565000\"");
+shouldBe("Number(12345.67890123456789012345).toPrecision(20)","\"12345.678901234567000\"");
 shouldBe("Number(12345.67890123456789012345).toPrecision(21)","\"12345.6789012345670000\"");
 shouldBe("Number(-.0000000012345).toPrecision(2)","\"-1.2e-9\"");
 shouldBe("Number(-.000000012345).toPrecision(2)","\"-1.2e-8\"");
@@ -424,11 +424,11 @@ shouldBe("Number(-0.0001234567890123456789012345).toPrecision(13)","\"-0.0001234
 shouldBe("Number(-0.0001234567890123456789012345).toPrecision(14)","\"-0.00012345678901235\"");
 shouldBe("Number(-0.0001234567890123456789012345).toPrecision(15)","\"-0.000123456789012346\"");
 shouldBe("Number(-0.0001234567890123456789012345).toPrecision(16)","\"-0.0001234567890123457\"");
-shouldBe("Number(-0.0001234567890123456789012345).toPrecision(17)","\"-0.00012345678901234568\"");
-shouldBe("Number(-0.0001234567890123456789012345).toPrecision(18)","\"-0.000123456789012345680\"");
-shouldBe("Number(-0.0001234567890123456789012345).toPrecision(19)","\"-0.0001234567890123456800\"");
-shouldBe("Number(-0.0001234567890123456789012345).toPrecision(20)","\"-0.00012345678901234567000\"");
-shouldBe("Number(-0.0001234567890123456789012345).toPrecision(21)","\"-0.000123456789012345680000\"");
+shouldBe("Number(-0.0001234567890123456789012345).toPrecision(17)","\"-0.00012345678901234567\"");
+shouldBe("Number(-0.0001234567890123456789012345).toPrecision(18)","\"-0.000123456789012345671\"");
+shouldBe("Number(-0.0001234567890123456789012345).toPrecision(19)","\"-0.0001234567890123456713\"");
+shouldBe("Number(-0.0001234567890123456789012345).toPrecision(20)","\"-0.00012345678901234567130\"");
+shouldBe("Number(-0.0001234567890123456789012345).toPrecision(21)","\"-0.000123456789012345671297\"");
 shouldBe("Number(-12345.67890123456789012345).toPrecision()","\"-12345.678901234567\"");
 shouldBe("Number(-12345.67890123456789012345).toPrecision(1)","\"-1e+4\"");
 shouldBe("Number(-12345.67890123456789012345).toPrecision(2)","\"-1.2e+4\"");
@@ -449,7 +449,7 @@ shouldBe("Number(-12345.67890123456789012345).toPrecision(16)","\"-12345.6789012
 shouldBe("Number(-12345.67890123456789012345).toPrecision(17)","\"-12345.678901234568\"");
 shouldBe("Number(-12345.67890123456789012345).toPrecision(18)","\"-12345.6789012345660\"");
 shouldBe("Number(-12345.67890123456789012345).toPrecision(19)","\"-12345.67890123456800\"");
-shouldBe("Number(-12345.67890123456789012345).toPrecision(20)","\"-12345.678901234565000\"");
+shouldBe("Number(-12345.67890123456789012345).toPrecision(20)","\"-12345.678901234567000\"");
 shouldBe("Number(-12345.67890123456789012345).toPrecision(21)","\"-12345.6789012345670000\"");
 shouldBe("Number(0).toPrecision()","\"0\"");
 shouldBe("Number(0).toPrecision(1)","\"0\"");
diff --git a/LayoutTests/fast/js/number-toExponential-expected.txt b/LayoutTests/fast/js/number-toExponential-expected.txt
index c789e6d..0e940ec 100644
--- a/LayoutTests/fast/js/number-toExponential-expected.txt
+++ b/LayoutTests/fast/js/number-toExponential-expected.txt
@@ -17,12 +17,12 @@ PASS (123.456).toExponential(3) is "1.235e+2"
 PASS (123.456).toExponential(5) is "1.23456e+2"
 PASS (123.456).toExponential(6) is "1.234560e+2"
 FAIL (123.456).toExponential(20) should be 1.23456000000000003070e+2. Was 1.23456000000000000000e+2.
-FAIL (123.456).toExponential(21) should be 1.234560000000000030695e+2. Threw exception RangeError: toExponential() argument must between 0 and 20
-FAIL (123.456).toExponential(100) should be 1.2345600000000000306954461848363280296325683593750000000000000000000000000000000000000000000000000000e+2. Threw exception RangeError: toExponential() argument must between 0 and 20
-PASS (123.456).toExponential(101) threw exception RangeError: toExponential() argument must between 0 and 20.
-PASS (123.456).toExponential(-1) threw exception RangeError: toExponential() argument must between 0 and 20.
-PASS (1234.567).toExponential(posInf) threw exception RangeError: toExponential() argument must between 0 and 20.
-PASS (1234.567).toExponential(negInf) threw exception RangeError: toExponential() argument must between 0 and 20.
+PASS (123.456).toExponential(21) threw exception RangeError: toExponential() argument must be between 0 and 20.
+PASS (123.456).toExponential(100) threw exception RangeError: toExponential() argument must be between 0 and 20.
+PASS (123.456).toExponential(101) threw exception RangeError: toExponential() argument must be between 0 and 20.
+PASS (123.456).toExponential(-1) threw exception RangeError: toExponential() argument must be between 0 and 20.
+PASS (1234.567).toExponential(posInf) threw exception RangeError: toExponential() argument must be between 0 and 20.
+PASS (1234.567).toExponential(negInf) threw exception RangeError: toExponential() argument must be between 0 and 20.
 PASS posInf.toExponential() is "Infinity"
 PASS negInf.toExponential() is "-Infinity"
 PASS nan.toExponential() is "NaN"
diff --git a/LayoutTests/fast/js/number-tofixed-expected.txt b/LayoutTests/fast/js/number-tofixed-expected.txt
index 8f053e3..8751df5 100644
--- a/LayoutTests/fast/js/number-tofixed-expected.txt
+++ b/LayoutTests/fast/js/number-tofixed-expected.txt
@@ -42,16 +42,16 @@ PASS (1234.567).toFixed(2) is "1234.57"
 PASS (1234.567).toFixed(2.9) is "1234.57"
 PASS (1234.567).toFixed(5) is "1234.56700"
 FAIL (1234.567).toFixed(20) should be 1234.56700000000000727596. Was 1234.56700000000000000000.
-FAIL (1234.567).toFixed(21) should be 1234.567000000000007275958. Threw exception RangeError: toFixed() digits argument must be between 0 and 20
-FAIL (1234.567).toFixed(100) should be 1234.5670000000000072759576141834259033203125000000000000000000000000000000000000000000000000000000000000. Threw exception RangeError: toFixed() digits argument must be between 0 and 20
-PASS (1234.567).toFixed(101) threw exception RangeError: toFixed() digits argument must be between 0 and 20.
-FAIL (1234.567).toFixed(-1) should be 1230. Threw exception RangeError: toFixed() digits argument must be between 0 and 20
-FAIL (1234.567).toFixed(-4) should be 0. Threw exception RangeError: toFixed() digits argument must be between 0 and 20
-FAIL (1234.567).toFixed(-5) should be 0. Threw exception RangeError: toFixed() digits argument must be between 0 and 20
-FAIL (1234.567).toFixed(-20) should be 0. Threw exception RangeError: toFixed() digits argument must be between 0 and 20
-PASS (1234.567).toFixed(-21) threw exception RangeError: toFixed() digits argument must be between 0 and 20.
-PASS (1234.567).toFixed(posInf) threw exception RangeError: toFixed() digits argument must be between 0 and 20.
-PASS (1234.567).toFixed(negInf) threw exception RangeError: toFixed() digits argument must be between 0 and 20.
+PASS (1234.567).toFixed(21) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(100) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(101) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(-1) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(-4) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(-5) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(-20) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(-21) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(posInf) threw exception RangeError: toFixed() argument must be between 0 and 20.
+PASS (1234.567).toFixed(negInf) threw exception RangeError: toFixed() argument must be between 0 and 20.
 PASS posInf.toFixed() is "Infinity"
 PASS negInf.toFixed() is "-Infinity"
 PASS nan.toFixed() is "NaN"
diff --git a/LayoutTests/fast/js/number-toprecision-expected.txt b/LayoutTests/fast/js/number-toprecision-expected.txt
index 631fa80..71303d7 100644
--- a/LayoutTests/fast/js/number-toprecision-expected.txt
+++ b/LayoutTests/fast/js/number-toprecision-expected.txt
@@ -23,8 +23,8 @@ PASS (1234.567).toPrecision(2) is "1.2e+3"
 PASS (1234.567).toPrecision(2.9) is "1.2e+3"
 PASS (1234.567).toPrecision(5) is "1234.6"
 FAIL (1234.567).toPrecision(21) should be 1234.56700000000000728. Was 1234.56700000000000000.
-FAIL (1234.567).toPrecision(22) should be 1234.567000000000007276. Threw exception RangeError: toPrecision() argument must be between 1 and 21
-FAIL (1234.567).toPrecision(100) should be 1234.567000000000007275957614183425903320312500000000000000000000000000000000000000000000000000000000. Threw exception RangeError: toPrecision() argument must be between 1 and 21
+PASS (1234.567).toPrecision(22) threw exception RangeError: toPrecision() argument must be between 1 and 21.
+PASS (1234.567).toPrecision(100) threw exception RangeError: toPrecision() argument must be between 1 and 21.
 PASS (1234.567).toPrecision(101) threw exception RangeError: toPrecision() argument must be between 1 and 21.
 PASS (1234.567).toPrecision(posInf) threw exception RangeError: toPrecision() argument must be between 1 and 21.
 PASS (1234.567).toPrecision(negInf) threw exception RangeError: toPrecision() argument must be between 1 and 21.
diff --git a/LayoutTests/fast/js/script-tests/number-toExponential.js b/LayoutTests/fast/js/script-tests/number-toExponential.js
index ad9cc31..716ad56 100644
--- a/LayoutTests/fast/js/script-tests/number-toExponential.js
+++ b/LayoutTests/fast/js/script-tests/number-toExponential.js
@@ -29,8 +29,8 @@ shouldBeEqualToString("(123.456).toExponential(6)", "1.234560e+2");
 shouldBeEqualToString("(123.456).toExponential(20)", "1.23456000000000003070e+2");
 
 // SpiderMonkey allows precision values 0 to 100, we only allow 0 to 20 currently
-shouldBeEqualToString("(123.456).toExponential(21)", "1.234560000000000030695e+2");
-shouldBeEqualToString("(123.456).toExponential(100)", "1.2345600000000000306954461848363280296325683593750000000000000000000000000000000000000000000000000000e+2");
+shouldThrow("(123.456).toExponential(21)");
+shouldThrow("(123.456).toExponential(100)");
 shouldThrow("(123.456).toExponential(101)");
 shouldThrow("(123.456).toExponential(-1)");
 
diff --git a/LayoutTests/fast/js/script-tests/number-tofixed.js b/LayoutTests/fast/js/script-tests/number-tofixed.js
index ec50507..b6b70bf 100644
--- a/LayoutTests/fast/js/script-tests/number-tofixed.js
+++ b/LayoutTests/fast/js/script-tests/number-tofixed.js
@@ -61,14 +61,14 @@ shouldBeEqualToString("(1234.567).toFixed(2.9)", "1234.57");
 shouldBeEqualToString("(1234.567).toFixed(5)", "1234.56700");
 shouldBeEqualToString("(1234.567).toFixed(20)", "1234.56700000000000727596");
 
-// SpiderMonkey allows precision values -20 to 100, we only allow 0 to 20 currently
-shouldBeEqualToString("(1234.567).toFixed(21)", "1234.567000000000007275958");
-shouldBeEqualToString("(1234.567).toFixed(100)", "1234.5670000000000072759576141834259033203125000000000000000000000000000000000000000000000000000000000000");
+// SpiderMonkey allows precision values -20 to 100, the spec only allows 0 to 20
+shouldThrow("(1234.567).toFixed(21)");
+shouldThrow("(1234.567).toFixed(100)");
 shouldThrow("(1234.567).toFixed(101)");
-shouldBeEqualToString("(1234.567).toFixed(-1)", "1230");
-shouldBeEqualToString("(1234.567).toFixed(-4)", "0");
-shouldBeEqualToString("(1234.567).toFixed(-5)", "0");
-shouldBeEqualToString("(1234.567).toFixed(-20)", "0");
+shouldThrow("(1234.567).toFixed(-1)");
+shouldThrow("(1234.567).toFixed(-4)");
+shouldThrow("(1234.567).toFixed(-5)");
+shouldThrow("(1234.567).toFixed(-20)");
 shouldThrow("(1234.567).toFixed(-21)");
 
 shouldThrow("(1234.567).toFixed(posInf)");
diff --git a/LayoutTests/fast/js/script-tests/number-toprecision.js b/LayoutTests/fast/js/script-tests/number-toprecision.js
index ffc960f..c48b33a 100644
--- a/LayoutTests/fast/js/script-tests/number-toprecision.js
+++ b/LayoutTests/fast/js/script-tests/number-toprecision.js
@@ -28,9 +28,9 @@ shouldBeEqualToString("(1234.567).toPrecision(2)", "1.2e+3");
 shouldBeEqualToString("(1234.567).toPrecision(2.9)", "1.2e+3");
 shouldBeEqualToString("(1234.567).toPrecision(5)", "1234.6");
 shouldBeEqualToString("(1234.567).toPrecision(21)", "1234.56700000000000728");
-// SpiderMonkey allows precision values 1 to 100, we only allow 1 to 21 currently
-shouldBeEqualToString("(1234.567).toPrecision(22)", "1234.567000000000007276");
-shouldBeEqualToString("(1234.567).toPrecision(100)", "1234.567000000000007275957614183425903320312500000000000000000000000000000000000000000000000000000000");
+// SpiderMonkey allows precision values 1 to 100, we implement the spec and only allow 1 to 21.
+shouldThrow("(1234.567).toPrecision(22)");
+shouldThrow("(1234.567).toPrecision(100)");
 shouldThrow("(1234.567).toPrecision(101)");
 
 shouldThrow("(1234.567).toPrecision(posInf)");
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 8e7876c..b24c8bb 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,13 @@
+2010-08-23  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        https://bugs.webkit.org/show_bug.cgi?id=44487
+
+        * html/LegacyHTMLTreeBuilder.cpp:
+        (WebCore::serializeForNumberType):
+            Update function call to numberToString.
+
 2010-08-24  Eric Seidel  <eric at webkit.org>
 
         Reviewed by Adam Barth.
@@ -1126,6 +1136,7 @@
 
         * html/HTMLTreeBuilder.cpp:
 
+>>>>>>> .r65945
 2010-08-23  Adam Barth  <abarth at webkit.org>
 
         Reviewed by Eric Seidel.
@@ -4599,7 +4610,6 @@
         * rendering/RenderBlock.cpp:
         (WebCore::RenderBlock::removeChild):
 
->>>>>>> .r65561
 2010-08-17  Darin Fisher  <darin at chromium.org>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/html/HTMLTreeBuilder.cpp b/WebCore/html/HTMLTreeBuilder.cpp
index c620c5d..3904875 100644
--- a/WebCore/html/HTMLTreeBuilder.cpp
+++ b/WebCore/html/HTMLTreeBuilder.cpp
@@ -2850,11 +2850,9 @@ 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.
-    DtoaBuffer buffer;
-    unsigned length;
-    doubleToStringInJavaScriptFormat(number, buffer, &length);
-    return String(buffer, length);
-}
+    NumberToStringBuffer buffer;
+    return String(buffer, numberToString(number, buffer));
+ }
 
 // FIXME: Move this function to a more appropriate place.
 bool parseToDoubleForNumberType(const String& src, double* out)

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list