Bug 1020420 part 3 - Make parseFloat work with Latin1 strings. r=njn
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 06 Jun 2014 11:17:51 +0200
changeset 206297 654117be57c2a674b7b80e8314ed962a67f97738
parent 206296 1962fd3aa8193c1a4678961833a1b15a4c241258
child 206298 7e7061043b859b4493a3bb9cf5a62fd9da6b672f
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [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 3 - Make parseFloat work with Latin1 strings. r=njn
js/src/jit-test/tests/latin1/parseInt-parseFloat.js
js/src/jsnum.cpp
js/src/jsnum.h
--- a/js/src/jit-test/tests/latin1/parseInt-parseFloat.js
+++ b/js/src/jit-test/tests/latin1/parseInt-parseFloat.js
@@ -1,20 +1,39 @@
 function testParseInt() {
     // Latin1
     assertEq(parseInt(toLatin1("12345abc")), 12345);
     assertEq(parseInt(toLatin1("0x5")), 0x5);
     assertEq(parseInt(toLatin1("-123")), -123);
     assertEq(parseInt(toLatin1("xyz")), NaN);
     assertEq(parseInt(toLatin1("1234GHI"), 17), 94298);
     assertEq(parseInt(toLatin1("9007199254749999")), 9007199254750000);
-    assertEq(parseInt(toLatin1("9007199254749998"), 16), 10378291982571444000);
+    assertEq(parseInt(toLatin1("  9007199254749998"), 16), 10378291982571444000);
 
     // TwoByte
     assertEq(parseInt("12345abc\u1200"), 12345);
     assertEq(parseInt("0x5\u1200"), 0x5);
     assertEq(parseInt("  -123\u1200"), -123);
     assertEq(parseInt("\u1200"), NaN);
     assertEq(parseInt("1234GHI\u1200", 17), 94298);
     assertEq(parseInt("9007199254749999\u1200"), 9007199254750000);
-    assertEq(parseInt("9007199254749998\u1200", 16), 10378291982571444000);
+    assertEq(parseInt("  9007199254749998\u1200", 16), 10378291982571444000);
 }
 testParseInt();
+
+function testParseFloat() {
+    // Latin1
+    assertEq(parseFloat(toLatin1("3.1415")), 3.1415);
+    assertEq(parseFloat(toLatin1("  -1234")), -1234);
+    assertEq(parseFloat(toLatin1("\u00AA")), NaN);
+    assertEq(parseFloat(toLatin1("Infinityabc")), Infinity);
+    assertEq(parseFloat(toLatin1("-Infinity")), -Infinity);
+    assertEq(parseFloat(toLatin1("\t\t\t+Infinity")), Infinity);
+
+    // TwoByte
+    assertEq(parseFloat("3.1415\u0FFF"), 3.1415);
+    assertEq(parseFloat("  -1234\u0FFF"), -1234);
+    assertEq(parseFloat("\u00AA\u0FFF"), NaN);
+    assertEq(parseFloat("Infinityabc\u0FFF"), Infinity);
+    assertEq(parseFloat("-Infinity\u0FFF"), -Infinity);
+    assertEq(parseFloat("\t\t\t+Infinity\u0FFF"), Infinity);
+}
+testParseFloat();
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -302,31 +302,43 @@ static bool
 num_parseFloat(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() == 0) {
         args.rval().setNaN();
         return true;
     }
+
     JSString *str = ToString<CanGC>(cx, args[0]);
     if (!str)
         return false;
-    const jschar *bp = str->getChars(cx);
-    if (!bp)
+
+    JSLinearString *linear = str->ensureLinear(cx);
+    if (!linear)
         return false;
-    const jschar *end = bp + str->length();
-    const jschar *ep;
+
     double d;
-    if (!js_strtod(cx, bp, end, &ep, &d))
-        return false;
-    if (ep == bp) {
-        args.rval().setNaN();
-        return true;
+    AutoCheckCannotGC nogc;
+    if (linear->hasLatin1Chars()) {
+        const Latin1Char *begin = linear->latin1Chars(nogc);
+        const Latin1Char *end;
+        if (!js_strtod(cx, begin, begin + linear->length(), &end, &d))
+            return false;
+        if (end == begin)
+            d = GenericNaN();
+    } else {
+        const jschar *begin = linear->twoByteChars(nogc);
+        const jschar *end;
+        if (!js_strtod(cx, begin, begin + linear->length(), &end, &d))
+            return false;
+        if (end == begin)
+            d = GenericNaN();
     }
+
     args.rval().setDouble(d);
     return true;
 }
 
 template <typename CharT>
 static bool
 ParseIntImpl(JSContext *cx, const CharT *chars, size_t length, bool stripPrefix, int32_t radix,
              double *res)
@@ -1726,21 +1738,22 @@ js::ToUint16Slow(JSContext *cx, const Ha
     unsigned m = JS_BIT(16);
     d = fmod(d, (double) m);
     if (d < 0)
         d += m;
     *out = (uint16_t) d;
     return true;
 }
 
+template <typename CharT>
 bool
-js_strtod(ThreadSafeContext *cx, const jschar *begin, const jschar *end,
-          const jschar **dEnd, double *d)
+js_strtod(ThreadSafeContext *cx, const CharT *begin, const CharT *end, const CharT **dEnd,
+          double *d)
 {
-    const jschar *s = SkipSpace(begin, end);
+    const CharT *s = SkipSpace(begin, end);
     size_t length = end - s;
 
     Vector<char, 32> chars(cx);
     if (!chars.growByUninitialized(length + 1))
         return false;
 
     size_t i = 0;
     for (; i < length; i++) {
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -170,22 +170,25 @@ num_parseInt(JSContext *cx, unsigned arg
 
 /*
  * Similar to strtod except that it replaces overflows with infinities of the
  * correct sign, and underflows with zeros of the correct sign.  Guaranteed to
  * return the closest double number to the given input in dp.
  *
  * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
  * the appropriate sign.  The case of the "Infinity" string must match exactly.
- * If the string does not contain a number, set *ep to s and return 0.0 in dp.
+ * If the string does not contain a number, set *dEnd to begin and return 0.0
+ * in *d.
+ *
  * Return false if out of memory.
  */
+template <typename CharT>
 extern bool
-js_strtod(js::ThreadSafeContext *cx, const jschar *s, const jschar *send,
-          const jschar **ep, double *dp);
+js_strtod(js::ThreadSafeContext *cx, const CharT *begin, const CharT *end,
+          const CharT **dEnd, double *d);
 
 extern bool
 js_num_toString(JSContext *cx, unsigned argc, js::Value *vp);
 
 extern bool
 js_num_valueOf(JSContext *cx, unsigned argc, js::Value *vp);
 
 namespace js {