LibJS: Differentiate between failed ISO8601 parsing and invalid values

If we were able to parse an ISO8601 Date string, but the parse results
in an invalid date (e.g. out of the min/max range), we should abort
parsing immediately.
This commit is contained in:
Timothy Flynn 2024-11-26 11:05:57 -05:00 committed by Tim Flynn
commit fc6155cf2c
Notes: github-actions[bot] 2024-11-26 21:57:31 +00:00
2 changed files with 11 additions and 7 deletions

View file

@ -25,7 +25,7 @@ namespace JS {
GC_DEFINE_ALLOCATOR(DateConstructor);
// 21.4.3.2 Date.parse ( string ), https://tc39.es/ecma262/#sec-date.parse
static double parse_simplified_iso8601(ByteString const& iso_8601)
static Optional<double> parse_simplified_iso8601(ByteString const& iso_8601)
{
// 21.4.1.15 Date Time String Format, https://tc39.es/ecma262/#sec-date-time-string-format
GenericLexer lexer(iso_8601);
@ -127,9 +127,8 @@ static double parse_simplified_iso8601(ByteString const& iso_8601)
};
auto lex_time = [&]() { return lex_hours_minutes(hours, minutes) && (!lexer.consume_specific(':') || lex_seconds_milliseconds()) && lex_timezone(); };
if (!lex_date() || (lexer.consume_specific('T') && !lex_time()) || !lexer.is_eof()) {
return NAN;
}
if (!lex_date() || (lexer.consume_specific('T') && !lex_time()) || !lexer.is_eof())
return {};
// We parsed a valid date simplified ISO 8601 string.
VERIFY(year.has_value()); // A valid date string always has at least a year.
@ -154,9 +153,8 @@ static double parse_date_string(VM& vm, ByteString const& date_string)
if (date_string.is_empty())
return NAN;
auto value = parse_simplified_iso8601(date_string);
if (isfinite(value))
return value;
if (auto time = parse_simplified_iso8601(date_string); time.has_value())
return *time;
// Date.parse() is allowed to accept an arbitrary number of implementation-defined formats.
// FIXME: Exactly what timezone and which additional formats we should support is unclear.

View file

@ -67,6 +67,12 @@ test("basic functionality", () => {
test("time clip", () => {
expect(Date.parse("+999999")).toBeNaN();
expect(Date.parse("-999999")).toBeNaN();
const belowMinDate = "-271821-04-19T23:59:59.999Z";
expect(belowMinDate).toBeNaN();
const aboveMaxDate = "+275760-09-13T00:00:00.001Z";
expect(aboveMaxDate).toBeNaN();
});
test("extra micro seconds extension", () => {