From 52bfec37d4f7753c23f3b51f858659d14220f615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Thu, 3 Oct 2024 13:38:10 +0000 Subject: [PATCH] Bug 1920955 - Part 1: Ensure date-time separators are consistent. r=sfink Request for test262 coverage: https://github.com/tc39/test262/issues/4237 Differential Revision: https://phabricator.services.mozilla.com/D223506 --- js/public/friend/ErrorNumbers.msg | 2 ++ js/src/builtin/temporal/TemporalParser.cpp | 35 +++++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/js/public/friend/ErrorNumbers.msg b/js/public/friend/ErrorNumbers.msg index b388901ba4282..0000cbac00ccc 100644 --- a/js/public/friend/ErrorNumbers.msg +++ b/js/public/friend/ErrorNumbers.msg @@ -969,6 +969,8 @@ MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME, 0, JSEXN_RANG MSG_DEF(JSMSG_TEMPORAL_PARSER_MONTH_DAY_CALENDAR_NOT_ISO8601, 0, JSEXN_RANGEERR, "Month-Day formats only support the \"iso8601\" calendar") MSG_DEF(JSMSG_TEMPORAL_PARSER_YEAR_MONTH_CALENDAR_NOT_ISO8601, 0, JSEXN_RANGEERR, "Year-Month formats only support the \"iso8601\" calendar") MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE, 0, JSEXN_RANGEERR, "time zone offset must not contain seconds precision") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INCONSISTENT_DATE_SEPARATOR, 0, JSEXN_RANGEERR, "date separator '-' must be consistent") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR, 0, JSEXN_RANGEERR, "time separator ':' must be consistent") // Explicit Resource Management diff --git a/js/src/builtin/temporal/TemporalParser.cpp b/js/src/builtin/temporal/TemporalParser.cpp index 1dd301f9f3fe3..4ce358431b46c 100644 --- a/js/src/builtin/temporal/TemporalParser.cpp +++ b/js/src/builtin/temporal/TemporalParser.cpp @@ -986,7 +986,7 @@ mozilla::Result TemporalParser::date() { } // Optional: - - character('-'); + bool hasMonthSeparator = character('-'); // DateMonth ::: // 0 NonzeroDigit @@ -1003,7 +1003,12 @@ mozilla::Result TemporalParser::date() { } // Optional: - - character('-'); + bool hasDaySeparator = character('-'); + + // Date separators must be consistent. + if (hasMonthSeparator != hasDaySeparator) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INCONSISTENT_DATE_SEPARATOR); + } // DateDay ::: // 0 NonzeroDigit @@ -1053,7 +1058,7 @@ mozilla::Result TemporalParser::timeSpec() { } // Optional: : - bool needsMinutes = character(':'); + bool hasMinuteSeparator = character(':'); // TimeMinute ::: // MinuteSecond @@ -1072,7 +1077,7 @@ mozilla::Result TemporalParser::timeSpec() { } // Optional: : - bool needsSeconds = needsMinutes && character(':'); + bool hasSecondSeparator = character(':'); // TimeSecond ::: // MinuteSecond @@ -1083,6 +1088,11 @@ mozilla::Result TemporalParser::timeSpec() { return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND); } + // Time separators must be consistent. + if (hasMinuteSeparator != hasSecondSeparator) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR); + } + // TimeFraction ::: // Fraction if (auto f = fraction()) { @@ -1091,10 +1101,10 @@ mozilla::Result TemporalParser::timeSpec() { result.microsecond = (fractionalPart % 1'000'000) / 1'000; result.nanosecond = fractionalPart % 1'000; } - } else if (needsSeconds) { + } else if (hasSecondSeparator) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_SECOND); } - } else if (needsMinutes) { + } else if (hasMinuteSeparator) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE); } @@ -1231,7 +1241,7 @@ TemporalParser::utcOffsetSubMinutePrecision() { // TimeSeparator[Extended] ::: // [+Extended] : // [~Extended] [empty] - bool needsMinutes = character(':'); + bool hasMinuteSeparator = character(':'); // MinuteSecond ::: // 0 DecimalDigit @@ -1249,7 +1259,7 @@ TemporalParser::utcOffsetSubMinutePrecision() { // TimeSeparator[Extended] ::: // [+Extended] : // [~Extended] [empty] - bool needsSeconds = needsMinutes && character(':'); + bool hasSecondSeparator = character(':'); // MinuteSecond ::: // 0 DecimalDigit @@ -1264,15 +1274,20 @@ TemporalParser::utcOffsetSubMinutePrecision() { return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_SECOND); } + // Time separators must be consistent. + if (hasMinuteSeparator != hasSecondSeparator) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR); + } + if (auto fractionalPart = fraction()) { result.fractionalPart = fractionalPart.value(); } result.subMinutePrecision = true; - } else if (needsSeconds) { + } else if (hasSecondSeparator) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_SECOND); } - } else if (needsMinutes) { + } else if (hasMinuteSeparator) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE); }