Bug 786135 - Make parseInt(stringStartingWith0ButNot0xOr0X) parse as decimal to comply with ES5. r=dmandelin
authorJeff Walden <jwalden@mit.edu>
Mon, 28 Jan 2013 13:08:32 -0800
changeset 120152 67f7ebdea2fe875fa99a6b4e433aba296711f540
parent 120151 4baea9b16379fe875c96dcee6928b23e88387539
child 120153 f68f04e1fa230353566166a71397934b8e8f60d2
push id24239
push userryanvm@gmail.com
push dateTue, 29 Jan 2013 14:36:31 +0000
treeherdermozilla-central@d3a5e1de98b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmandelin
bugs786135
milestone21.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 786135 - Make parseInt(stringStartingWith0ButNot0xOr0X) parse as decimal to comply with ES5. r=dmandelin
js/src/jit-test/tests/basic/parseIntTests.js
js/src/jit-test/tests/basic/strictParseIntOctal.js
js/src/jsnum.cpp
js/src/tests/ecma/GlobalObject/15.1.2.2-1.js
js/src/tests/ecma/GlobalObject/15.1.2.2-2.js
js/src/tests/ecma/TypeConversion/9.3.1-3.js
js/src/tests/ecma_5/Global/parseInt-default-to-decimal.js
js/src/tests/js1_8_5/extensions/parseInt-octal.js
toolkit/components/places/tests/head_common.js
--- a/js/src/jit-test/tests/basic/parseIntTests.js
+++ b/js/src/jit-test/tests/basic/parseIntTests.js
@@ -14,10 +14,10 @@ function doParseIntTests() {
     outputs[7] = -1;
     for (var i = 0; i < 8; i++) {
         var testfn = new Function('return parseIntHelper(' + uneval(inputs[i]) + ');');
         assertEq(testfn(), outputs[i]);
     }
 }
 doParseIntTests();
 
-assertEq(parseInt("08"), 0);
-assertEq(parseInt("09"), 0);
+assertEq(parseInt("08"), 8);
+assertEq(parseInt("09"), 9);
--- a/js/src/jit-test/tests/basic/strictParseIntOctal.js
+++ b/js/src/jit-test/tests/basic/strictParseIntOctal.js
@@ -1,16 +1,16 @@
 "use strict";
 
-assertEq(parseInt("08"), 0);
-assertEq(parseInt("09"), 0);
-assertEq(parseInt("014"), 12);
+assertEq(parseInt("08"), 8);
+assertEq(parseInt("09"), 9);
+assertEq(parseInt("014"), 14);
 assertEq(parseInt("0xA"), 10);
-assertEq(parseInt("00123"), 83);
+assertEq(parseInt("00123"), 123);
 
 for (var i = 0; i < 5; i++)
 {
-  assertEq(parseInt("08"), 0);
-  assertEq(parseInt("09"), 0);
-  assertEq(parseInt("014"), 12);
+  assertEq(parseInt("08"), 8);
+  assertEq(parseInt("09"), 9);
+  assertEq(parseInt("014"), 14);
   assertEq(parseInt("0xA"), 10);
-  assertEq(parseInt("00123"), 83);
+  assertEq(parseInt("00123"), 123);
 }
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -276,70 +276,17 @@ num_parseFloat(JSContext *cx, unsigned a
     if (ep == bp) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     vp->setNumber(d);
     return JS_TRUE;
 }
 
