Fix error handling in Date.prototype.toISOString.
This fixes Date.prototyoe.toISOString to throw a RangeError exception for invalid time values. It also includes a fix to removes the arbitrary (and completely bogus) range limit on the date value during construction of a Date object. Note that we still have bogus range limits on the year and month values. R=lrn@chromium.org BUG=v8:1792 TEST=mjsunit/date,test262/15.9.5.43-0-* Review URL: http://codereview.chromium.org/8392036 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9829 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f077a41b12
commit
cd9bc6c3a6
10
src/date.js
10
src/date.js
@ -351,13 +351,12 @@ function MakeDay(year, month, date) {
|
||||
date = TO_INTEGER_MAP_MINUS_ZERO(date);
|
||||
|
||||
if (year < kMinYear || year > kMaxYear ||
|
||||
month < kMinMonth || month > kMaxMonth ||
|
||||
date < kMinDate || date > kMaxDate) {
|
||||
month < kMinMonth || month > kMaxMonth) {
|
||||
return $NaN;
|
||||
}
|
||||
|
||||
// Now we rely on year, month and date being SMIs.
|
||||
return %DateMakeDay(year, month, date);
|
||||
// Now we rely on year and month being SMIs.
|
||||
return %DateMakeDay(year, month) + date - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -978,9 +977,10 @@ function PadInt(n, digits) {
|
||||
}
|
||||
|
||||
|
||||
// ECMA 262 - 15.9.5.43
|
||||
function DateToISOString() {
|
||||
var t = DATE_VALUE(this);
|
||||
if (NUMBER_IS_NAN(t)) return kInvalidDate;
|
||||
if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []);
|
||||
var year = this.getUTCFullYear();
|
||||
var year_string;
|
||||
if (year >= 0 && year <= 9999) {
|
||||
|
@ -82,8 +82,6 @@ const kMinYear = -1000000;
|
||||
const kMaxYear = 1000000;
|
||||
const kMinMonth = -10000000;
|
||||
const kMaxMonth = 10000000;
|
||||
const kMinDate = -100000000;
|
||||
const kMaxDate = 100000000;
|
||||
|
||||
# Native cache ids.
|
||||
const STRING_TO_REGEXP_CACHE_ID = 0;
|
||||
|
@ -198,6 +198,7 @@ function FormatMessage(message) {
|
||||
// RangeError
|
||||
"invalid_array_length", ["Invalid array length"],
|
||||
"stack_overflow", ["Maximum call stack size exceeded"],
|
||||
"invalid_time_value", ["Invalid time value"],
|
||||
// SyntaxError
|
||||
"unable_to_parse", ["Parse error"],
|
||||
"invalid_regexp_flags", ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
|
||||
|
@ -7490,7 +7490,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
|
||||
}
|
||||
|
||||
|
||||
static int MakeDay(int year, int month, int day) {
|
||||
static int MakeDay(int year, int month) {
|
||||
static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
|
||||
181, 212, 243, 273, 304, 334};
|
||||
static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
|
||||
@ -7527,23 +7527,22 @@ static int MakeDay(int year, int month, int day) {
|
||||
year1 / 400 -
|
||||
base_day;
|
||||
|
||||
if (year % 4 || (year % 100 == 0 && year % 400 != 0)) {
|
||||
return day_from_year + day_from_month[month] + day - 1;
|
||||
if ((year % 4 != 0) || (year % 100 == 0 && year % 400 != 0)) {
|
||||
return day_from_year + day_from_month[month];
|
||||
}
|
||||
|
||||
return day_from_year + day_from_month_leap[month] + day - 1;
|
||||
return day_from_year + day_from_month_leap[month];
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 3);
|
||||
ASSERT(args.length() == 2);
|
||||
|
||||
CONVERT_SMI_ARG_CHECKED(year, 0);
|
||||
CONVERT_SMI_ARG_CHECKED(month, 1);
|
||||
CONVERT_SMI_ARG_CHECKED(date, 2);
|
||||
|
||||
return Smi::FromInt(MakeDay(year, month, date));
|
||||
return Smi::FromInt(MakeDay(year, month));
|
||||
}
|
||||
|
||||
|
||||
@ -7772,7 +7771,7 @@ static inline void DateYMDFromTimeAfter1970(int date,
|
||||
month = kMonthInYear[date];
|
||||
day = kDayInYear[date];
|
||||
|
||||
ASSERT(MakeDay(year, month, day) == save_date);
|
||||
ASSERT(MakeDay(year, month) + day - 1 == save_date);
|
||||
}
|
||||
|
||||
|
||||
@ -7786,7 +7785,7 @@ static inline void DateYMDFromTimeSlow(int date,
|
||||
year = 400 * (date / kDaysIn400Years) - kYearsOffset;
|
||||
date %= kDaysIn400Years;
|
||||
|
||||
ASSERT(MakeDay(year, 0, 1) + date == save_date);
|
||||
ASSERT(MakeDay(year, 0) + date == save_date);
|
||||
|
||||
date--;
|
||||
int yd1 = date / kDaysIn100Years;
|
||||
@ -7809,8 +7808,8 @@ static inline void DateYMDFromTimeSlow(int date,
|
||||
ASSERT(is_leap || (date >= 0));
|
||||
ASSERT((date < 365) || (is_leap && (date < 366)));
|
||||
ASSERT(is_leap == ((year % 4 == 0) && (year % 100 || (year % 400 == 0))));
|
||||
ASSERT(is_leap || ((MakeDay(year, 0, 1) + date) == save_date));
|
||||
ASSERT(!is_leap || ((MakeDay(year, 0, 1) + date + 1) == save_date));
|
||||
ASSERT(is_leap || ((MakeDay(year, 0) + date) == save_date));
|
||||
ASSERT(!is_leap || ((MakeDay(year, 0) + date + 1) == save_date));
|
||||
|
||||
if (is_leap) {
|
||||
day = kDayInYear[2*365 + 1 + date];
|
||||
@ -7820,7 +7819,7 @@ static inline void DateYMDFromTimeSlow(int date,
|
||||
month = kMonthInYear[date];
|
||||
}
|
||||
|
||||
ASSERT(MakeDay(year, month, day) == save_date);
|
||||
ASSERT(MakeDay(year, month) + day - 1 == save_date);
|
||||
}
|
||||
|
||||
|
||||
|
@ -246,7 +246,7 @@ namespace internal {
|
||||
F(DateLocalTimezone, 1, 1) \
|
||||
F(DateLocalTimeOffset, 0, 1) \
|
||||
F(DateDaylightSavingsOffset, 1, 1) \
|
||||
F(DateMakeDay, 3, 1) \
|
||||
F(DateMakeDay, 2, 1) \
|
||||
F(DateYMDFromTime, 2, 1) \
|
||||
\
|
||||
/* Numbers */ \
|
||||
|
@ -157,7 +157,7 @@ testToLocaleTimeString();
|
||||
// Test that -0 is treated correctly in MakeDay.
|
||||
var d = new Date();
|
||||
assertDoesNotThrow("d.setDate(-0)");
|
||||
assertDoesNotThrow("new Date(-0, -0, -0, -0, -0, -0. -0)");
|
||||
assertDoesNotThrow("new Date(-0, -0, -0, -0, -0, -0, -0)");
|
||||
assertDoesNotThrow("new Date(0x40000000, 0x40000000, 0x40000000," +
|
||||
"0x40000000, 0x40000000, 0x40000000, 0x40000000)")
|
||||
assertDoesNotThrow("new Date(-0x40000001, -0x40000001, -0x40000001," +
|
||||
@ -178,7 +178,7 @@ assertTrue(isNaN(Date.UTC(-271821, 3, 19, 23, 59, 59, 999)));
|
||||
assertTrue(isNaN(Date.UTC(-271821, 3, 19)));
|
||||
|
||||
|
||||
// Test creation of large date values.
|
||||
// Test creation with large date values.
|
||||
d = new Date(1969, 12, 1, 99999999999);
|
||||
assertTrue(isNaN(d.getTime()));
|
||||
d = new Date(1969, 12, 1, -99999999999);
|
||||
@ -188,6 +188,17 @@ assertTrue(isNaN(d.getTime()));
|
||||
d = new Date(1969, 12, 1, -Infinity);
|
||||
assertTrue(isNaN(d.getTime()));
|
||||
|
||||
|
||||
// Test creation with obscure date values.
|
||||
var timezoneOffset = new Date().getTimezoneOffset();
|
||||
d = new Date(1970, 0, 1 + 100000001, -24, -timezoneOffset);
|
||||
assertFalse(isNaN(d.getTime()));
|
||||
assertEquals(8640000000000000, d.getTime())
|
||||
d = new Date(1970, 0, 1 - 100000001, 24, -timezoneOffset);
|
||||
assertFalse(isNaN(d.getTime()));
|
||||
assertEquals(-8640000000000000, d.getTime())
|
||||
|
||||
|
||||
// Parsing ES5 ISO-8601 dates.
|
||||
// When TZ is omitted, it defaults to 'Z' meaning UTC.
|
||||
|
||||
|
@ -131,12 +131,6 @@ S15.3_A3_T3: FAIL
|
||||
|
||||
##################### DELIBERATE INCOMPATIBILITIES #####################
|
||||
|
||||
# 15.9.5.43-0-9 and 15.9.5.43-0-10. V8 doesn't throw RangeError
|
||||
# from Date.prototype.toISOString when string is not a finite number.
|
||||
# This is compatible with Firefox and Safari.
|
||||
15.9.5.43-0-9: PASS || FAIL
|
||||
15.9.5.43-0-10: PASS || FAIL
|
||||
|
||||
# We deliberately treat arguments to parseInt() with a leading zero as
|
||||
# octal numbers in order to not break the web.
|
||||
S15.1.2.2_A5.1_T1: FAIL_OK
|
||||
@ -478,24 +472,6 @@ S15.4.4.3_A2_T1: FAIL_OK
|
||||
# Bug? Array.prototype.reduceRight - decreasing length of array does not delete
|
||||
# non-configurable properties
|
||||
15.4.4.22-9-b-29: FAIL
|
||||
# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is
|
||||
# Date(1970, 0, -99999999, 0, 0, 0, -1), the time zone is UTC(0)
|
||||
15.9.5.43-0-8: FAIL
|
||||
# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date
|
||||
# is Date(1970, 0, 100000001, 0, 0, 0, -1), the time zone is UTC(0)
|
||||
15.9.5.43-0-11: FAIL
|
||||
# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date
|
||||
# is Date(1970, 0, 100000001, 0, 0, 0, 0), the time zone is UTC(0)
|
||||
15.9.5.43-0-12: FAIL
|
||||
# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is
|
||||
# Date(1970, 0, 100000001, 0, 0, 0, 1), the time zone is UTC(0)
|
||||
15.9.5.43-0-13: FAIL
|
||||
# Bug? Date.prototype.toISOString - when value of year is -Infinity
|
||||
# Date.prototype.toISOString throw the RangeError
|
||||
15.9.5.43-0-14: FAIL
|
||||
# Bug? Date.prototype.toISOString - value of year is Infinity
|
||||
# Date.prototype.toISOString throw the RangeError
|
||||
15.9.5.43-0-15: FAIL
|
||||
|
||||
############################ SKIPPED TESTS #############################
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user