
This patch adds the Duration object itself, its constructor and prototype (currently empty), and three required abstract operations.
107 lines
4.9 KiB
C++
107 lines
4.9 KiB
C++
/*
|
||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||
*
|
||
* SPDX-License-Identifier: BSD-2-Clause
|
||
*/
|
||
|
||
#include <LibJS/Runtime/AbstractOperations.h>
|
||
#include <LibJS/Runtime/GlobalObject.h>
|
||
#include <LibJS/Runtime/Temporal/Duration.h>
|
||
#include <LibJS/Runtime/Temporal/DurationConstructor.h>
|
||
|
||
namespace JS::Temporal {
|
||
|
||
// 7 Temporal.Duration Objects, https://tc39.es/proposal-temporal/#sec-temporal-duration-objects
|
||
Duration::Duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object& prototype)
|
||
: Object(prototype)
|
||
, m_years(years)
|
||
, m_months(months)
|
||
, m_weeks(weeks)
|
||
, m_days(days)
|
||
, m_hours(hours)
|
||
, m_minutes(minutes)
|
||
, m_seconds(seconds)
|
||
, m_milliseconds(milliseconds)
|
||
, m_microseconds(microseconds)
|
||
, m_nanoseconds(nanoseconds)
|
||
{
|
||
}
|
||
|
||
// 7.5.3 DurationSign ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds )
|
||
i8 duration_sign(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds)
|
||
{
|
||
// 1. For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
|
||
for (auto& v : { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }) {
|
||
// a. If v < 0, return −1.
|
||
if (v < 0)
|
||
return -1;
|
||
|
||
// b. If v > 0, return 1.
|
||
if (v > 0)
|
||
return 1;
|
||
}
|
||
|
||
// 2. Return 0.
|
||
return 0;
|
||
}
|
||
|
||
// 7.5.4 IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds )
|
||
bool is_valid_duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds)
|
||
{
|
||
// 1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
|
||
auto sign = duration_sign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
|
||
|
||
// 2. For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
|
||
for (auto& v : { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }) {
|
||
// a. If v is not finite, return false.
|
||
if (!isfinite(v))
|
||
return false;
|
||
|
||
// b. If v < 0 and sign > 0, return false.
|
||
if (v < 0 && sign > 0)
|
||
return false;
|
||
|
||
// c. If v > 0 and sign < 0, return false.
|
||
if (v > 0 && sign < 0)
|
||
return false;
|
||
}
|
||
|
||
// 3. Return true.
|
||
return true;
|
||
}
|
||
|
||
// 7.5.7 CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalduration
|
||
Duration* create_temporal_duration(GlobalObject& global_object, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, FunctionObject* new_target)
|
||
{
|
||
auto& vm = global_object.vm();
|
||
|
||
// 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception.
|
||
if (!is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)) {
|
||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidDuration);
|
||
return {};
|
||
}
|
||
|
||
// 2. If newTarget is not present, set it to %Temporal.Duration%.
|
||
if (!new_target)
|
||
new_target = global_object.temporal_duration_constructor();
|
||
|
||
// 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Duration.prototype%", « [[InitializedTemporalDuration]], [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]], [[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »).
|
||
// 4. Set object.[[Years]] to years.
|
||
// 5. Set object.[[Months]] to months.
|
||
// 6. Set object.[[Weeks]] to weeks.
|
||
// 7. Set object.[[Days]] to days.
|
||
// 8. Set object.[[Hours]] to hours.
|
||
// 9. Set object.[[Minutes]] to minutes.
|
||
// 10. Set object.[[Seconds]] to seconds.
|
||
// 11. Set object.[[Milliseconds]] to milliseconds.
|
||
// 12. Set object.[[Microseconds]] to microseconds.
|
||
// 13. Set object.[[Nanoseconds]] to nanoseconds.
|
||
auto* object = ordinary_create_from_constructor<Duration>(global_object, *new_target, &GlobalObject::temporal_duration_prototype, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
|
||
if (vm.exception())
|
||
return {};
|
||
|
||
// 14. Return object.
|
||
return object;
|
||
}
|
||
|
||
}
|