Commit c0a3ea6d authored by tkent@chromium.org's avatar tkent@chromium.org

2010-01-31 Kent Tamura <tkent@chromium.org>

        Reviewed by Darin Adler.

        Fix valueAsNumber calculation for type=month.
        https://bugs.webkit.org/show_bug.cgi?id=34304

        valueAsNumber calculation for type=month which was checked in as
        r53893 was the number of milliseconds since UNIX epoch, and it was
        wrong. The correct way is the number months since UNIX epoch.

        * fast/forms/input-valueasnumber-month-expected.txt:
        * fast/forms/script-tests/input-valueasnumber-month.js:

2010-01-31  Kent Tamura  <tkent@chromium.org>

        Reviewed by Darin Adler.

        Fix valueAsNumber calculation for type=month.
        https://bugs.webkit.org/show_bug.cgi?id=34304

        valueAsNumber calculation for type=month which was checked in as
        r53893 was the number of milliseconds since UNIX epoch, and it was
        wrong. The correct way is the number months since UNIX epoch.

        * html/DateComponents.cpp:
        (WebCore::DateComponents::setMonthsSinceEpoch):
        (WebCore::DateComponents::monthsSinceEpoch):
        * html/DateComponents.h: Declare setMonthsSinceEpoch() and monthsSinceEpoch().
        * html/HTMLInputElement.cpp:
        (WebCore::HTMLInputElement::parseToDouble):
          Switch to monthsSinceEpoch() for type=MONTH.
        (WebCore::HTMLInputElement::valueAsDate):
          Add code with millisecondsSinceEpoch() for MONTH because
          parseToDouble() changed its behavior.
        (WebCore::HTMLInputElement::setValueAsNumber):
          Use setMonthsSinceEpoch() for MONTH.

