mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
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:
parent
c5c32ad274
commit
2c6bd3a61b
Notes:
sideshowbarker
2024-07-18 08:18:57 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/2c6bd3a61b3 Pull-request: https://github.com/SerenityOS/serenity/pull/9023 Reviewed-by: https://github.com/linusg ✅
11 changed files with 47 additions and 49 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
@ -28,15 +28,15 @@ private:
|
|||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
// 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]]
|
||||
Object& m_calendar; // [[Calendar]]
|
||||
i32 m_iso_year { 0 }; // [[ISOYear]]
|
||||
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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue