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()); VERIFY(sign_part.has_value());
// b. Set hours to ! ToIntegerOrInfinity(hours). // 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 // 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")) { if (sign_part->is_one_of("-", "\u2212")) {
// i. Set sign to 1. // i. Set sign to 1.
@ -592,10 +592,10 @@ Optional<TemporalTimeZone> parse_temporal_time_zone_string(GlobalObject& global_
} }
// e. Set minutes to ! ToIntegerOrInfinity(minutes). // 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). // 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; i32 nanoseconds;
// g. If fraction is not undefined, then // g. If fraction is not undefined, then

View file

@ -33,25 +33,23 @@ struct ISODateTime {
Optional<String> calendar = {}; Optional<String> calendar = {};
}; };
// FIXME: Use more narrow types for most of these (u8/u16)
struct TemporalInstant { struct TemporalInstant {
i32 year; i32 year;
i32 month; u8 month;
i32 day; u8 day;
i32 hour; u8 hour;
i32 minute; u8 minute;
i32 second; u8 second;
i32 millisecond; u16 millisecond;
i32 microsecond; u16 microsecond;
i32 nanosecond; u16 nanosecond;
Optional<String> time_zone_offset; Optional<String> time_zone_offset;
}; };
// FIXME: Use more narrow type for month/day (u8)
struct TemporalDate { struct TemporalDate {
i32 year; i32 year;
i32 month; u8 month;
i32 day; u8 day;
Optional<String> calendar; 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 // 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. // 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 // 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); 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 calendar_equals(GlobalObject&, Object& one, Object& two);
bool is_iso_leap_year(i32 year); bool is_iso_leap_year(i32 year);
u16 iso_days_in_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); u8 to_iso_day_of_week(i32 year, u8 month, u8 day);
u16 to_iso_day_of_year(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); 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); double resolve_iso_month(GlobalObject&, Object& fields);
Optional<TemporalDate> iso_date_from_fields(GlobalObject&, Object& fields, Object& options); Optional<TemporalDate> iso_date_from_fields(GlobalObject&, Object& fields, Object& options);
i32 iso_year(Object& temporal_object); i32 iso_year(Object& temporal_object);

View file

@ -14,7 +14,7 @@
namespace JS::Temporal { namespace JS::Temporal {
// 3 Temporal.PlainDate Objects, https://tc39.es/proposal-temporal/#sec-temporal-plaindate-objects // 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) : Object(prototype)
, m_iso_year(year) , m_iso_year(year)
, m_iso_month(month) , 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 // 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(); 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. // 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 // 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. // 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); vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
return {}; return {};
} }
auto y = static_cast<i32>(year); auto y = static_cast<i32>(year);
auto m = static_cast<i32>(month); auto m = static_cast<u8>(month);
auto d = static_cast<i32>(day); auto d = static_cast<u8>(day);
// a. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception. // a. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception.
if (is_valid_iso_date(y, m, d)) { if (is_valid_iso_date(y, m, d)) {
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate); 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)); day = constrain_to_range(day, 1, iso_days_in_month(y, month));
// c. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }. // 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(); VERIFY_NOT_REACHED();
} }
// 3.5.5 IsValidISODate ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidisodate // 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. // 1. Assert: year, month, and day are integers.

View file

@ -15,12 +15,12 @@ class PlainDate final : public Object {
JS_OBJECT(PlainDate, Object); JS_OBJECT(PlainDate, Object);
public: 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; virtual ~PlainDate() override = default;
[[nodiscard]] i32 iso_year() const { return m_iso_year; } [[nodiscard]] i32 iso_year() const { return m_iso_year; }
[[nodiscard]] i32 iso_month() const { return m_iso_month; } [[nodiscard]] u8 iso_month() const { return m_iso_month; }
[[nodiscard]] i32 iso_day() const { return m_iso_day; } [[nodiscard]] u8 iso_day() const { return m_iso_day; }
[[nodiscard]] Object const& calendar() const { return m_calendar; } [[nodiscard]] Object const& calendar() const { return m_calendar; }
[[nodiscard]] Object& calendar() { return m_calendar; } [[nodiscard]] Object& calendar() { return m_calendar; }
@ -28,15 +28,15 @@ private:
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
// 3.4 Properties of Temporal.PlainDate Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plaindate-instances // 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_year { 0 }; // [[ISOYear]]
i32 m_iso_month { 1 }; // [[ISOMonth]] u8 m_iso_month { 1 }; // [[ISOMonth]]
i32 m_iso_day { 1 }; // [[ISODay]] u8 m_iso_day { 1 }; // [[ISODay]]
Object& m_calendar; // [[Calendar]] 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); 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); 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. // 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 // 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. // 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); vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
return {}; 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 // 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(); auto& vm = global_object.vm();
@ -70,7 +70,7 @@ const auto DATETIME_NANOSECONDS_MIN = "-8640086400000000000000"_sbigint;
const auto DATETIME_NANOSECONDS_MAX = "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 // 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. // 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]] 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); 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, 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, 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); 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 { namespace JS::Temporal {
// 4.5.5 IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidtime // 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. // 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers.
// 2. If hour < 0 or hour > 23, then // 2. If hour < 0 or hour > 23, then
if (hour < 0 || hour > 23) { if (hour > 23) {
// a. Return false. // a. Return false.
return false; return false;
} }
// 3. If minute < 0 or minute > 59, then // 3. If minute < 0 or minute > 59, then
if (minute < 0 || minute > 59) { if (minute > 59) {
// a. Return false. // a. Return false.
return false; return false;
} }
// 4. If second < 0 or second > 59, then // 4. If second < 0 or second > 59, then
if (second < 0 || second > 59) { if (second > 59) {
// a. Return false. // a. Return false.
return false; return false;
} }
// 5. If millisecond < 0 or millisecond > 999, then // 5. If millisecond < 0 or millisecond > 999, then
if (millisecond < 0 || millisecond > 999) { if (millisecond > 999) {
// a. Return false. // a. Return false.
return false; return false;
} }
// 6. If microsecond < 0 or microsecond > 999, then // 6. If microsecond < 0 or microsecond > 999, then
if (microsecond < 0 || microsecond > 999) { if (microsecond > 999) {
// a. Return false. // a. Return false.
return false; return false;
} }
// 7. If nanosecond < 0 or nanosecond > 999, then // 7. If nanosecond < 0 or nanosecond > 999, then
if (nanosecond < 0 || nanosecond > 999) { if (nanosecond > 999) {
// a. Return false. // a. Return false.
return false; return false;
} }

View file

@ -10,6 +10,6 @@
namespace JS::Temporal { 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);
} }