-static bool
-ParseIntStringHelper(JSContext *cx, const jschar *ws, const jschar *end, int maybeRadix,
-                     bool stripPrefix, double *dp)
-{
-    JS_ASSERT(maybeRadix == 0 || (2 <= maybeRadix && maybeRadix <= 36));
-    JS_ASSERT(ws <= end);
-
-    const jschar *s = SkipSpace(ws, end);
-    JS_ASSERT(ws <= s);
-    JS_ASSERT(s <= end);
-
-    /* 15.1.2.2 steps 3-4. */
-    bool negative = (s != end && s[0] == '-');
-
-    /* 15.1.2.2 step 5. */
-    if (s != end && (s[0] == '-' || s[0] == '+'))
-        s++;
-
-    /* 15.1.2.2 step 9. */
-    int radix = maybeRadix;
-    if (radix == 0) {
-        if (end - s >= 2 && s[0] == '0' && (s[1] != 'x' && s[1] != 'X')) {
-            /*
-             * Non-standard: ES5 requires that parseInt interpret leading-zero
-             * strings not starting with "0x" or "0X" as decimal (absent an
-             * explicitly specified non-zero radix), but we continue to
-             * interpret such strings as octal, as per ES3 and web practice.
-             */
-            radix = 8;
-        } else {
-            radix = 10;
-        }
-    }
-
-    /* 15.1.2.2 step 10. */
-    if (stripPrefix) {
-        if (end - s >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
-            s += 2;
-            radix = 16;
-        }
-    }
-
-    /* 15.1.2.2 steps 11-14. */
-    const jschar *actualEnd;
-    if (!GetPrefixInteger(cx, s, end, radix, &actualEnd, dp))
-        return false;
-    if (s == actualEnd)
-        *dp = js_NaN;
-    else if (negative)
-        *dp = -*dp;
-    return true;
-}
-
-/* See ECMA 15.1.2.2. */
+/* ES5 15.1.2.2. */
 JSBool
 js::num_parseInt(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Fast paths and exceptional cases. */
     if (args.length() == 0) {
         args.rval().setDouble(js_NaN);
@@ -347,16 +294,17 @@ js::num_parseInt(JSContext *cx, unsigned
     }
 
     if (args.length() == 1 ||
         (args[1].isInt32() && (args[1].toInt32() == 0 || args[1].toInt32() == 10))) {
         if (args[0].isInt32()) {
             args.rval().set(args[0]);
             return true;
         }
+
         /*
          * Step 1 is |inputString = ToString(string)|. When string >=
          * 1e21, ToString(string) is in the form "NeM". 'e' marks the end of
          * the word, which would mean the result of parseInt(string) should be |N|.
          *
          * To preserve this behaviour, we can't use the fast-path when string >
          * 1e21, or else the result would be |NeM|.
          *
@@ -381,44 +329,74 @@ js::num_parseInt(JSContext *cx, unsigned
     }
 
     /* Step 1. */
     RootedString inputString(cx, ToString<CanGC>(cx, args[0]));
     if (!inputString)
         return false;
     args[0].setString(inputString);
 
-    /* 15.1.2.2 steps 6-8. */
+    /* Steps 6-9. */
     bool stripPrefix = true;
-    int32_t radix = 0;
-    if (args.length() > 1) {
+    int32_t radix;
+    if (!args.hasDefined(1)) {
+        radix = 10;
+    } else {
         if (!ToInt32(cx, args[1], &radix))
             return false;
-        if (radix != 0) {
+        if (radix == 0) {
+            radix = 10;
+        } else {
             if (radix < 2 || radix > 36) {
                 args.rval().setDouble(js_NaN);
                 return true;
             }
             if (radix != 16)
                 stripPrefix = false;
         }
     }
 
-    /* Steps 2-5, 9-14. */
-    const jschar *ws = inputString->getChars(cx);
-    if (!ws)
-        return false;
-    const jschar *end = ws + inputString->length();
+    /* Step 2. */
+    const jschar *s;
+    const jschar *end;
+    {
+        const jschar *ws = inputString->getChars(cx);
+        if (!ws)
+            return false;
+        end = ws + inputString->length();
+        s = SkipSpace(ws, end);
+
+        MOZ_ASSERT(ws <= s);
+        MOZ_ASSERT(s <= end);
+    }
+
+    /* Steps 3-4. */
+    bool negative = (s != end && s[0] == '-');
 
+    /* Step 5. */
+    if (s != end && (s[0] == '-' || s[0] == '+'))
+        s++;
+
+    /* Step 10. */
+    if (stripPrefix) {
+        if (end - s >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
+            s += 2;
+            radix = 16;
+        }
+    }
+
+    /* Steps 11-15. */
+    const jschar *actualEnd;
     double number;
-    if (!ParseIntStringHelper(cx, ws, end, radix, stripPrefix, &number))
+    if (!GetPrefixInteger(cx, s, end, radix, &actualEnd, &number))
         return false;
-
-    /* Step 15. */
-    args.rval().setNumber(number);
+    if (s == actualEnd)
+        args.rval().setNumber(js_NaN);
+    else
+        args.rval().setNumber(negative ? -number : number);
     return true;
 }
 
 static JSFunctionSpec number_functions[] = {
     JS_FN(js_isNaN_str,         num_isNaN,           1,0),
     JS_FN(js_isFinite_str,      num_isFinite,        1,0),
     JS_FN(js_parseFloat_str,    num_parseFloat,      1,0),
     JS_FN(js_parseInt_str,      num_parseInt,        2,0),
--- a/js/src/tests/ecma/GlobalObject/15.1.2.2-1.js
+++ b/js/src/tests/ecma/GlobalObject/15.1.2.2-1.js
@@ -145,121 +145,121 @@ new TestCase( SECTION,
 	      parseInt( "0xabcdef") );
 
 new TestCase( SECTION,
 	      "parseInt( 0XABCDEF )",
 	      11259375,
 	      parseInt( "0XABCDEF") );
 
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+")",    HEX_VALUE,  parseInt(HEX_STRING) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"')",    HEX_VALUE,  parseInt(HEX_STRING) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "0X0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+")",    HEX_VALUE,  parseInt(HEX_STRING) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"')",    HEX_VALUE,  parseInt(HEX_STRING) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+",16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"', 16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+",16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"', 16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+",null)",    HEX_VALUE,  parseInt(HEX_STRING,null) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"', null)",    HEX_VALUE,  parseInt(HEX_STRING,null) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+", void 0)",    HEX_VALUE,  parseInt(HEX_STRING, void 0) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"', void 0)",    HEX_VALUE,  parseInt(HEX_STRING, void 0) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 
 // a few tests with spaces
 
 for ( var space = " ", HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0;
       POWER < 15;
       POWER++, HEX_STRING = HEX_STRING +"f", space += " ")
 {
-  new TestCase( SECTION, "parseInt("+space+HEX_STRING+space+", void 0)",    HEX_VALUE,  parseInt(space+HEX_STRING+space, void 0) );
+  new TestCase( SECTION, "parseInt('"+space+HEX_STRING+space+"', void 0)",    HEX_VALUE,  parseInt(space+HEX_STRING+space, void 0) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 
 new TestCase(SECTION, "parseInt(BOM + '123', 10)", 123, parseInt("\uFEFF" + "123", 10));
 
 // a few tests with negative numbers
 for ( HEX_STRING = "-0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+")",    HEX_VALUE,  parseInt(HEX_STRING) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"')",    HEX_VALUE,  parseInt(HEX_STRING) );
   HEX_VALUE -= Math.pow(16,POWER)*15;
 }
 
 // we should stop parsing when we get to a value that is not a numeric literal for the type we expect
 
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+"g,16)",    HEX_VALUE,  parseInt(HEX_STRING+"g",16) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"g', 16)",    HEX_VALUE,  parseInt(HEX_STRING+"g",16) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+"g,16)",    HEX_VALUE,  parseInt(HEX_STRING+"G",16) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"G', 16)",    HEX_VALUE,  parseInt(HEX_STRING+"G",16) );
   HEX_VALUE += Math.pow(16,POWER)*15;
 }
 
 for ( HEX_STRING = "-0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+")",    HEX_VALUE,  parseInt(HEX_STRING) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"')",    HEX_VALUE,  parseInt(HEX_STRING) );
   HEX_VALUE -= Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "-0X0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+")",    HEX_VALUE,  parseInt(HEX_STRING) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"')",    HEX_VALUE,  parseInt(HEX_STRING) );
   HEX_VALUE -= Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "-0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+",16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"', 16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
   HEX_VALUE -= Math.pow(16,POWER)*15;
 }
 for ( HEX_STRING = "-0x0", HEX_VALUE = 0, POWER = 0; POWER < 15; POWER++, HEX_STRING = HEX_STRING +"f" ) {
-  new TestCase( SECTION, "parseInt("+HEX_STRING+",16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
+  new TestCase( SECTION, "parseInt('"+HEX_STRING+"', 16)",    HEX_VALUE,  parseInt(HEX_STRING,16) );
   HEX_VALUE -= Math.pow(16,POWER)*15;
 }
 
-//  let us do some octal tests.  numbers that start with 0 and do not provid a radix should
-//  default to using "0" as a radix.
+// Numbers that start with 0 and do not provide a radix should use 10 as radix
+// per ES5, not octal (as it was in ES3).
 
 var OCT_STRING = "0";
 var OCT_VALUE = 0;
 
 for ( OCT_STRING = "0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
-  new TestCase( SECTION, "parseInt("+OCT_STRING+")",    OCT_VALUE,  parseInt(OCT_STRING) );
-  OCT_VALUE += Math.pow(8,POWER)*7;
+  new TestCase( SECTION, "parseInt('"+OCT_STRING+"')",    OCT_VALUE,  parseInt(OCT_STRING) );
+  OCT_VALUE += Math.pow(10,POWER)*7;
 }
 
 for ( OCT_STRING = "-0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
-  new TestCase( SECTION, "parseInt("+OCT_STRING+")",    OCT_VALUE,  parseInt(OCT_STRING) );
-  OCT_VALUE -= Math.pow(8,POWER)*7;
+  new TestCase( SECTION, "parseInt('"+OCT_STRING+"')",    OCT_VALUE,  parseInt(OCT_STRING) );
+  OCT_VALUE -= Math.pow(10,POWER)*7;
 }
 
-// should get the same results as above if we provid the radix of 8 (or 010)
+// should get octal-based results if we provid the radix of 8 (or 010)
 
 for ( OCT_STRING = "0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
-  new TestCase( SECTION, "parseInt("+OCT_STRING+",8)",    OCT_VALUE,  parseInt(OCT_STRING,8) );
+  new TestCase( SECTION, "parseInt('"+OCT_STRING+"', 8)",    OCT_VALUE,  parseInt(OCT_STRING,8) );
   OCT_VALUE += Math.pow(8,POWER)*7;
 }
 for ( OCT_STRING = "-0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
-  new TestCase( SECTION, "parseInt("+OCT_STRING+",010)",    OCT_VALUE,  parseInt(OCT_STRING,010) );
+  new TestCase( SECTION, "parseInt('"+OCT_STRING+"', 010)",    OCT_VALUE,  parseInt(OCT_STRING,010) );
   OCT_VALUE -= Math.pow(8,POWER)*7;
 }
 
 // we shall stop parsing digits when we get one that isn't a numeric literal of the type we think
 // it should be.
 for ( OCT_STRING = "0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
-  new TestCase( SECTION, "parseInt("+OCT_STRING+"8,8)",    OCT_VALUE,  parseInt(OCT_STRING+"8",8) );
+  new TestCase( SECTION, "parseInt('"+OCT_STRING+"8', 8)",    OCT_VALUE,  parseInt(OCT_STRING+"8",8) );
   OCT_VALUE += Math.pow(8,POWER)*7;
 }
 for ( OCT_STRING = "-0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
-  new TestCase( SECTION, "parseInt("+OCT_STRING+"8,010)",    OCT_VALUE,  parseInt(OCT_STRING+"8",010) );
+  new TestCase( SECTION, "parseInt('"+OCT_STRING+"8', 010)",    OCT_VALUE,  parseInt(OCT_STRING+"8",010) );
   OCT_VALUE -= Math.pow(8,POWER)*7;
 }
 
 new TestCase( SECTION,
 	      "parseInt( '0x' )",             
 	      NaN,       
 	      parseInt("0x") );
 
@@ -290,18 +290,18 @@ new TestCase( SECTION,
 
 new TestCase( SECTION,
 	      "parseInt( '01234567890', -1 )", 
 	      Number.NaN,   
 	      parseInt("01234567890",-1) );
 
 new TestCase( SECTION,
 	      "parseInt( '01234567890', 0 )", 
-	      Number.NaN,    
-	      parseInt("01234567890",1) );
+	      1234567890,
+	      parseInt("01234567890", 0) );
 
 new TestCase( SECTION,
 	      "parseInt( '01234567890', 1 )", 
 	      Number.NaN,    
 	      parseInt("01234567890",1) );
 
 new TestCase( SECTION,
 	      "parseInt( '01234567890', 2 )", 
@@ -340,17 +340,17 @@ new TestCase( SECTION,
 
 new TestCase( SECTION,
 	      "parseInt( '01234567890', 9 )", 
 	      6053444,       
 	      parseInt("01234567890",9) );
 
 new TestCase( SECTION,
 	      "parseInt( '01234567890', 10 )",
-	      1234567890,    
+	      1234567890,
 	      parseInt("01234567890",10) );
 
 // need more test cases with hex radix
 
 new TestCase( SECTION,
 	      "parseInt( '1234567890', '0xa')",
 	      1234567890,
 	      parseInt("1234567890","0xa") );
--- a/js/src/tests/ecma/GlobalObject/15.1.2.2-2.js
+++ b/js/src/tests/ecma/GlobalObject/15.1.2.2-2.js
@@ -117,23 +117,28 @@ new TestCase( SECTION,
 
 new TestCase( SECTION,
 	      'parseInt("0x10",10)',
 	      0,
 	      parseInt("0x10",10));
 
 new TestCase( SECTION,
 	      'parseInt("0022")',
-	      18,
+	      22,
 	      parseInt("0022"));
 
 new TestCase( SECTION,
-	      'parseInt("0022",10)',
+	      'parseInt("0022", 8)',
+	      18,
+	      parseInt("0022", 8));
+
+new TestCase( SECTION,
+	      'parseInt("0022", 10)',
 	      22,
-	      parseInt("0022",10) );
+	      parseInt("0022", 10) );
 
 new TestCase( SECTION,
 	      'parseInt("0x1000000000000080")',
 	      1152921504606847000,
 	      parseInt("0x1000000000000080") );
 
 new TestCase( SECTION,
 	      'parseInt("0x1000000000000081")',
--- a/js/src/tests/ecma/TypeConversion/9.3.1-3.js
+++ b/js/src/tests/ecma/TypeConversion/9.3.1-3.js
@@ -469,18 +469,23 @@ new TestCase( SECTION,
 
 new TestCase( SECTION,
 	      "parseInt(\"0x10\",10)",
 	      0,
 	      parseInt("0x10",10) );
 
 new TestCase( SECTION,
 	      "parseInt(\"0022\")",
+	      22,
+	      parseInt("0022") );
+
+new TestCase( SECTION,
+	      "parseInt(\"0022\", 8)",
 	      18,
-	      parseInt("0022") );
+	      parseInt("0022", 8) );
 
 new TestCase( SECTION,
 	      "parseInt(\"0022\",10)",
 	      22,
 	      parseInt("0022",10) );
 
 new TestCase( SECTION,
 	      "parseInt(\"0x1000000000000080\")",
rename from js/src/tests/js1_8_5/extensions/parseInt-octal.js
rename to js/src/tests/ecma_5/Global/parseInt-default-to-decimal.js
--- a/js/src/tests/js1_8_5/extensions/parseInt-octal.js
+++ b/js/src/tests/ecma_5/Global/parseInt-default-to-decimal.js
@@ -1,30 +1,31 @@
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 583925;
 var summary =
-  "parseInt should treat leading-zero inputs as octal regardless of whether caller is strict or laissez-faire mode code";
+  "parseInt should treat leading-zero inputs (with radix unspecified) as " +
+  "decimal, not octal (this changed in bug 786135)";
 
 print(BUGNUMBER + ": " + summary);
 
 /**************
  * BEGIN TEST *
  **************/
 
-assertEq(parseInt("08"), 0);
-assertEq(parseInt("09"), 0);
-assertEq(parseInt("014"), 12);
+assertEq(parseInt("08"), 8);
+assertEq(parseInt("09"), 9);
+assertEq(parseInt("014"), 14);
 
 function strictParseInt(s) { "use strict"; return parseInt(s); }
 
-assertEq(strictParseInt("08"), 0);
-assertEq(strictParseInt("09"), 0);
-assertEq(strictParseInt("014"), 12);
+assertEq(strictParseInt("08"), 8);
+assertEq(strictParseInt("09"), 9);
+assertEq(strictParseInt("014"), 14);
 
 /******************************************************************************/
 
 if (typeof reportCompare === "function")
   reportCompare(true, true);
 
 print("All tests passed!");
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -468,17 +468,17 @@ function check_bookmarks_html() {
  */
 function create_JSON_backup(aFilename) {
   if (!aFilename)
     do_throw("you must pass a filename to create_JSON_backup function");
   remove_all_JSON_backups();
   let bookmarksBackupDir = gProfD.clone();
   bookmarksBackupDir.append("bookmarkbackups");
   if (!bookmarksBackupDir.exists()) {
-    bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755"));
+    bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
     do_check_true(bookmarksBackupDir.exists());
   }
   let bookmarksJSONFile = gTestDir.clone();
   bookmarksJSONFile.append(aFilename);
   do_check_true(bookmarksJSONFile.exists());
   bookmarksJSONFile.copyTo(bookmarksBackupDir, FILENAME_BOOKMARKS_JSON);
   let profileBookmarksJSONFile = bookmarksBackupDir.clone();
   profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON);