ladybird/Userland/Libraries/LibJS/Runtime/Temporal/Duration.cpp
Linus Groh 7921d8ba91 LibJS: Start implementing Temporal.Duration
This patch adds the Duration object itself, its constructor and
prototype (currently empty), and three required abstract operations.
2021-07-16 01:07:01 +01:00

107 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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;
}
}