Bug 1020420 part 4 - Make StringToNumber work with Latin1 strings. r=njn
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 06 Jun 2014 11:17:52 +0200
changeset 207382 7e7061043b859b4493a3bb9cf5a62fd9da6b672f
parent 207381 654117be57c2a674b7b80e8314ed962a67f97738
child 207383 ca725c15bdeb62c97ca0876a40aaacb8cac542e3
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1020420
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1020420 part 4 - Make StringToNumber work with Latin1 strings. r=njn
js/src/jit-test/tests/latin1/toNumber.js
js/src/jsnum.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/toNumber.js
@@ -0,0 +1,24 @@
+function testToNumber() {
+    // Latin1
+    assertEq(+toLatin1("12345.6"), 12345.6);
+    assertEq(+toLatin1("+123"), 123);
+    assertEq(+toLatin1("0xABC"), 0xABC);
+    assertEq(+toLatin1("112."), 112);
+    assertEq(+toLatin1("112.A"), NaN);
+    assertEq(+toLatin1("-Infinity"), -Infinity);
+
+    // TwoByte
+    function twoByte(s) {
+	s = "\u1200" + s;
+	s = s.substr(1);
+	assertEq(isLatin1(s), false);
+	return s;
+    }
+    assertEq(+twoByte("12345.6"), 12345.6);
+    assertEq(+twoByte("+123"), 123);
+    assertEq(+twoByte("0xABC"), 0xABC);
+    assertEq(+twoByte("112."), 112);
+    assertEq(+twoByte("112.A"), NaN);
+    assertEq(+twoByte("-Infinity"), -Infinity);
+}
+testToNumber();
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1471,41 +1471,42 @@ js::NumberValueToStringBuffer(JSContext 
     /*
      * Inflate to jschar string.  The input C-string characters are < 127, so
      * even if jschars are UTF-8, all chars should map to one jschar.
      */
     JS_ASSERT(!cbuf.dbuf && cstrlen < cbuf.sbufSize);
     return sb.appendInflated(cstr, cstrlen);
 }
 
+template <typename CharT>
 static bool
-CharsToNumber(ThreadSafeContext *cx, const jschar *chars, size_t length, double *result)
+CharsToNumber(ThreadSafeContext *cx, const CharT *chars, size_t length, double *result)
 {
     if (length == 1) {
-        jschar c = chars[0];
+        CharT c = chars[0];
         if ('0' <= c && c <= '9')
             *result = c - '0';
         else if (unicode::IsSpace(c))
             *result = 0.0;
         else
             *result = GenericNaN();
         return true;
     }
 
-    const jschar *end = chars + length;
-    const jschar *bp = SkipSpace(chars, end);
+    const CharT *end = chars + length;
+    const CharT *bp = SkipSpace(chars, end);
 
     /* ECMA doesn't allow signed hex numbers (bug 273467). */
     if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) {
         /*
          * It's probably a hex number.  Accept if there's at least one hex
          * digit after the 0x, and if no non-whitespace characters follow all
          * the hex digits.
          */
-        const jschar *endptr;
+        const CharT *endptr;
         double d;
         if (!GetPrefixInteger(cx, bp + 2, end, 16, &endptr, &d) ||
             endptr == bp + 2 ||
             SkipSpace(endptr, end) != end)
         {
             *result = GenericNaN();
         } else {
             *result = d;
@@ -1515,17 +1516,17 @@ CharsToNumber(ThreadSafeContext *cx, con
 
     /*
      * Note that ECMA doesn't treat a string beginning with a '0' as
      * an octal number here. This works because all such numbers will
      * be interpreted as decimal by js_strtod.  Also, any hex numbers
      * that have made it here (which can only be negative ones) will
      * be treated as 0 without consuming the 'x' by js_strtod.
      */
-    const jschar *ep;
+    const CharT *ep;
     double d;
     if (!js_strtod(cx, bp, end, &ep, &d)) {
         *result = GenericNaN();
         return false;
     }
 
     if (SkipSpace(ep, end) != end)
         *result = GenericNaN();
@@ -1538,17 +1539,19 @@ CharsToNumber(ThreadSafeContext *cx, con
 bool
 js::StringToNumber(ThreadSafeContext *cx, JSString *str, double *result)
 {
     AutoCheckCannotGC nogc;
     ScopedThreadSafeStringInspector inspector(str);
     if (!inspector.ensureChars(cx, nogc))
         return false;
 
-    return CharsToNumber(cx, inspector.twoByteChars(), str->length(), result);
+    return inspector.hasLatin1Chars()
+           ? CharsToNumber(cx, inspector.latin1Chars(), str->length(), result)
+           : CharsToNumber(cx, inspector.twoByteChars(), str->length(), result);
 }
 
 bool
 js::NonObjectToNumberSlow(ThreadSafeContext *cx, Value v, double *out)
 {
     JS_ASSERT(!v.isNumber());
     JS_ASSERT(!v.isObject());