Bug 786135 - Make parseInt(stringStartingWith0ButNot0xOr0X) parse as decimal to comply with ES5. r=dmandelin

--HG--
rename : js/src/tests/js1_8_5/extensions/parseInt-octal.js => js/src/tests/ecma_5/Global/parseInt-default-to-decimal.js
extra : rebase_source : 824fe7e00fbb6ffa38ebba5c43f6c0801f387309
This commit is contained in:
Jeff Walden 2013-01-28 13:08:32 -08:00
Родитель 3645333c96
Коммит 371def9626
8 изменённых файлов: 106 добавлений и 117 удалений

Просмотреть файл

@ -19,5 +19,5 @@ function doParseIntTests() {
}
doParseIntTests();
assertEq(parseInt("08"), 0);
assertEq(parseInt("09"), 0);
assertEq(parseInt("08"), 8);
assertEq(parseInt("09"), 9);

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -281,60 +281,7 @@ num_parseFloat(JSContext *cx, unsigned argc, Value *vp)
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)
{
@ -352,6 +299,7 @@ js::num_parseInt(JSContext *cx, unsigned argc, Value *vp)
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
@ -386,13 +334,17 @@ js::num_parseInt(JSContext *cx, unsigned argc, Value *vp)
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;
@ -402,18 +354,44 @@ js::num_parseInt(JSContext *cx, unsigned argc, Value *vp)
}
}
/* 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;
}

Просмотреть файл

@ -150,27 +150,27 @@ new TestCase( SECTION,
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;
}
@ -180,7 +180,7 @@ 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;
}
@ -188,73 +188,73 @@ new TestCase(SECTION, "parseInt(BOM + '123', 10)", 123, parseInt("\uFEFF" + "123
// 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;
}
@ -295,8 +295,8 @@ new TestCase( SECTION,
new TestCase( SECTION,
"parseInt( '01234567890', 0 )",
Number.NaN,
parseInt("01234567890",1) );
1234567890,
parseInt("01234567890", 0) );
new TestCase( SECTION,
"parseInt( '01234567890', 1 )",
@ -345,7 +345,7 @@ new TestCase( SECTION,
new TestCase( SECTION,
"parseInt( '01234567890', 10 )",
1234567890,
1234567890,
parseInt("01234567890",10) );
// need more test cases with hex radix

Просмотреть файл

@ -122,13 +122,18 @@ new TestCase( SECTION,
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")',

Просмотреть файл

@ -474,9 +474,14 @@ new TestCase( SECTION,
new TestCase( SECTION,
"parseInt(\"0022\")",
18,
22,
parseInt("0022") );
new TestCase( SECTION,
"parseInt(\"0022\", 8)",
18,
parseInt("0022", 8) );
new TestCase( SECTION,
"parseInt(\"0022\",10)",
22,

Просмотреть файл

@ -4,7 +4,8 @@
//-----------------------------------------------------------------------------
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);
@ -12,15 +13,15 @@ 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);
/******************************************************************************/

Просмотреть файл

@ -473,7 +473,7 @@ function create_JSON_backup(aFilename) {
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();