1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:07:44 +00:00

LibJS: Don't accept UTC designators in strings for plain Temporal types

This is a normative change in the Temporal spec.

See: cd2dc7d
This commit is contained in:
Linus Groh 2021-11-24 08:56:03 +00:00
parent 836ce8ee5d
commit 78724fdd33
6 changed files with 87 additions and 16 deletions

View file

@ -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") \

View file

@ -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) };
}

View file

@ -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"
);
});
});

View file

@ -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"
);
});
});

View file

@ -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"
);
});
});

View file

@ -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"
);
});
});