LibJS: Use "either" / "one of" when comparing multiple items in Temporal

This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/5b02980
This commit is contained in:
Timothy Flynn 2026-02-14 11:46:19 -05:00 committed by Shannon Booth
parent d9ce90978c
commit 78ff593cc8
9 changed files with 28 additions and 26 deletions

View file

@ -353,7 +353,7 @@ Optional<Unicode::CalendarPattern> get_date_time_format(Unicode::CalendarPattern
format_options.era = options.era;
}
// c. If required is TIME or ANY, then
// c. If required is either TIME or ANY, then
if (required == OptionRequired::Time || required == OptionRequired::Any) {
// i. Set formatOptions.[[hourCycle]] to options.[[hourCycle]].
format_options.hour_cycle = options.hour_cycle;
@ -536,7 +536,7 @@ static double to_epoch_milliseconds(Crypto::SignedBigInteger const& epoch_nanose
// 15.6.15 HandleDateTimeTemporalDate ( dateTimeFormat, temporalDate ), https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporaldate
ThrowCompletionOr<ValueFormat> handle_date_time_temporal_date(VM& vm, DateTimeFormat& date_time_format, Temporal::PlainDate const& temporal_date)
{
// 1. If temporalDate.[[Calendar]] is not dateTimeFormat.[[Calendar]] or "iso8601", throw a RangeError exception.
// 1. If temporalDate.[[Calendar]] is not either dateTimeFormat.[[Calendar]] or "iso8601", throw a RangeError exception.
if (!temporal_date.calendar().is_one_of(date_time_format.calendar(), "iso8601"sv))
return vm.throw_completion<RangeError>(ErrorType::IntlTemporalInvalidCalendar, "Temporal.PlainDate"sv, temporal_date.calendar(), date_time_format.calendar());

View file

@ -310,7 +310,7 @@ ThrowCompletionOr<Precision> get_temporal_fractional_second_digits_option(VM& vm
return Precision { Auto {} };
}
// 4. If digitsValue is NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception.
// 4. If digitsValue is one of NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception.
if (digits_value.is_nan() || digits_value.is_infinity())
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, digits_value, vm.names.fractionalSecondDigits);
@ -469,11 +469,11 @@ ThrowCompletionOr<void> validate_temporal_unit_value(VM& vm, PropertyKey const&
auto unit_value = value.get<Unit>();
auto category = temporal_unit_category(unit_value);
// 4. If category is DATE and unitGroup is DATE or DATETIME, return unused.
// 4. If category is DATE and unitGroup is either DATE or DATETIME, return unused.
if (category == UnitCategory::Date && (unit_group == UnitGroup::Date || unit_group == UnitGroup::DateTime))
return {};
// 5. If category is TIME and unitGroup is TIME or DATETIME, return unused.
// 5. If category is TIME and unitGroup is either TIME or DATETIME, return unused.
if (category == UnitCategory::Time && (unit_group == UnitGroup::Time || unit_group == UnitGroup::DateTime))
return {};
@ -1666,13 +1666,13 @@ CalendarFields iso_date_to_fields(StringView calendar, ISODate iso_date, DateTyp
// 3. Set fields.[[MonthCode]] to calendarDate.[[MonthCode]].
fields.month_code = calendar_date.month_code;
// 4. If type is MONTH-DAY or DATE, then
// 4. If type is either MONTH-DAY or DATE, then
if (type == DateType::MonthDay || type == DateType::Date) {
// a. Set fields.[[Day]] to calendarDate.[[Day]].
fields.day = calendar_date.day;
}
// 5. If type is YEAR-MONTH or DATE, then
// 5. If type is either YEAR-MONTH or DATE, then
if (type == DateType::YearMonth || type == DateType::Date) {
// a. Set fields.[[Year]] to calendarDate.[[Year]].
fields.year = calendar_date.year;

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
* Copyright (c) 2024-2026, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -206,7 +206,7 @@ ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, Value argument, Err
// 1. Let number be ? ToNumber(argument).
auto number = TRY(argument.to_number(vm));
// 2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
// 2. If number is one of NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception.
if (number.is_nan() || number.is_infinity())
return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
@ -223,7 +223,7 @@ ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, StringView argument
// 1. Let number be ? ToNumber(argument).
auto number = string_to_number(argument);
// 2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
// 2. If number is one of NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception.
if (isnan(number) || isinf(number))
return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);

View file

@ -7,6 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/GenericShorthands.h>
#include <AK/NonnullRawPtr.h>
#include <AK/QuickSort.h>
#include <LibJS/Runtime/AbstractOperations.h>
@ -485,7 +486,7 @@ DateDuration calendar_date_until(VM& vm, StringView calendar, ISODate one, ISODa
// number of months to traverse.
// c. If largestUnit is YEAR, then
// e. If largestUnit is YEAR or largestUnit is MONTH, then
// e. If largestUnit is either YEAR or MONTH, then
if (largest_unit == Unit::Year || largest_unit == Unit::Month) {
// c.i. Let candidateYears be sign.
auto candidate_years = two.year - one.year;
@ -691,12 +692,12 @@ bool calendar_equals(StringView one, StringView two)
// 12.3.17 ISODaysInMonth ( year, month ), https://tc39.es/proposal-temporal/#sec-temporal-isodaysinmonth
u8 iso_days_in_month(double year, double month)
{
// 1. If month is 1, 3, 5, 7, 8, 10, or 12, return 31.
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
// 1. If month is one of 1, 3, 5, 7, 8, 10, or 12, return 31.
if (first_is_one_of(month, 1, 3, 5, 7, 8, 10, 12))
return 31;
// 2. If month is 4, 6, 9, or 11, return 30.
if (month == 4 || month == 6 || month == 9 || month == 11)
// 2. If month is one of 4, 6, 9, or 11, return 30.
if (first_is_one_of(month, 4, 6, 9, 11))
return 30;
// 3. Assert: month is 2.

View file

@ -7,6 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/GenericShorthands.h>
#include <AK/Math.h>
#include <AK/NumericLimits.h>
#include <LibJS/Runtime/AbstractOperations.h>
@ -1526,8 +1527,8 @@ String temporal_duration_to_string(Duration const& duration, Precision precision
// 10. Let zeroMinutesAndHigher be false.
auto zero_minutes_and_higher = false;
// 11. If DefaultTemporalLargestUnit(duration) is SECOND, MILLISECOND, MICROSECOND, or NANOSECOND, set zeroMinutesAndHigher to true.
if (auto unit = default_temporal_largest_unit(duration); unit == Unit::Second || unit == Unit::Millisecond || unit == Unit::Microsecond || unit == Unit::Nanosecond)
// 11. If DefaultTemporalLargestUnit(duration) is one of SECOND, MILLISECOND, MICROSECOND, or NANOSECOND, set zeroMinutesAndHigher to true.
if (first_is_one_of(default_temporal_largest_unit(duration), Unit::Second, Unit::Millisecond, Unit::Microsecond, Unit::Nanosecond))
zero_minutes_and_higher = true;
// 12. Let secondsDuration be TimeDurationFromComponents(0, 0, duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
* Copyright (c) 2024-2026, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -147,7 +147,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationConstructor::compare)
// 11. Let duration2 be ToInternalDurationRecord(two).
auto duration2 = to_internal_duration_record(vm, two);
// 12. If zonedRelativeTo is not undefined, and either TemporalUnitCategory(largestUnit1) or TemporalUnitCategory(largestUnit2) is date, then
// 12. If zonedRelativeTo is not undefined, and TemporalUnitCategory(largestUnit1) is DATE or TemporalUnitCategory(largestUnit2) is DATE, then
if (zoned_relative_to && (temporal_unit_category(largest_unit1) == UnitCategory::Date || temporal_unit_category(largest_unit2) == UnitCategory::Date)) {
// a. Let timeZone be zonedRelativeTo.[[TimeZone]].
auto const time_zone = zoned_relative_to->time_zone();

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
* Copyright (c) 2024-2026, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -407,7 +407,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::round)
return TRY(temporal_duration_from_internal(vm, internal_duration, largest_unit_value));
}
// 29. If IsCalendarUnit(existingLargestUnit) is true, or IsCalendarUnit(largestUnit) is true, throw a RangeError exception.
// 29. If IsCalendarUnit(existingLargestUnit) is true or IsCalendarUnit(largestUnit) is true, throw a RangeError exception.
if (is_calendar_unit(existing_largest_unit))
return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidLargestUnit, temporal_unit_to_string(existing_largest_unit));
if (is_calendar_unit(largest_unit_value))
@ -548,7 +548,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::total)
// a. Let largestUnit be DefaultTemporalLargestUnit(duration).
auto largest_unit = default_temporal_largest_unit(duration);
// b. If IsCalendarUnit(largestUnit) is true, or IsCalendarUnit(unit) is true, throw a RangeError exception.
// b. If IsCalendarUnit(largestUnit) is true or IsCalendarUnit(unit) is true, throw a RangeError exception.
if (is_calendar_unit(largest_unit))
return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidLargestUnit, temporal_unit_to_string(largest_unit));
if (is_calendar_unit(unit_value))
@ -591,7 +591,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::to_string)
// 8. Perform ? ValidateTemporalUnitValue(smallestUnit, TIME).
TRY(validate_temporal_unit_value(vm, vm.names.smallestUnit, smallest_unit, UnitGroup::Time));
// 9. If smallestUnit is HOUR or MINUTE, throw a RangeError exception.
// 9. If smallestUnit is either HOUR or MINUTE, throw a RangeError exception.
if (auto const* unit = smallest_unit.get_pointer<Unit>(); unit && (*unit == Unit::Hour || *unit == Unit::Minute))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, temporal_unit_to_string(*unit), vm.names.smallestUnit);

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
* Copyright (c) 2024-2026, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -538,7 +538,7 @@ Time round_time(Time const& time, u64 increment, Unit unit, RoundingMode roundin
double quantity = 0;
switch (unit) {
// 1. If unit is DAY or HOUR, then
// 1. If unit is either DAY or HOUR, then
case Unit::Day:
case Unit::Hour:
// a. Let quantity be ((((time.[[Hour]] × 60 + time.[[Minute]]) × 60 + time.[[Second]]) × 1000 + time.[[Millisecond]]) × 1000 + time.[[Microsecond]]) × 1000 + time.[[Nanosecond]].

View file

@ -295,7 +295,7 @@ ThrowCompletionOr<Crypto::SignedBigInteger> disambiguate_possible_epoch_nanoseco
// 3. If n ≠ 0, then
if (n != 0) {
// a. If disambiguation is EARLIER or COMPATIBLE, then
// a. If disambiguation is either EARLIER or COMPATIBLE, then
if (disambiguation == Disambiguation::Earlier || disambiguation == Disambiguation::Compatible) {
// i. Return possibleEpochNs[0].
return move(possible_epoch_ns[0]);