diff options
author | Linus Groh <mail@linusgroh.de> | 2021-11-24 08:56:03 +0000 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-11-24 08:56:03 +0000 |
commit | 78724fdd33dad520da7570a8189104edb22d752b (patch) | |
tree | dbb55f65ca40bfdb5abf835b4aa0bc4684f32edb | |
parent | 836ce8ee5d3e301d939430507141728eeca7eb18 (diff) | |
download | serenity-78724fdd33dad520da7570a8189104edb22d752b.zip |
LibJS: Don't accept UTC designators in strings for plain Temporal types
This is a normative change in the Temporal spec.
See: https://github.com/tc39/proposal-temporal/commit/cd2dc7d
6 files changed, 87 insertions, 16 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index 1fd4a9c879..1c17951d01 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -209,7 +209,9 @@ M(TemporalInvalidCalendarIdentifier, "Invalid calendar identifier '{}'") \ M(TemporalInvalidCalendarString, "Invalid calendar string '{}'") \ M(TemporalInvalidDateString, "Invalid date string '{}'") \ + M(TemporalInvalidDateStringUTCDesignator, "Invalid date string '{}': must not contain a UTC designator") \ M(TemporalInvalidDateTimeString, "Invalid date time string '{}'") \ + M(TemporalInvalidDateTimeStringUTCDesignator, "Invalid date time string '{}': must not contain a UTC designator") \ M(TemporalInvalidDuration, "Invalid duration") \ M(TemporalInvalidDurationLikeObject, "Invalid duration-like object") \ M(TemporalInvalidDurationPropertyValueNonIntegral, "Invalid value for duration property '{}': must be an integer, got {}") \ @@ -219,6 +221,7 @@ M(TemporalInvalidISODate, "Invalid ISO date") \ M(TemporalInvalidMonthCode, "Invalid month code") \ M(TemporalInvalidMonthDayString, "Invalid month day string '{}'") \ + M(TemporalInvalidMonthDayStringUTCDesignator, "Invalid month day string '{}': must not contain a UTC designator") \ M(TemporalInvalidOffsetNanosecondsValue, "Invalid offset nanoseconds value, must be in range -86400 * 10^9 to 86400 * 10^9") \ M(TemporalInvalidPlainDate, "Invalid plain date") \ M(TemporalInvalidPlainDateTime, "Invalid plain date time") \ @@ -229,10 +232,12 @@ M(TemporalInvalidRelativeToString, "Invalid relative to string '{}'") \ M(TemporalInvalidTime, "Invalid time") \ M(TemporalInvalidTimeString, "Invalid time string '{}'") \ + M(TemporalInvalidTimeStringUTCDesignator, "Invalid time string '{}': must not contain a UTC designator") \ M(TemporalInvalidTimeZoneName, "Invalid time zone name") \ M(TemporalInvalidTimeZoneString, "Invalid time zone string '{}'") \ M(TemporalInvalidUnitRange, "Invalid unit range, {} is larger than {}") \ M(TemporalInvalidYearMonthString, "Invalid year month string '{}'") \ + M(TemporalInvalidYearMonthStringUTCDesignator, "Invalid year month string '{}': must not contain a UTC designator") \ M(TemporalInvalidZonedDateTimeOffset, "Invalid offset for the provided date and time in the current time zone") \ M(TemporalInvalidZonedDateTimeString, "Invalid zoned date time string '{}'") \ M(TemporalMissingOptionsObject, "Required options object is missing or undefined") \ diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp index fb05b4cded..eed71e054c 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp @@ -1272,10 +1272,16 @@ ThrowCompletionOr<TemporalDate> parse_temporal_date_string(GlobalObject& global_ return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDateString, iso_string); } - // 3. Let result be ? ParseISODateTime(isoString). + // 3. If isoString contains a UTCDesignator, then + if (parse_result->utc_designator.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDateStringUTCDesignator, iso_string); + } + + // 4. Let result be ? ParseISODateTime(isoString). auto result = TRY(parse_iso_date_time(global_object, *parse_result)); - // 4. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. + // 5. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. return TemporalDate { .year = result.year, .month = result.month, .day = result.day, .calendar = move(result.calendar) }; } @@ -1293,10 +1299,16 @@ ThrowCompletionOr<ISODateTime> parse_temporal_date_time_string(GlobalObject& glo return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDateTimeString, iso_string); } - // 3. Let result be ? ParseISODateTime(isoString). + // 3. If isoString contains a UTCDesignator, then + if (parse_result->utc_designator.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDateTimeStringUTCDesignator, iso_string); + } + + // 4. Let result be ? ParseISODateTime(isoString). auto result = TRY(parse_iso_date_time(global_object, *parse_result)); - // 4. Return result. + // 5. Return result. return result; } @@ -1322,19 +1334,25 @@ ThrowCompletionOr<TemporalMonthDay> parse_temporal_month_day_string(GlobalObject return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidMonthDayString, iso_string); } - // 3. Let result be ? ParseISODateTime(isoString). + // 3. If isoString contains a UTCDesignator, then + if (parse_result->utc_designator.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidMonthDayStringUTCDesignator, iso_string); + } + + // 4. Let result be ? ParseISODateTime(isoString). auto result = TRY(parse_iso_date_time(global_object, *parse_result)); - // 4. Let year be result.[[Year]]. + // 5. Let year be result.[[Year]]. Optional<i32> year = result.year; - // 5. If no part of isoString is produced by the DateYear production, then + // 6. If no part of isoString is produced by the DateYear production, then if (!parse_result->date_year.has_value()) { // a. Set year to undefined. year = {}; } - // 6. Return the Record { [[Year]]: year, [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. + // 7. Return the Record { [[Year]]: year, [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. return TemporalMonthDay { .year = year, .month = result.month, .day = result.day, .calendar = move(result.calendar) }; } @@ -1401,10 +1419,16 @@ ThrowCompletionOr<TemporalTime> parse_temporal_time_string(GlobalObject& global_ return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidTimeString, iso_string); } - // 3. Let result be ? ParseISODateTime(isoString). + // 3. If isoString contains a UTCDesignator, then + if (parse_result->utc_designator.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidTimeStringUTCDesignator, iso_string); + } + + // 4. Let result be ? ParseISODateTime(isoString). auto result = TRY(parse_iso_date_time(global_object, *parse_result)); - // 4. Return the Record { [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], [[Nanosecond]]: result.[[Nanosecond]], [[Calendar]]: result.[[Calendar]] }. + // 5. Return the Record { [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], [[Nanosecond]]: result.[[Nanosecond]], [[Calendar]]: result.[[Calendar]] }. return TemporalTime { .hour = result.hour, .minute = result.minute, .second = result.second, .millisecond = result.millisecond, .microsecond = result.microsecond, .nanosecond = result.nanosecond, .calendar = move(result.calendar) }; } @@ -1518,10 +1542,16 @@ ThrowCompletionOr<TemporalYearMonth> parse_temporal_year_month_string(GlobalObje return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidYearMonthString, iso_string); } - // 3. Let result be ? ParseISODateTime(isoString). + // 3. If isoString contains a UTCDesignator, then + if (parse_result->utc_designator.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidYearMonthStringUTCDesignator, iso_string); + } + + // 4. Let result be ? ParseISODateTime(isoString). auto result = TRY(parse_iso_date_time(global_object, *parse_result)); - // 4. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. + // 5. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. return TemporalYearMonth { .year = result.year, .month = result.month, .day = result.day, .calendar = move(result.calendar) }; } diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js index 5230c153a7..9cc4432aa7 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js @@ -96,7 +96,7 @@ describe("correct behavior", () => { }); test("PlainDateTime string argument", () => { - const plainDateTime = Temporal.PlainDateTime.from("2021-07-06T23:42:01Z"); + const plainDateTime = Temporal.PlainDateTime.from("2021-07-06T23:42:01"); expect(plainDateTime.year).toBe(2021); expect(plainDateTime.month).toBe(7); expect(plainDateTime.day).toBe(6); @@ -177,4 +177,13 @@ describe("errors", () => { Temporal.PlainDateTime.from(zonedDateTime); }).toThrowWithMessage(TypeError, "null is not a function"); }); + + test("string must not contain a UTC designator", () => { + expect(() => { + Temporal.PlainDateTime.from("2021-07-06T23:42:01Z"); + }).toThrowWithMessage( + RangeError, + "Invalid date time string '2021-07-06T23:42:01Z': must not contain a UTC designator" + ); + }); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js index 99f6ce55fb..78388845c3 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js @@ -42,7 +42,7 @@ describe("correct behavior", () => { }); test("from date time string", () => { - const plainMonthDay = Temporal.PlainMonthDay.from("2021-07-06T23:42:01Z"); + const plainMonthDay = Temporal.PlainMonthDay.from("2021-07-06T23:42:01"); expect(plainMonthDay.monthCode).toBe("M07"); expect(plainMonthDay.day).toBe(6); }); @@ -66,4 +66,13 @@ describe("errors", () => { Temporal.PlainMonthDay.from("foo"); }).toThrowWithMessage(RangeError, "Invalid month day string 'foo'"); }); + + test("string must not contain a UTC designator", () => { + expect(() => { + Temporal.PlainMonthDay.from("2021-07-06T23:42:01Z"); + }).toThrowWithMessage( + RangeError, + "Invalid month day string '2021-07-06T23:42:01Z': must not contain a UTC designator" + ); + }); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js index 7f3069c393..d549c5272b 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js @@ -38,7 +38,7 @@ describe("correct behavior", () => { }); test("PlainTime string argument", () => { - const createdPlainTime = Temporal.PlainTime.from("2021-08-27T18:44:11Z"); + const createdPlainTime = Temporal.PlainTime.from("2021-08-27T18:44:11"); expect(createdPlainTime.hour).toBe(18); expect(createdPlainTime.minute).toBe(44); expect(createdPlainTime.second).toBe(11); @@ -55,4 +55,13 @@ describe("errors", () => { Temporal.PlainTime.from(zonedDateTime); }).toThrowWithMessage(TypeError, "null is not a function"); }); + + test("string must not contain a UTC designator", () => { + expect(() => { + Temporal.PlainTime.from("2021-07-06T23:42:01Z"); + }).toThrowWithMessage( + RangeError, + "Invalid time string '2021-07-06T23:42:01Z': must not contain a UTC designator" + ); + }); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js index 0ba572a08b..78a1fbc031 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js @@ -63,7 +63,7 @@ describe("correct behavior", () => { }); test("from date time string", () => { - const plainYearMonth = Temporal.PlainYearMonth.from("2021-07-06T23:42:01Z"); + const plainYearMonth = Temporal.PlainYearMonth.from("2021-07-06T23:42:01"); expect(plainYearMonth.year).toBe(2021); expect(plainYearMonth.month).toBe(7); expect(plainYearMonth.monthCode).toBe("M07"); @@ -92,4 +92,13 @@ describe("errors", () => { Temporal.PlainYearMonth.from("foo"); }).toThrowWithMessage(RangeError, "Invalid year month string 'foo'"); }); + + test("string must not contain a UTC designator", () => { + expect(() => { + Temporal.PlainYearMonth.from("2021-07-06T23:42:01Z"); + }).toThrowWithMessage( + RangeError, + "Invalid year month string '2021-07-06T23:42:01Z': must not contain a UTC designator" + ); + }); }); |