git-svn-id: svn://svn.chromium.org/blink/trunk@54120 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent b9c4b68e
2010-01-31 Kent Tamura <tkent@chromium.org>
Reviewed by Darin Adler.
Fix valueAsNumber calculation for type=month.
https://bugs.webkit.org/show_bug.cgi?id=34304
valueAsNumber calculation for type=month which was checked in as
r53893 was the number of milliseconds since UNIX epoch, and it was
wrong. The correct way is the number months since UNIX epoch.
* fast/forms/input-valueasnumber-month-expected.txt:
* fast/forms/script-tests/input-valueasnumber-month.js:
2010-01-28 Ojan Vafai <ojan@chromium.org> 2010-01-28 Ojan Vafai <ojan@chromium.org>
Reviewed by Darin Adler. Reviewed by Darin Adler.
......
...@@ -4,18 +4,22 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE ...@@ -4,18 +4,22 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS valueAsNumberFor("") is Number.NaN PASS valueAsNumberFor("") is Number.NaN
PASS valueAsNumberFor("1969-12") is Date.UTC(1969, 11, 1, 0, 0, 0, 0) PASS valueAsNumberFor("1969-01") is -12
PASS valueAsNumberFor("1970-01") is Date.UTC(1970, 0, 1) PASS valueAsNumberFor("1969-12") is -1
PASS valueAsNumberFor("2009-12") is Date.UTC(2009, 11, 1) PASS valueAsNumberFor("1970-01") is 0
PASS setValueAsNumberAndGetValue(1969, 11, 1) is "1969-12" PASS valueAsNumberFor("1970-12") is 11
PASS setValueAsNumberAndGetValue(1970, 0, 1) is "1970-01" PASS valueAsNumberFor("1971-01") is 12
PASS setValueAsNumberAndGetValue(2009, 11, 31) is "2009-12" PASS valueAsNumberFor("2009-12") is (2009-1970)*12+11
PASS setValueAsNumberAndGetValue(10000, 0, 1) is "10000-01" PASS input.valueAsNumber = -1; input.value is "1969-12"
PASS setValueAsNumberAndGetValue(794, 9, 22) is "" PASS input.valueAsNumber = 0; input.value is "1970-01"
PASS setValueAsNumberAndGetValue(1582, 8, 30) is "" PASS setValueAsNumberAndGetValue(2009, 12) is "2009-12"
PASS setValueAsNumberAndGetValue(1582, 9, 1) is "1582-10" PASS setValueAsNumberAndGetValue(10000, 1) is "10000-01"
PASS setValueAsNumberAndGetValue(1582, 9, 31) is "1582-10" PASS setValueAsNumberAndGetValue(794, 9) is ""
PASS setValueAsNumberAndGetValue(275760, 8, 13) is "275760-09" PASS setValueAsNumberAndGetValue(1582, 9) is ""
PASS setValueAsNumberAndGetValue(1582, 10) is "1582-10"
PASS setValueAsNumberAndGetValue(1582, 11) is "1582-11"
PASS setValueAsNumberAndGetValue(275760, 9) is "275760-09"
PASS setValueAsNumberAndGetValue(2147483647, 12) is "2147483647-12"
Tests to set invalid values to valueAsNumber: Tests to set invalid values to valueAsNumber:
PASS input.value = ""; input.valueAsNumber = null; input.value is "1970-01" PASS input.value = ""; input.valueAsNumber = null; input.value is "1970-01"
PASS input.valueAsNumber = "foo" threw exception Error: NOT_SUPPORTED_ERR: DOM Exception 9. PASS input.valueAsNumber = "foo" threw exception Error: NOT_SUPPORTED_ERR: DOM Exception 9.
......
...@@ -8,26 +8,31 @@ function valueAsNumberFor(stringValue) { ...@@ -8,26 +8,31 @@ function valueAsNumberFor(stringValue) {
return input.valueAsNumber; return input.valueAsNumber;
} }
function setValueAsNumberAndGetValue(year, month, day) { function setValueAsNumberAndGetValue(y, m) {
input.valueAsNumber = Date.UTC(year, month, day); input.valueAsNumber = (y - 1970) * 12 + m - 1;
return input.value; return input.value;
} }
shouldBe('valueAsNumberFor("")', 'Number.NaN'); shouldBe('valueAsNumberFor("")', 'Number.NaN');
shouldBe('valueAsNumberFor("1969-12")', 'Date.UTC(1969, 11, 1, 0, 0, 0, 0)'); shouldBe('valueAsNumberFor("1969-01")', '-12');
shouldBe('valueAsNumberFor("1970-01")', 'Date.UTC(1970, 0, 1)'); shouldBe('valueAsNumberFor("1969-12")', '-1');
shouldBe('valueAsNumberFor("2009-12")', 'Date.UTC(2009, 11, 1)'); shouldBe('valueAsNumberFor("1970-01")', '0');
shouldBe('valueAsNumberFor("1970-12")', '11');
shouldBe('setValueAsNumberAndGetValue(1969, 11, 1)', '"1969-12"'); shouldBe('valueAsNumberFor("1971-01")', '12');
shouldBe('setValueAsNumberAndGetValue(1970, 0, 1)', '"1970-01"'); shouldBe('valueAsNumberFor("2009-12")', '(2009-1970)*12+11');
shouldBe('setValueAsNumberAndGetValue(2009, 11, 31)', '"2009-12"');
shouldBe('setValueAsNumberAndGetValue(10000, 0, 1)', '"10000-01"'); shouldBe('input.valueAsNumber = -1; input.value', '"1969-12"');
shouldBe('input.valueAsNumber = 0; input.value', '"1970-01"');
shouldBe('setValueAsNumberAndGetValue(794, 9, 22)', '""'); shouldBe('setValueAsNumberAndGetValue(2009, 12)', '"2009-12"');
shouldBe('setValueAsNumberAndGetValue(1582, 8, 30)', '""'); shouldBe('setValueAsNumberAndGetValue(10000, 1)', '"10000-01"');
shouldBe('setValueAsNumberAndGetValue(1582, 9, 1)', '"1582-10"');
shouldBe('setValueAsNumberAndGetValue(1582, 9, 31)', '"1582-10"'); shouldBe('setValueAsNumberAndGetValue(794, 9)', '""');
shouldBe('setValueAsNumberAndGetValue(275760, 8, 13)', '"275760-09"'); shouldBe('setValueAsNumberAndGetValue(1582, 9)', '""');
shouldBe('setValueAsNumberAndGetValue(1582, 10)', '"1582-10"');
shouldBe('setValueAsNumberAndGetValue(1582, 11)', '"1582-11"');
shouldBe('setValueAsNumberAndGetValue(275760, 9)', '"275760-09"');
shouldBe('setValueAsNumberAndGetValue(2147483647, 12)', '"2147483647-12"');
// Date.UTC() of V8 throws an exception for the following value though JavaScriptCore doesn't. // Date.UTC() of V8 throws an exception for the following value though JavaScriptCore doesn't.
// shouldBe('setValueAsNumberAndGetValue(275760, 8, 14)', '"275760-09"'); // shouldBe('setValueAsNumberAndGetValue(275760, 8, 14)', '"275760-09"');
......
2010-01-31 Kent Tamura <tkent@chromium.org>
Reviewed by Darin Adler.
Fix valueAsNumber calculation for type=month.
https://bugs.webkit.org/show_bug.cgi?id=34304
valueAsNumber calculation for type=month which was checked in as
r53893 was the number of milliseconds since UNIX epoch, and it was
wrong. The correct way is the number months since UNIX epoch.
* html/DateComponents.cpp:
(WebCore::DateComponents::setMonthsSinceEpoch):
(WebCore::DateComponents::monthsSinceEpoch):
* html/DateComponents.h: Declare setMonthsSinceEpoch() and monthsSinceEpoch().
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::parseToDouble):
Switch to monthsSinceEpoch() for type=MONTH.
(WebCore::HTMLInputElement::valueAsDate):
Add code with millisecondsSinceEpoch() for MONTH because
parseToDouble() changed its behavior.
(WebCore::HTMLInputElement::setValueAsNumber):
Use setMonthsSinceEpoch() for MONTH.
2010-01-31 Dan Bernstein <mitz@apple.com> 2010-01-31 Dan Bernstein <mitz@apple.com>
Reviewed by Timothy Hatcher. Reviewed by Timothy Hatcher.
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <wtf/DateMath.h> #include <wtf/DateMath.h>
#include <wtf/MathExtras.h> #include <wtf/MathExtras.h>
using namespace std;
namespace WebCore { namespace WebCore {
// The oldest day of Gregorian Calendar is 1582-10-15. We don't support dates older than it. // The oldest day of Gregorian Calendar is 1582-10-15. We don't support dates older than it.
...@@ -537,6 +539,25 @@ bool DateComponents::setMillisecondsSinceMidnight(double ms) ...@@ -537,6 +539,25 @@ bool DateComponents::setMillisecondsSinceMidnight(double ms)
return true; return true;
} }
bool DateComponents::setMonthsSinceEpoch(double months)
{
if (!isfinite(months))
return false;
months = round(months);
double doubleMonth = positiveFmod(months, 12);
double doubleYear = 1970 + (months - doubleMonth) / 12;
if (doubleYear < gregorianStartYear || numeric_limits<int>::max() < doubleYear)
return false;
int year = static_cast<int>(doubleYear);
int month = static_cast<int>(doubleMonth);
if (beforeGregorianStartDate(year, month, gregorianStartDay))
return false;
m_year = year;
m_month = month;
m_type = Month;
return true;
}
// Offset from January 1st to Monday of the ISO 8601's first week. // Offset from January 1st to Monday of the ISO 8601's first week.
// ex. If January 1st is Friday, such Monday is 3 days later. Returns 3. // ex. If January 1st is Friday, such Monday is 3 days later. Returns 3.
static int offsetTo1stWeekStart(int year) static int offsetTo1stWeekStart(int year)
...@@ -605,6 +626,12 @@ double DateComponents::millisecondsSinceEpoch() const ...@@ -605,6 +626,12 @@ double DateComponents::millisecondsSinceEpoch() const
return invalidMilliseconds(); return invalidMilliseconds();
} }
double DateComponents::monthsSinceEpoch() const
{
ASSERT(m_type == Month);
return (m_year - 1970) * 12 + m_month;
}
String DateComponents::toStringForTime(SecondFormat format) const String DateComponents::toStringForTime(SecondFormat format) const
{ {
ASSERT(m_type == DateTime || m_type == DateTimeLocal || m_type == Time); ASSERT(m_type == DateTime || m_type == DateTimeLocal || m_type == Time);
......
...@@ -124,10 +124,16 @@ public: ...@@ -124,10 +124,16 @@ public:
// For Time type. Updates m_hour, m_minute, m_second and m_millisecond. // For Time type. Updates m_hour, m_minute, m_second and m_millisecond.
bool setMillisecondsSinceMidnight(double ms); bool setMillisecondsSinceMidnight(double ms);
// Another initializer for Month type. Updates m_year and m_month.
bool setMonthsSinceEpoch(double months);
// Returns the number of milliseconds from 1970-01-01 00:00:00 UTC. // Returns the number of milliseconds from 1970-01-01 00:00:00 UTC.
// For a DateComponents initialized with parseDateTimeLocal(), // For a DateComponents initialized with parseDateTimeLocal(),
// millisecondsSinceEpoch() returns a value for UTC timezone. // millisecondsSinceEpoch() returns a value for UTC timezone.
double millisecondsSinceEpoch() const; double millisecondsSinceEpoch() const;
// Returns the number of months from 1970-01.
// Do not call this for types other than Month.
double monthsSinceEpoch() const;
static inline double invalidMilliseconds() { return std::numeric_limits<double>::quiet_NaN(); } static inline double invalidMilliseconds() { return std::numeric_limits<double>::quiet_NaN(); }
private: private:
......
...@@ -1489,7 +1489,6 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c ...@@ -1489,7 +1489,6 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c
case DATE: case DATE:
case DATETIME: case DATETIME:
case DATETIMELOCAL: case DATETIMELOCAL:
case MONTH:
case TIME: case TIME:
case WEEK: { case WEEK: {
DateComponents date; DateComponents date;
...@@ -1499,6 +1498,14 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c ...@@ -1499,6 +1498,14 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c
ASSERT(isfinite(msec)); ASSERT(isfinite(msec));
return msec; return msec;
} }
case MONTH: {
DateComponents date;
if (!formStringToDateComponents(inputType(), src, &date))
return defaultValue;
double months = date.monthsSinceEpoch();
ASSERT(isfinite(months));
return months;
}
case NUMBER: case NUMBER:
case RANGE: { case RANGE: {
double numberValue; double numberValue;
...@@ -1535,10 +1542,17 @@ double HTMLInputElement::valueAsDate() const ...@@ -1535,10 +1542,17 @@ double HTMLInputElement::valueAsDate() const
switch (inputType()) { switch (inputType()) {
case DATE: case DATE:
case DATETIME: case DATETIME:
case MONTH:
case TIME: case TIME:
case WEEK: case WEEK:
return parseToDouble(value(), DateComponents::invalidMilliseconds()); return parseToDouble(value(), DateComponents::invalidMilliseconds());
case MONTH: {
DateComponents date;
if (!formStringToDateComponents(inputType(), value(), &date))
return DateComponents::invalidMilliseconds();
double msec = date.millisecondsSinceEpoch();
ASSERT(isfinite(msec));
return msec;
}
case BUTTON: case BUTTON:
case CHECKBOX: case CHECKBOX:
...@@ -1665,11 +1679,19 @@ void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec) ...@@ -1665,11 +1679,19 @@ void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
switch (inputType()) { switch (inputType()) {
case DATE: case DATE:
case DATETIME: case DATETIME:
case MONTH:
case TIME: case TIME:
case WEEK: case WEEK:
setValueAsDate(newValue, ec); setValueAsDate(newValue, ec);
return; return;
case MONTH: {
DateComponents date;
if (!date.setMonthsSinceEpoch(newValue)) {
setValue(String());
return;
}
setValue(date.toString());
return;
}
case DATETIMELOCAL: { case DATETIMELOCAL: {
DateComponents date; DateComponents date;
if (!date.setMillisecondsSinceEpochForDateTimeLocal(newValue)) { if (!date.setMillisecondsSinceEpochForDateTimeLocal(newValue)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment