mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 20:33:10 +00:00
LibJS: Refactor Temporal add/subtract to common AOs
This is an editorial change in the Temporal spec. See: - https://github.com/tc39/proposal-temporal/commit/2f96efc - https://github.com/tc39/proposal-temporal/commit/fbff635
This commit is contained in:
parent
875093e6a9
commit
3729a910f6
|
@ -17,6 +17,11 @@
|
|||
|
||||
namespace JS::Temporal {
|
||||
|
||||
enum class ArithmeticOperation {
|
||||
Add,
|
||||
Subtract,
|
||||
};
|
||||
|
||||
enum class OptionType {
|
||||
Boolean,
|
||||
String,
|
||||
|
|
|
@ -1719,4 +1719,26 @@ String temporal_duration_to_string(double years, double months, double weeks, do
|
|||
return result.to_string();
|
||||
}
|
||||
|
||||
// 7.5.29 AddDurationToOrSubtractDurationFromDuration ( operation, duration, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromduration
|
||||
ThrowCompletionOr<Duration*> add_duration_to_or_subtract_duration_from_duration(GlobalObject& global_object, ArithmeticOperation operation, Duration const& duration, Value other_value, Value options_value)
|
||||
{
|
||||
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
|
||||
i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1;
|
||||
|
||||
// 2. Set other to ? ToTemporalDurationRecord(other).
|
||||
auto other = TRY(to_temporal_duration_record(global_object, other_value));
|
||||
|
||||
// 3. Set options to ? GetOptionsObject(options).
|
||||
auto const* options = TRY(get_options_object(global_object, options_value));
|
||||
|
||||
// 4. Let relativeTo be ? ToRelativeTemporalObject(options).
|
||||
auto relative_to = TRY(to_relative_temporal_object(global_object, *options));
|
||||
|
||||
// 5. Let result be ? AddDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], sign × other.[[Years]], sign × other.[[Months]], sign × other.[[Weeks]], sign × other.[[Days]], sign × other.[[Hours]], sign × other.[[Minutes]], sign × other.[[Seconds]], sign × other.[[Milliseconds]], sign × other.[[Microseconds]], sign × other.[[Nanoseconds]], relativeTo).
|
||||
auto result = TRY(add_duration(global_object, duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds(), sign * other.years, sign * other.months, sign * other.weeks, sign * other.days, sign * other.hours, sign * other.minutes, sign * other.seconds, sign * other.milliseconds, sign * other.microseconds, sign * other.nanoseconds, relative_to));
|
||||
|
||||
// 6. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return MUST(create_temporal_duration(global_object, result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject&, double years, d
|
|||
ThrowCompletionOr<DurationRecord> adjust_rounded_duration_days(GlobalObject& global_object, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, u32 increment, StringView unit, StringView rounding_mode, Object* relative_to_object = nullptr);
|
||||
ThrowCompletionOr<DurationRecord> to_limited_temporal_duration(GlobalObject&, Value temporal_duration_like, Vector<StringView> const& disallowed_fields);
|
||||
String temporal_duration_to_string(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Variant<StringView, u8> const& precision);
|
||||
ThrowCompletionOr<Duration*> add_duration_to_or_subtract_duration_from_duration(GlobalObject&, ArithmeticOperation, Duration const&, Value other_value, Value options_value);
|
||||
|
||||
// 7.5.22 DaysUntil ( earlier, later ), https://tc39.es/proposal-temporal/#sec-temporal-daysuntil
|
||||
template<typename EarlierObjectType, typename LaterObjectType>
|
||||
|
|
|
@ -294,47 +294,29 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::abs)
|
|||
// 7.3.18 Temporal.Duration.prototype.add ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.add
|
||||
JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::add)
|
||||
{
|
||||
auto other = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let duration be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Set other to ? ToTemporalDurationRecord(other).
|
||||
auto other = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto const* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let relativeTo be ? ToRelativeTemporalObject(options).
|
||||
auto relative_to = TRY(to_relative_temporal_object(global_object, *options));
|
||||
|
||||
// 6. Let result be ? AddDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], other.[[Years]], other.[[Months]], other.[[Weeks]], other.[[Days]], other.[[Hours]], other.[[Minutes]], other.[[Seconds]], other.[[Milliseconds]], other.[[Microseconds]], other.[[Nanoseconds]], relativeTo).
|
||||
auto result = TRY(add_duration(global_object, duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds(), other.years, other.months, other.weeks, other.days, other.hours, other.minutes, other.seconds, other.milliseconds, other.microseconds, other.nanoseconds, relative_to));
|
||||
|
||||
// 7. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return MUST(create_temporal_duration(global_object, result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromDuration(add, duration, other, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_duration(global_object, ArithmeticOperation::Add, *duration, other, options));
|
||||
}
|
||||
|
||||
// 7.3.19 Temporal.Duration.prototype.subtract ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.subtract
|
||||
JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::subtract)
|
||||
{
|
||||
auto other = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let duration be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Set other to ? ToTemporalDurationRecord(other).
|
||||
auto other = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto const* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let relativeTo be ? ToRelativeTemporalObject(options).
|
||||
auto relative_to = TRY(to_relative_temporal_object(global_object, *options));
|
||||
|
||||
// 6. Let result be ? AddDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], -other.[[Years]], -other.[[Months]], -other.[[Weeks]], -other.[[Days]], -other.[[Hours]], -other.[[Minutes]], -other.[[Seconds]], -other.[[Milliseconds]], -other.[[Microseconds]], -other.[[Nanoseconds]], relativeTo).
|
||||
auto result = TRY(add_duration(global_object, duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds(), -other.years, -other.months, -other.weeks, -other.days, -other.hours, -other.minutes, -other.seconds, -other.milliseconds, -other.microseconds, -other.nanoseconds, relative_to));
|
||||
|
||||
// 7. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return MUST(create_temporal_duration(global_object, result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromDuration(subtract, duration, other, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_duration(global_object, ArithmeticOperation::Subtract, *duration, other, options));
|
||||
}
|
||||
|
||||
// 7.3.20 Temporal.Duration.prototype.round ( roundTo ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.round
|
||||
|
|
|
@ -281,4 +281,20 @@ ThrowCompletionOr<String> temporal_instant_to_string(GlobalObject& global_object
|
|||
return String::formatted("{}{}", date_time_string, time_zone_string);
|
||||
}
|
||||
|
||||
// 8.5.10 AddDurationToOrSubtractDurationFromInstant ( operation, instant, temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfrominstant
|
||||
ThrowCompletionOr<Instant*> add_duration_to_or_subtract_duration_from_instant(GlobalObject& global_object, ArithmeticOperation operation, Instant const& instant, Value temporal_duration_like)
|
||||
{
|
||||
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
|
||||
i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1;
|
||||
|
||||
// 2. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »).
|
||||
auto duration = TRY(to_limited_temporal_duration(global_object, temporal_duration_like, { "years"sv, "months"sv, "weeks"sv, "days"sv }));
|
||||
|
||||
// 3. Let ns be ? AddInstant(instant.[[Nanoseconds]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
|
||||
auto* ns = TRY(add_instant(global_object, instant.nanoseconds(), sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds));
|
||||
|
||||
// 4. Return ! CreateTemporalInstant(ns).
|
||||
return MUST(create_temporal_instant(global_object, *ns));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
@ -12,6 +12,7 @@
|
|||
#include <LibJS/Runtime/BigInt.h>
|
||||
#include <LibJS/Runtime/Completion.h>
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
|
@ -45,5 +46,6 @@ ThrowCompletionOr<BigInt*> add_instant(GlobalObject&, BigInt const& epoch_nanose
|
|||
BigInt* difference_instant(GlobalObject&, BigInt const& nanoseconds1, BigInt const& nanoseconds2, u64 rounding_increment, StringView smallest_unit, StringView rounding_mode);
|
||||
BigInt* round_temporal_instant(GlobalObject&, BigInt const& nanoseconds, u64 increment, StringView unit, StringView rounding_mode);
|
||||
ThrowCompletionOr<String> temporal_instant_to_string(GlobalObject&, Instant&, Value time_zone, Variant<StringView, u8> const& precision);
|
||||
ThrowCompletionOr<Instant*> add_duration_to_or_subtract_duration_from_instant(GlobalObject&, ArithmeticOperation, Instant const&, Value temporal_duration_like);
|
||||
|
||||
}
|
||||
|
|
|
@ -126,14 +126,8 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::add)
|
|||
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
|
||||
auto* instant = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »).
|
||||
auto duration = TRY(to_limited_temporal_duration(global_object, temporal_duration_like, { "years"sv, "months"sv, "weeks"sv, "days"sv }));
|
||||
|
||||
// 4. Let ns be ? AddInstant(instant.[[Nanoseconds]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
|
||||
auto* ns = TRY(add_instant(global_object, instant->nanoseconds(), duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds));
|
||||
|
||||
// 5. Return ! CreateTemporalInstant(ns).
|
||||
return MUST(create_temporal_instant(global_object, *ns));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromInstant(add, instant, temporalDurationLike).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_instant(global_object, ArithmeticOperation::Add, *instant, temporal_duration_like));
|
||||
}
|
||||
|
||||
// 8.3.8 Temporal.Instant.prototype.subtract ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.subtract
|
||||
|
@ -145,14 +139,8 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::subtract)
|
|||
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
|
||||
auto* instant = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »).
|
||||
auto duration = TRY(to_limited_temporal_duration(global_object, temporal_duration_like, { "years"sv, "months"sv, "weeks"sv, "days"sv }));
|
||||
|
||||
// 4. Let ns be ? AddInstant(instant.[[Nanoseconds]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]]).
|
||||
auto* ns = TRY(add_instant(global_object, instant->nanoseconds(), -duration.hours, -duration.minutes, -duration.seconds, -duration.milliseconds, -duration.microseconds, -duration.nanoseconds));
|
||||
|
||||
// 5. Return ! CreateTemporalInstant(ns).
|
||||
return MUST(create_temporal_instant(global_object, *ns));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromInstant(subtract, instant, temporalDurationLike).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_instant(global_object, ArithmeticOperation::Subtract, *instant, temporal_duration_like));
|
||||
}
|
||||
|
||||
// 8.3.9 Temporal.Instant.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.until
|
||||
|
|
|
@ -391,4 +391,29 @@ ThrowCompletionOr<DurationRecord> difference_iso_date_time(GlobalObject& global_
|
|||
return create_duration_record(date_difference->years(), date_difference->months(), date_difference->weeks(), balance_result.days, balance_result.hours, balance_result.minutes, balance_result.seconds, balance_result.milliseconds, balance_result.microseconds, balance_result.nanoseconds);
|
||||
}
|
||||
|
||||
// 5.5.12 AddDurationToOrSubtractDurationFromPlainDateTime ( operation, dateTime, temporalDurationLike, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromplaindatetime
|
||||
ThrowCompletionOr<PlainDateTime*> add_duration_to_or_subtract_duration_from_plain_date_time(GlobalObject& global_object, ArithmeticOperation operation, PlainDateTime& date_time, Value temporal_duration_like, Value options_value)
|
||||
{
|
||||
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
|
||||
i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1;
|
||||
|
||||
// 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, temporal_duration_like));
|
||||
|
||||
// 3. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, options_value));
|
||||
|
||||
// 4. Let result be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]], options).
|
||||
auto result = TRY(add_date_time(global_object, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), sign * duration.years, sign * duration.months, sign * duration.weeks, sign * duration.days, sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds, options));
|
||||
|
||||
// 5. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
|
||||
VERIFY(is_valid_iso_date(result.year, result.month, result.day));
|
||||
|
||||
// 6. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
|
||||
VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
|
||||
// 7. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]).
|
||||
return create_temporal_date_time(global_object, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, date_time.calendar());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,5 +74,6 @@ i8 compare_iso_date_time(i32 year1, u8 month1, u8 day1, u8 hour1, u8 minute1, u8
|
|||
ThrowCompletionOr<TemporalPlainDateTime> add_date_time(GlobalObject&, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object& calendar, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object* options);
|
||||
ISODateTime round_iso_date_time(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, u64 increment, StringView unit, StringView rounding_mode, Optional<double> day_length = {});
|
||||
ThrowCompletionOr<DurationRecord> difference_iso_date_time(GlobalObject&, i32 year1, u8 month1, u8 day1, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, i32 year2, u8 month2, u8 day2, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2, Object& calendar, StringView largest_unit, Object const* options = nullptr);
|
||||
ThrowCompletionOr<PlainDateTime*> add_duration_to_or_subtract_duration_from_plain_date_time(GlobalObject&, ArithmeticOperation, PlainDateTime&, Value temporal_duration_like, Value options_value);
|
||||
|
||||
}
|
||||
|
|
|
@ -461,53 +461,29 @@ JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::with_calendar)
|
|||
// 5.3.26 Temporal.PlainDateTime.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.add
|
||||
JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::add)
|
||||
{
|
||||
auto temporal_duration_like = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let dateTime be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
|
||||
auto* date_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let result be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], options).
|
||||
auto result = TRY(add_date_time(global_object, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), date_time->calendar(), duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds, options));
|
||||
|
||||
// 6. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
|
||||
VERIFY(is_valid_iso_date(result.year, result.month, result.day));
|
||||
|
||||
// 7. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
|
||||
VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
|
||||
// 8. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]).
|
||||
return TRY(create_temporal_date_time(global_object, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, date_time->calendar()));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromPlainDateTime(add, dateTime, temporalDurationLike, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_plain_date_time(global_object, ArithmeticOperation::Add, *date_time, temporal_duration_like, options));
|
||||
}
|
||||
|
||||
// 5.3.27 Temporal.PlainDateTime.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.subtract
|
||||
JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::subtract)
|
||||
{
|
||||
auto temporal_duration_like = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let dateTime be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
|
||||
auto* date_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let result be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], -duration.[[Years]], -duration.[[Months]], -duration.[[Weeks]], -duration.[[Days]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]], options).
|
||||
auto result = TRY(add_date_time(global_object, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), date_time->calendar(), -duration.years, -duration.months, -duration.weeks, -duration.days, -duration.hours, -duration.minutes, -duration.seconds, -duration.milliseconds, -duration.microseconds, -duration.nanoseconds, options));
|
||||
|
||||
// 6. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
|
||||
VERIFY(is_valid_iso_date(result.year, result.month, result.day));
|
||||
|
||||
// 7. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
|
||||
VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
|
||||
// 8. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]).
|
||||
return TRY(create_temporal_date_time(global_object, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, date_time->calendar()));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromPlainDateTime(subtract, dateTime, temporalDurationLike, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_plain_date_time(global_object, ArithmeticOperation::Subtract, *date_time, temporal_duration_like, options));
|
||||
}
|
||||
|
||||
// 5.3.28 Temporal.PlainDateTime.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.since
|
||||
|
|
|
@ -618,4 +618,23 @@ DaysAndTime round_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 micro
|
|||
return balance_time(hour, minute, second, millisecond, microsecond, result);
|
||||
}
|
||||
|
||||
// 4.5.14 AddDurationToOrSubtractDurationFromPlainTime ( operation, temporalTime, temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromplaintime
|
||||
ThrowCompletionOr<PlainTime*> add_duration_to_or_subtract_duration_from_plain_time(GlobalObject& global_object, ArithmeticOperation operation, PlainTime const& temporal_time, Value temporal_duration_like)
|
||||
{
|
||||
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
|
||||
i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1;
|
||||
|
||||
// 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, temporal_duration_like));
|
||||
|
||||
// 3. Let result be ! AddTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
|
||||
auto result = add_time(temporal_time.iso_hour(), temporal_time.iso_minute(), temporal_time.iso_second(), temporal_time.iso_millisecond(), temporal_time.iso_microsecond(), temporal_time.iso_nanosecond(), sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds);
|
||||
|
||||
// 4. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
|
||||
VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
|
||||
// 5. Return ? CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).
|
||||
return TRY(create_temporal_time(global_object, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -106,5 +106,6 @@ String temporal_time_to_string(u8 hour, u8 minute, u8 second, u16 millisecond, u
|
|||
i8 compare_temporal_time(u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2);
|
||||
DaysAndTime add_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds);
|
||||
DaysAndTime round_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, u64 increment, StringView unit, StringView rounding_mode, Optional<double> day_length_ns = {});
|
||||
ThrowCompletionOr<PlainTime*> add_duration_to_or_subtract_duration_from_plain_time(GlobalObject&, ArithmeticOperation, PlainTime const&, Value temporal_duration_like);
|
||||
|
||||
}
|
||||
|
|
|
@ -145,17 +145,8 @@ JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::add)
|
|||
// 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
|
||||
auto* temporal_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, temporal_duration_like));
|
||||
|
||||
// 4. Let result be ! AddTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
|
||||
auto result = add_time(temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds);
|
||||
|
||||
// 5. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
|
||||
VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
|
||||
// 6. Return ? CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).
|
||||
return TRY(create_temporal_time(global_object, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromPlainTime(add, temporalTime, temporalDurationLike).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_plain_time(global_object, ArithmeticOperation::Add, *temporal_time, temporal_duration_like));
|
||||
}
|
||||
|
||||
// 4.3.11 Temporal.PlainTime.prototype.subtract ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.subtract
|
||||
|
@ -167,17 +158,8 @@ JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::subtract)
|
|||
// 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
|
||||
auto* temporal_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, temporal_duration_like));
|
||||
|
||||
// 4. Let result be ! AddTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]]).
|
||||
auto result = add_time(temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), -duration.hours, -duration.minutes, -duration.seconds, -duration.milliseconds, -duration.microseconds, -duration.nanoseconds);
|
||||
|
||||
// 5. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
|
||||
VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
|
||||
// 6. Return ? CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).
|
||||
return TRY(create_temporal_time(global_object, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromPlainTime(subtract, temporalTime, temporalDurationLike).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_plain_time(global_object, ArithmeticOperation::Subtract, *temporal_time, temporal_duration_like));
|
||||
}
|
||||
|
||||
// 4.3.12 Temporal.PlainTime.prototype.with ( temporalTimeLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.with
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Temporal/Calendar.h>
|
||||
#include <LibJS/Runtime/Temporal/Duration.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainDate.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainYearMonth.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainYearMonthConstructor.h>
|
||||
|
@ -255,4 +257,92 @@ ThrowCompletionOr<String> temporal_year_month_to_string(GlobalObject& global_obj
|
|||
return String::formatted("{}{}", result, calendar_string);
|
||||
}
|
||||
|
||||
// 9.5.9 AddDurationToOrSubtractDurationFromPlainYearMonth ( operation, yearMonth, temporalDurationLike, options ), https://tc39.es/proposal-temporal/#sec-temporal-addtemporalplainyearmonth
|
||||
ThrowCompletionOr<PlainYearMonth*> add_duration_to_or_subtract_duration_from_plain_year_month(GlobalObject& global_object, ArithmeticOperation operation, PlainYearMonth& year_month, Value temporal_duration_like, Value options_value)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// 1. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, temporal_duration_like));
|
||||
|
||||
// 2. If operation is subtract, then
|
||||
if (operation == ArithmeticOperation::Subtract) {
|
||||
// a. Set duration to ! CreateNegatedTemporalDuration(duration).
|
||||
// FIXME: According to the spec CreateNegatedTemporalDuration takes a Temporal.Duration object,
|
||||
// not a record, so we have to do some trickery. If they want to accept anything that has
|
||||
// the required internal slots, this should be updated in the AO's description.
|
||||
// We also have to convert back to a Duration Record afterwards to match the initial type.
|
||||
auto* actual_duration = MUST(create_temporal_duration(global_object, duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds));
|
||||
auto* negated_duration = create_negated_temporal_duration(global_object, *actual_duration);
|
||||
duration = MUST(to_temporal_duration_record(global_object, negated_duration));
|
||||
}
|
||||
|
||||
// 3. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
|
||||
auto balance_result = TRY(balance_duration(global_object, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, Crypto::SignedBigInteger::create_from((i64)duration.nanoseconds), "day"sv));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, options_value));
|
||||
|
||||
// 5. Let calendar be yearMonth.[[Calendar]].
|
||||
auto& calendar = year_month.calendar();
|
||||
|
||||
// 6. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »).
|
||||
auto field_names = TRY(calendar_fields(global_object, calendar, { "monthCode"sv, "year"sv }));
|
||||
|
||||
// 7. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»).
|
||||
auto* fields = TRY(prepare_temporal_fields(global_object, year_month, field_names, {}));
|
||||
|
||||
// 8. Set sign to ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0).
|
||||
auto sign = duration_sign(duration.years, duration.months, duration.weeks, balance_result.days, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
double day;
|
||||
|
||||
// 9. If sign < 0, then
|
||||
if (sign < 0) {
|
||||
// a. Let dayFromCalendar be ? CalendarDaysInMonth(calendar, yearMonth).
|
||||
auto day_from_calendar = TRY(calendar_days_in_month(global_object, calendar, year_month));
|
||||
|
||||
// b. Let day be ? ToPositiveInteger(dayFromCalendar).
|
||||
day = TRY(to_positive_integer(global_object, day_from_calendar));
|
||||
}
|
||||
// 10. Else,
|
||||
else {
|
||||
// a. Let day be 1.
|
||||
day = 1;
|
||||
}
|
||||
|
||||
// 11. Perform ! CreateDataPropertyOrThrow(fields, "day", day).
|
||||
MUST(fields->create_data_property_or_throw(vm.names.day, Value(day)));
|
||||
|
||||
// 12. Let date be ? CalendarDateFromFields(calendar, fields, undefined).
|
||||
auto* date = TRY(calendar_date_from_fields(global_object, calendar, *fields, nullptr));
|
||||
|
||||
// 13. Let durationToAdd be ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0).
|
||||
auto* duration_to_add = MUST(create_temporal_duration(global_object, duration.years, duration.months, duration.weeks, balance_result.days, 0, 0, 0, 0, 0, 0));
|
||||
|
||||
// 14. Let optionsCopy be OrdinaryObjectCreate(%Object.prototype%).
|
||||
auto* options_copy = Object::create(global_object, global_object.object_prototype());
|
||||
|
||||
// 15. Let entries be ? EnumerableOwnPropertyNames(options, key+value).
|
||||
auto entries = TRY(options->enumerable_own_property_names(Object::PropertyKind::KeyAndValue));
|
||||
|
||||
// 16. For each element nextEntry of entries, do
|
||||
for (auto& next_entry : entries) {
|
||||
auto key = MUST(next_entry.as_array().get_without_side_effects(0).to_property_key(global_object));
|
||||
auto value = next_entry.as_array().get_without_side_effects(1);
|
||||
|
||||
// a. Perform ! CreateDataPropertyOrThrow(optionsCopy, nextEntry[0], nextEntry[1]).
|
||||
MUST(options_copy->create_data_property_or_throw(key, value));
|
||||
}
|
||||
|
||||
// 17. Let addedDate be ? CalendarDateAdd(calendar, date, durationToAdd, options).
|
||||
auto* added_date = TRY(calendar_date_add(global_object, calendar, date, *duration_to_add, options));
|
||||
|
||||
// 18. Let addedDateFields be ? PrepareTemporalFields(addedDate, fieldNames, «»).
|
||||
auto* added_date_fields = TRY(prepare_temporal_fields(global_object, *added_date, field_names, {}));
|
||||
|
||||
// 19. Return ? CalendarYearMonthFromFields(calendar, addedDateFields, optionsCopy).
|
||||
return calendar_year_month_from_fields(global_object, calendar, *added_date_fields, options_copy);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
|
@ -47,5 +48,6 @@ ISOYearMonth balance_iso_year_month(double year, double month);
|
|||
ISOYearMonth constrain_iso_year_month(double year, double month);
|
||||
ThrowCompletionOr<PlainYearMonth*> create_temporal_year_month(GlobalObject&, i32 iso_year, u8 iso_month, Object& calendar, u8 reference_iso_day, FunctionObject const* new_target = nullptr);
|
||||
ThrowCompletionOr<String> temporal_year_month_to_string(GlobalObject&, PlainYearMonth&, StringView show_calendar);
|
||||
ThrowCompletionOr<PlainYearMonth*> add_duration_to_or_subtract_duration_from_plain_year_month(GlobalObject&, ArithmeticOperation, PlainYearMonth&, Value temporal_duration_like, Value options_value);
|
||||
|
||||
}
|
||||
|
|
|
@ -239,164 +239,29 @@ JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::with)
|
|||
// 9.3.12 Temporal.PlainYearMonth.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.add
|
||||
JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::add)
|
||||
{
|
||||
auto temporal_duration_like = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let yearMonth be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
|
||||
auto* year_month = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
|
||||
auto balance_result = TRY(balance_duration(global_object, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, Crypto::SignedBigInteger::create_from((i64)duration.nanoseconds), "day"sv));
|
||||
|
||||
// 5. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 6. Let calendar be yearMonth.[[Calendar]].
|
||||
auto& calendar = year_month->calendar();
|
||||
|
||||
// 7. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »).
|
||||
auto field_names = TRY(calendar_fields(global_object, calendar, { "monthCode"sv, "year"sv }));
|
||||
|
||||
// 8. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»).
|
||||
auto* fields = TRY(prepare_temporal_fields(global_object, *year_month, field_names, {}));
|
||||
|
||||
// 9. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0).
|
||||
auto sign = duration_sign(duration.years, duration.months, duration.weeks, balance_result.days, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
double day;
|
||||
|
||||
// 10. If sign < 0, then
|
||||
if (sign < 0) {
|
||||
// a. Let dayFromCalendar be ? CalendarDaysInMonth(calendar, yearMonth).
|
||||
auto day_from_calendar = TRY(calendar_days_in_month(global_object, calendar, *year_month));
|
||||
|
||||
// b. Let day be ? ToPositiveInteger(dayFromCalendar).
|
||||
day = TRY(to_positive_integer(global_object, day_from_calendar));
|
||||
}
|
||||
// 11. Else,
|
||||
else {
|
||||
// a. Let day be 1.
|
||||
day = 1;
|
||||
}
|
||||
|
||||
// 12. Perform ! CreateDataPropertyOrThrow(fields, "day", day).
|
||||
MUST(fields->create_data_property_or_throw(vm.names.day, Value(day)));
|
||||
|
||||
// 13. Let date be ? CalendarDateFromFields(calendar, fields, undefined).
|
||||
auto* date = TRY(calendar_date_from_fields(global_object, calendar, *fields, nullptr));
|
||||
|
||||
// 14. Let durationToAdd be ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0).
|
||||
auto* duration_to_add = MUST(create_temporal_duration(global_object, duration.years, duration.months, duration.weeks, balance_result.days, 0, 0, 0, 0, 0, 0));
|
||||
|
||||
// 15. Let optionsCopy be OrdinaryObjectCreate(%Object.prototype%).
|
||||
auto* options_copy = Object::create(global_object, global_object.object_prototype());
|
||||
|
||||
// 16. Let entries be ? EnumerableOwnPropertyNames(options, key+value).
|
||||
auto entries = TRY(options->enumerable_own_property_names(Object::PropertyKind::KeyAndValue));
|
||||
|
||||
// 17. For each element nextEntry of entries, do
|
||||
for (auto& next_entry : entries) {
|
||||
auto key = MUST(next_entry.as_array().get_without_side_effects(0).to_property_key(global_object));
|
||||
auto value = next_entry.as_array().get_without_side_effects(1);
|
||||
|
||||
// a. Perform ! CreateDataPropertyOrThrow(optionsCopy, nextEntry[0], nextEntry[1]).
|
||||
MUST(options_copy->create_data_property_or_throw(key, value));
|
||||
}
|
||||
|
||||
// 18. Let addedDate be ? CalendarDateAdd(calendar, date, durationToAdd, options).
|
||||
auto* added_date = TRY(calendar_date_add(global_object, calendar, date, *duration_to_add, options));
|
||||
|
||||
// 19. Let addedDateFields be ? PrepareTemporalFields(addedDate, fieldNames, «»).
|
||||
auto* added_date_fields = TRY(prepare_temporal_fields(global_object, *added_date, field_names, {}));
|
||||
|
||||
// 20. Return ? CalendarYearMonthFromFields(calendar, addedDateFields, optionsCopy).
|
||||
return TRY(calendar_year_month_from_fields(global_object, calendar, *added_date_fields, options_copy));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromPlainYearMonth(add, yearMonth, temporalDurationLike, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_plain_year_month(global_object, ArithmeticOperation::Add, *year_month, temporal_duration_like, options));
|
||||
}
|
||||
|
||||
// 9.3.13 Temporal.PlainYearMonth.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.subtract
|
||||
JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::subtract)
|
||||
{
|
||||
auto temporal_duration_like = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let yearMonth be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
|
||||
auto* year_month = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration_record = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set duration to ! CreateNegatedTemporalDuration(duration).
|
||||
// FIXME: According to the spec CreateNegatedTemporalDuration takes a Temporal.Duration object,
|
||||
// not a record, so we have to do some trickery. If they want to accept anything that has
|
||||
// the required internal slots, this should be updated in the AO's description.
|
||||
auto* duration = MUST(create_temporal_duration(global_object, duration_record.years, duration_record.months, duration_record.weeks, duration_record.days, duration_record.hours, duration_record.minutes, duration_record.seconds, duration_record.milliseconds, duration_record.microseconds, duration_record.nanoseconds));
|
||||
duration = create_negated_temporal_duration(global_object, *duration);
|
||||
|
||||
// 5. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
|
||||
auto balance_result = TRY(balance_duration(global_object, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger::create_from((i64)duration->nanoseconds()), "day"sv));
|
||||
|
||||
// 6. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 7. Let calendar be yearMonth.[[Calendar]].
|
||||
auto& calendar = year_month->calendar();
|
||||
|
||||
// 8. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »).
|
||||
auto field_names = TRY(calendar_fields(global_object, calendar, { "monthCode"sv, "year"sv }));
|
||||
|
||||
// 9. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»).
|
||||
auto* fields = TRY(prepare_temporal_fields(global_object, *year_month, field_names, {}));
|
||||
|
||||
// 10. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0).
|
||||
auto sign = duration_sign(duration->years(), duration->months(), duration->weeks(), balance_result.days, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
double day;
|
||||
|
||||
// 11. If sign < 0, then
|
||||
if (sign < 0) {
|
||||
// a. Let dayFromCalendar be ? CalendarDaysInMonth(calendar, yearMonth).
|
||||
auto day_from_calendar = TRY(calendar_days_in_month(global_object, calendar, *year_month));
|
||||
|
||||
// b. Let day be ? ToPositiveInteger(dayFromCalendar).
|
||||
day = TRY(to_positive_integer(global_object, day_from_calendar));
|
||||
}
|
||||
// 12. Else,
|
||||
else {
|
||||
// a. Let day be 1.
|
||||
day = 1;
|
||||
}
|
||||
|
||||
// 13. Perform ! CreateDataPropertyOrThrow(fields, "day", day).
|
||||
MUST(fields->create_data_property_or_throw(vm.names.day, Value(day)));
|
||||
|
||||
// 14. Let date be ? CalendarDateFromFields(calendar, fields, undefined).
|
||||
auto* date = TRY(calendar_date_from_fields(global_object, calendar, *fields, nullptr));
|
||||
|
||||
// 15. Let durationToAdd be ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0).
|
||||
auto* duration_to_add = MUST(create_temporal_duration(global_object, duration->years(), duration->months(), duration->weeks(), balance_result.days, 0, 0, 0, 0, 0, 0));
|
||||
|
||||
// 16. Let optionsCopy be OrdinaryObjectCreate(%Object.prototype%).
|
||||
auto* options_copy = Object::create(global_object, global_object.object_prototype());
|
||||
|
||||
// 17. Let entries be ? EnumerableOwnPropertyNames(options, key+value).
|
||||
auto entries = TRY(options->enumerable_own_property_names(Object::PropertyKind::KeyAndValue));
|
||||
|
||||
// 18. For each element nextEntry of entries, do
|
||||
for (auto& next_entry : entries) {
|
||||
auto key = MUST(next_entry.as_array().get_without_side_effects(0).to_property_key(global_object));
|
||||
auto value = next_entry.as_array().get_without_side_effects(1);
|
||||
|
||||
// a. Perform ! CreateDataPropertyOrThrow(optionsCopy, nextEntry[0], nextEntry[1]).
|
||||
MUST(options_copy->create_data_property_or_throw(key, value));
|
||||
}
|
||||
|
||||
// 19. Let addedDate be ? CalendarDateAdd(calendar, date, durationToAdd, options).
|
||||
auto* added_date = TRY(calendar_date_add(global_object, calendar, date, *duration_to_add, options));
|
||||
|
||||
// 20. Let addedDateFields be ? PrepareTemporalFields(addedDate, fieldNames, «»).
|
||||
auto* added_date_fields = TRY(prepare_temporal_fields(global_object, *added_date, field_names, {}));
|
||||
|
||||
// 21. Return ? CalendarYearMonthFromFields(calendar, addedDateFields, optionsCopy).
|
||||
return TRY(calendar_year_month_from_fields(global_object, calendar, *added_date_fields, options_copy));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromPlainYearMonth(add, yearMonth, temporalDurationLike, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_plain_year_month(global_object, ArithmeticOperation::Subtract, *year_month, temporal_duration_like, options));
|
||||
}
|
||||
|
||||
// 9.3.14 Temporal.PlainYearMonth.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.until
|
||||
|
|
|
@ -536,4 +536,29 @@ ThrowCompletionOr<NanosecondsToDaysResult> nanoseconds_to_days(GlobalObject& glo
|
|||
return NanosecondsToDaysResult { .days = days, .nanoseconds = move(nanoseconds), .day_length = fabs(day_length_ns.to_double()) };
|
||||
}
|
||||
|
||||
// 6.5.8 AddDurationToOrSubtractDurationFromZonedDateTime ( operation, zonedDateTime, temporalDurationLike, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoOrsubtractdurationfromzoneddatetime
|
||||
ThrowCompletionOr<ZonedDateTime*> add_duration_to_or_subtract_duration_from_zoned_date_time(GlobalObject& global_object, ArithmeticOperation operation, ZonedDateTime& zoned_date_time, Value temporal_duration_like, Value options_value)
|
||||
{
|
||||
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
|
||||
i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1;
|
||||
|
||||
// 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, temporal_duration_like));
|
||||
|
||||
// 3. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, options_value));
|
||||
|
||||
// 4. Let timeZone be zonedDateTime.[[TimeZone]].
|
||||
auto& time_zone = zoned_date_time.time_zone();
|
||||
|
||||
// 5. Let calendar be zonedDateTime.[[Calendar]].
|
||||
auto& calendar = zoned_date_time.calendar();
|
||||
|
||||
// 6. Let epochNanoseconds be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZone, calendar, sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]], options).
|
||||
auto* epoch_nanoseconds = TRY(add_zoned_date_time(global_object, zoned_date_time.nanoseconds(), &time_zone, calendar, sign * duration.years, sign * duration.months, sign * duration.weeks, sign * duration.days, sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds, options));
|
||||
|
||||
// 7. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
|
||||
return MUST(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, time_zone, calendar));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,5 +57,6 @@ ThrowCompletionOr<String> temporal_zoned_date_time_to_string(GlobalObject&, Zone
|
|||
ThrowCompletionOr<BigInt*> add_zoned_date_time(GlobalObject&, BigInt const& epoch_nanoseconds, Value time_zone, Object& calendar, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object* options = nullptr);
|
||||
ThrowCompletionOr<DurationRecord> difference_zoned_date_time(GlobalObject&, BigInt const& nanoseconds1, BigInt const& nanoseconds2, Object& time_zone, Object& calendar, StringView largest_unit, Object const* options = nullptr);
|
||||
ThrowCompletionOr<NanosecondsToDaysResult> nanoseconds_to_days(GlobalObject&, Crypto::SignedBigInteger nanoseconds, Value relative_to);
|
||||
ThrowCompletionOr<ZonedDateTime*> add_duration_to_or_subtract_duration_from_zoned_date_time(GlobalObject&, ArithmeticOperation, ZonedDateTime&, Value temporal_duration_like, Value options_value);
|
||||
|
||||
}
|
||||
|
|
|
@ -895,53 +895,29 @@ JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with_calendar)
|
|||
// 6.3.35 Temporal.ZonedDateTime.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.add
|
||||
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::add)
|
||||
{
|
||||
auto temporal_duration_like = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let zonedDateTime be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
|
||||
auto* zoned_date_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let timeZone be zonedDateTime.[[TimeZone]].
|
||||
auto& time_zone = zoned_date_time->time_zone();
|
||||
|
||||
// 6. Let calendar be zonedDateTime.[[Calendar]].
|
||||
auto& calendar = zoned_date_time->calendar();
|
||||
|
||||
// 7. Let epochNanoseconds be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZone, calendar, duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], options).
|
||||
auto* epoch_nanoseconds = TRY(add_zoned_date_time(global_object, zoned_date_time->nanoseconds(), &time_zone, calendar, duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds, options));
|
||||
|
||||
// 8. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
|
||||
return MUST(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, time_zone, calendar));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromZonedDateTime(add, zonedDateTime, temporalDurationLike, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_zoned_date_time(global_object, ArithmeticOperation::Add, *zoned_date_time, temporal_duration_like, options));
|
||||
}
|
||||
|
||||
// 6.3.36 Temporal.ZonedDateTime.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.subtract
|
||||
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::subtract)
|
||||
{
|
||||
auto temporal_duration_like = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let zonedDateTime be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
|
||||
auto* zoned_date_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
|
||||
auto duration = TRY(to_temporal_duration_record(global_object, vm.argument(0)));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY(get_options_object(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let timeZone be zonedDateTime.[[TimeZone]].
|
||||
auto& time_zone = zoned_date_time->time_zone();
|
||||
|
||||
// 6. Let calendar be zonedDateTime.[[Calendar]].
|
||||
auto& calendar = zoned_date_time->calendar();
|
||||
|
||||
// 7. Let epochNanoseconds be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZone, calendar, -duration.[[Years]], -duration.[[Months]], -duration.[[Weeks]], -duration.[[Days]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]], options).
|
||||
auto* epoch_nanoseconds = TRY(add_zoned_date_time(global_object, zoned_date_time->nanoseconds(), &time_zone, calendar, -duration.years, -duration.months, -duration.weeks, -duration.days, -duration.hours, -duration.minutes, -duration.seconds, -duration.milliseconds, -duration.microseconds, -duration.nanoseconds, options));
|
||||
|
||||
// 8. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
|
||||
return MUST(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, time_zone, calendar));
|
||||
// 3. Return ? AddDurationToOrSubtractDurationFromZonedDateTime(subtract, zonedDateTime, temporalDurationLike, options).
|
||||
return TRY(add_duration_to_or_subtract_duration_from_zoned_date_time(global_object, ArithmeticOperation::Subtract, *zoned_date_time, temporal_duration_like, options));
|
||||
}
|
||||
|
||||
// 6.3.37 Temporal.ZonedDateTime.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.until
|
||||
|
|
Loading…
Reference in a new issue