LibJS: Use narrower types in Temporal PlainDate/PlainDateTime/Calendar

These are bounds-checked during construction of PlainDate/PlainDateTime
and as such theres no need to widen them in these internal AO calls.
This commit is contained in:
Idan Horowitz 2021-07-26 16:48:47 +03:00 committed by Linus Groh
parent c5c32ad274
commit 2c6bd3a61b
Notes: sideshowbarker 2024-07-18 08:18:57 +09:00
11 changed files with 47 additions and 49 deletions

View file

@ -577,9 +577,9 @@ Optional<TemporalTimeZone> parse_temporal_time_zone_string(GlobalObject& global_
VERIFY(sign_part.has_value());
// b. Set hours to ! ToIntegerOrInfinity(hours).
i32 hours = Value(js_string(vm, *hours_part)).to_integer_or_infinity(global_object);
u8 hours = Value(js_string(vm, *hours_part)).to_integer_or_infinity(global_object);
i32 sign;
u8 sign;
// c. If sign is the code unit 0x002D (HYPHEN-MINUS) or the code unit 0x2212 (MINUS SIGN), then
if (sign_part->is_one_of("-", "\u2212")) {
// i. Set sign to 1.
@ -592,10 +592,10 @@ Optional<TemporalTimeZone> parse_temporal_time_zone_string(GlobalObject& global_
}
// e. Set minutes to ! ToIntegerOrInfinity(minutes).
i32 minutes = Value(js_string(vm, minutes_part.value_or(""sv))).to_integer_or_infinity(global_object);
u8 minutes = Value(js_string(vm, minutes_part.value_or(""sv))).to_integer_or_infinity(global_object);
// f. Set seconds to ! ToIntegerOrInfinity(seconds).
i32 seconds = Value(js_string(vm, seconds_part.value_or(""sv))).to_integer_or_infinity(global_object);
u8 seconds = Value(js_string(vm, seconds_part.value_or(""sv))).to_integer_or_infinity(global_object);
i32 nanoseconds;
// g. If fraction is not undefined, then

View file

@ -33,25 +33,23 @@ struct ISODateTime {
Optional<String> calendar = {};
};
// FIXME: Use more narrow types for most of these (u8/u16)
struct TemporalInstant {
i32 year;
i32 month;
i32 day;
i32 hour;
i32 minute;
i32 second;
i32 millisecond;
i32 microsecond;
i32 nanosecond;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u16 millisecond;
u16 microsecond;
u16 nanosecond;
Optional<String> time_zone_offset;
};
// FIXME: Use more narrow type for month/day (u8)
struct TemporalDate {
i32 year;
i32 month;
i32 day;
u8 month;
u8 day;
Optional<String> calendar;
};

View file

@ -460,7 +460,7 @@ u16 iso_days_in_year(i32 year)
}
// 12.1.32 ISODaysInMonth ( year, month ), https://tc39.es/proposal-temporal/#sec-temporal-isodaysinmonth
i32 iso_days_in_month(i32 year, i32 month)
u8 iso_days_in_month(i32 year, u8 month)
{
// 1. Assert: year is an integer.
@ -547,7 +547,7 @@ u8 to_iso_week_of_year(i32 year, u8 month, u8 day)
}
// 12.1.36 BuildISOMonthCode ( month ), https://tc39.es/proposal-temporal/#sec-buildisomonthcode
String build_iso_month_code(i32 month)
String build_iso_month_code(u8 month)
{
return String::formatted("M{:02}", month);
}

View file

@ -53,11 +53,11 @@ PlainDate* date_from_fields(GlobalObject&, Object& calendar, Object& fields, Obj
bool calendar_equals(GlobalObject&, Object& one, Object& two);
bool is_iso_leap_year(i32 year);
u16 iso_days_in_year(i32 year);
i32 iso_days_in_month(i32 year, i32 month);
u8 iso_days_in_month(i32 year, u8 month);
u8 to_iso_day_of_week(i32 year, u8 month, u8 day);
u16 to_iso_day_of_year(i32 year, u8 month, u8 day);
u8 to_iso_week_of_year(i32 year, u8 month, u8 day);
String build_iso_month_code(i32 month);
String build_iso_month_code(u8 month);
double resolve_iso_month(GlobalObject&, Object& fields);
Optional<TemporalDate> iso_date_from_fields(GlobalObject&, Object& fields, Object& options);
i32 iso_year(Object& temporal_object);

View file

@ -14,7 +14,7 @@
namespace JS::Temporal {
// 3 Temporal.PlainDate Objects, https://tc39.es/proposal-temporal/#sec-temporal-plaindate-objects
PlainDate::PlainDate(i32 year, i32 month, i32 day, Object& calendar, Object& prototype)
PlainDate::PlainDate(i32 year, u8 month, u8 day, Object& calendar, Object& prototype)
: Object(prototype)
, m_iso_year(year)
, m_iso_month(month)
@ -29,7 +29,7 @@ void PlainDate::visit_edges(Visitor& visitor)
}
// 3.5.1 CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaldate
PlainDate* create_temporal_date(GlobalObject& global_object, i32 iso_year, i32 iso_month, i32 iso_day, Object& calendar, FunctionObject* new_target)
PlainDate* create_temporal_date(GlobalObject& global_object, i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, FunctionObject* new_target)
{
auto& vm = global_object.vm();
@ -159,13 +159,13 @@ Optional<TemporalDate> regulate_iso_date(GlobalObject& global_object, double yea
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
// This does not change the exposed behaviour as the call to IsValidISODate will immediately check that these values are valid ISO
// values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check.
if (!AK::is_within_range<i32>(year) || !AK::is_within_range<i32>(month) || !AK::is_within_range<i32>(day)) {
if (!AK::is_within_range<i32>(year) || !AK::is_within_range<u8>(month) || !AK::is_within_range<u8>(day)) {
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
return {};
}
auto y = static_cast<i32>(year);
auto m = static_cast<i32>(month);
auto d = static_cast<i32>(day);
auto m = static_cast<u8>(month);
auto d = static_cast<u8>(day);
// a. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception.
if (is_valid_iso_date(y, m, d)) {
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
@ -191,13 +191,13 @@ Optional<TemporalDate> regulate_iso_date(GlobalObject& global_object, double yea
day = constrain_to_range(day, 1, iso_days_in_month(y, month));
// c. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }.
return TemporalDate { .year = y, .month = static_cast<i32>(month), .day = static_cast<i32>(day), .calendar = {} };
return TemporalDate { .year = y, .month = static_cast<u8>(month), .day = static_cast<u8>(day), .calendar = {} };
}
VERIFY_NOT_REACHED();
}
// 3.5.5 IsValidISODate ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidisodate
bool is_valid_iso_date(i32 year, i32 month, i32 day)
bool is_valid_iso_date(i32 year, u8 month, u8 day)
{
// 1. Assert: year, month, and day are integers.

View file

@ -15,12 +15,12 @@ class PlainDate final : public Object {
JS_OBJECT(PlainDate, Object);
public:
PlainDate(i32 iso_year, i32 iso_month, i32 iso_day, Object& calendar, Object& prototype);
PlainDate(i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, Object& prototype);
virtual ~PlainDate() override = default;
[[nodiscard]] i32 iso_year() const { return m_iso_year; }
[[nodiscard]] i32 iso_month() const { return m_iso_month; }
[[nodiscard]] i32 iso_day() const { return m_iso_day; }
[[nodiscard]] u8 iso_month() const { return m_iso_month; }
[[nodiscard]] u8 iso_day() const { return m_iso_day; }
[[nodiscard]] Object const& calendar() const { return m_calendar; }
[[nodiscard]] Object& calendar() { return m_calendar; }
@ -29,14 +29,14 @@ private:
// 3.4 Properties of Temporal.PlainDate Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plaindate-instances
i32 m_iso_year { 0 }; // [[ISOYear]]
i32 m_iso_month { 1 }; // [[ISOMonth]]
i32 m_iso_day { 1 }; // [[ISODay]]
u8 m_iso_month { 1 }; // [[ISOMonth]]
u8 m_iso_day { 1 }; // [[ISODay]]
Object& m_calendar; // [[Calendar]]
};
PlainDate* create_temporal_date(GlobalObject&, i32 iso_year, i32 iso_month, i32 iso_day, Object& calendar, FunctionObject* new_target = nullptr);
PlainDate* create_temporal_date(GlobalObject&, i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, FunctionObject* new_target = nullptr);
PlainDate* to_temporal_date(GlobalObject&, Value item, Object* options = nullptr);
Optional<TemporalDate> regulate_iso_date(GlobalObject&, double year, double month, double day, String const& overflow);
bool is_valid_iso_date(i32 year, i32 month, i32 day);
bool is_valid_iso_date(i32 year, u8 month, u8 day);
}

View file

@ -84,7 +84,7 @@ Value PlainDateConstructor::construct(FunctionObject& new_target)
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
// This does not change the exposed behaviour as the call to CreateTemporalDate will immediately check that these values are valid
// ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check.
if (!AK::is_within_range<i32>(y) || !AK::is_within_range<i32>(m) || !AK::is_within_range<i32>(d)) {
if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) {
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
return {};
}

View file

@ -36,7 +36,7 @@ void PlainDateTime::visit_edges(Visitor& visitor)
}
// 5.5.1 GetEpochFromISOParts ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-getepochfromisoparts
BigInt* get_epoch_from_iso_parts(GlobalObject& global_object, i32 year, i32 month, i32 day, i32 hour, i32 minute, i32 second, i32 millisecond, i32 microsecond, i32 nanosecond)
BigInt* get_epoch_from_iso_parts(GlobalObject& global_object, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
{
auto& vm = global_object.vm();
@ -70,7 +70,7 @@ const auto DATETIME_NANOSECONDS_MIN = "-8640086400000000000000"_sbigint;
const auto DATETIME_NANOSECONDS_MAX = "8640086400000000000000"_sbigint;
// 5.5.2 ISODateTimeWithinLimits ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isodatetimewithinlimits
bool iso_date_time_within_limits(GlobalObject& global_object, i32 year, i32 month, i32 day, i32 hour, i32 minute, i32 second, i32 millisecond, i32 microsecond, i32 nanosecond)
bool iso_date_time_within_limits(GlobalObject& global_object, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
{
// 1. Assert: year, month, day, hour, minute, second, millisecond, microsecond, and nanosecond are integers.

View file

@ -46,8 +46,8 @@ private:
Object& m_calendar; // [[Calendar]]
};
BigInt* get_epoch_from_iso_parts(GlobalObject&, i32 year, i32 month, i32 day, i32 hour, i32 minute, i32 second, i32 millisecond, i32 microsecond, i32 nanosecond);
bool iso_date_time_within_limits(GlobalObject&, i32 year, i32 month, i32 day, i32 hour, i32 minute, i32 second, i32 millisecond, i32 microsecond, i32 nanosecond);
BigInt* get_epoch_from_iso_parts(GlobalObject&, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond);
bool iso_date_time_within_limits(GlobalObject&, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond);
PlainDateTime* create_temporal_date_time(GlobalObject&, i32 iso_year, u8 iso_month, u8 iso_day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object& calendar, FunctionObject* new_target = nullptr);
}

View file

@ -10,42 +10,42 @@
namespace JS::Temporal {
// 4.5.5 IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidtime
bool is_valid_time(i32 hour, i32 minute, i32 second, i32 millisecond, i32 microsecond, i32 nanosecond)
bool is_valid_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
{
// 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers.
// 2. If hour < 0 or hour > 23, then
if (hour < 0 || hour > 23) {
if (hour > 23) {
// a. Return false.
return false;
}
// 3. If minute < 0 or minute > 59, then
if (minute < 0 || minute > 59) {
if (minute > 59) {
// a. Return false.
return false;
}
// 4. If second < 0 or second > 59, then
if (second < 0 || second > 59) {
if (second > 59) {
// a. Return false.
return false;
}
// 5. If millisecond < 0 or millisecond > 999, then
if (millisecond < 0 || millisecond > 999) {
if (millisecond > 999) {
// a. Return false.
return false;
}
// 6. If microsecond < 0 or microsecond > 999, then
if (microsecond < 0 || microsecond > 999) {
if (microsecond > 999) {
// a. Return false.
return false;
}
// 7. If nanosecond < 0 or nanosecond > 999, then
if (nanosecond < 0 || nanosecond > 999) {
if (nanosecond > 999) {
// a. Return false.
return false;
}

View file

@ -10,6 +10,6 @@
namespace JS::Temporal {
bool is_valid_time(i32 hour, i32 minute, i32 second, i32 millisecond, i32 microsecond, i32 nanosecond);
bool is_valid_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond);
}