mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Implement Temporal.Duration.{ add, subtract, with, toLocalString, toJSON }
Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
7135cbaefe
commit
8d140c3c0f
9 changed files with 369 additions and 304 deletions
|
|
@ -87,12 +87,60 @@ static Value builtinTemporalDurationToString(ExecutionState& state, Value thisVa
|
|||
return duration->toString(state, argc ? argv[0] : Value());
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationToJSON(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION2(duration, toJSON);
|
||||
return duration->toString(state, Value());
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION2(duration, toLocaleString);
|
||||
return duration->toString(state, Value());
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "can't convert Duration to primitive type");
|
||||
return Value();
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationNegated(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION(duration, Negated);
|
||||
return new TemporalDurationObject(state, TemporalDurationObject::createNegatedTemporalDuration(duration->duration()));
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationAbs(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION2(duration, abs);
|
||||
|
||||
auto newDuration = duration->duration();
|
||||
for (auto& n : newDuration) {
|
||||
n = std::abs(n);
|
||||
}
|
||||
|
||||
return new TemporalDurationObject(state, newDuration);
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationWith(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION2(duration, with);
|
||||
return duration->with(state, argv[0]);
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION2(duration, add);
|
||||
return new TemporalDurationObject(state, duration->addDurations(state, TemporalDurationObject::AddDurationsOperation::Add, argv[0]));
|
||||
}
|
||||
|
||||
static Value builtinTemporalDurationSubtract(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
RESOLVE_THIS_BINDING_TO_DURATION(duration, Subtract);
|
||||
return new TemporalDurationObject(state, duration->addDurations(state, TemporalDurationObject::AddDurationsOperation::Subtract, argv[0]));
|
||||
}
|
||||
|
||||
static Value builtinTemporalInstantConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
// If NewTarget is undefined, throw a TypeError exception.
|
||||
|
|
@ -429,8 +477,15 @@ void GlobalObject::installTemporal(ExecutionState& state)
|
|||
ObjectPropertyDescriptor(Value(strings->lazyTemporalDotDuration().string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->toString), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinTemporalDurationToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->toJSON), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toJSON, builtinTemporalDurationToJSON, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->toLocaleString), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleString, builtinTemporalDurationToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->valueOf), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinTemporalDurationValueOf, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyNegated()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyNegated(), builtinTemporalDurationNegated, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->abs), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->abs, builtinTemporalDurationAbs, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->with), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->with, builtinTemporalDurationWith, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->add), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->add, builtinTemporalDurationAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_temporalDurationPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySubtract()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySubtract(), builtinTemporalDurationSubtract, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
|
||||
#define DEFINE_DURATION_PROTOTYPE_GETTER_PROPERTY(name, stringName, Name) \
|
||||
|
|
|
|||
|
|
@ -367,122 +367,6 @@ Object* IntlDurationFormatObject::resolvedOptions(ExecutionState& state)
|
|||
return options;
|
||||
}
|
||||
|
||||
static bool isValidDurationWork(double v, int& sign)
|
||||
{
|
||||
// If 𝔽(v) is not finite, return false.
|
||||
if (!std::isfinite(v)) {
|
||||
return false;
|
||||
}
|
||||
// If v < 0, then
|
||||
if (v < 0) {
|
||||
// If sign > 0, return false.
|
||||
if (sign > 0) {
|
||||
return false;
|
||||
}
|
||||
// Set sign to -1.
|
||||
sign = -1;
|
||||
} else if (v > 0) {
|
||||
// Else if v > 0, then
|
||||
// If sign < 0, return false.
|
||||
if (sign < 0) {
|
||||
return false;
|
||||
}
|
||||
// Set sign to 1.
|
||||
sign = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static BigIntData totalNanoseconds(const DurationRecord& record)
|
||||
{
|
||||
BigIntData resultNs;
|
||||
constexpr int64_t nanoMultiplier = 1000000000ULL;
|
||||
constexpr int64_t milliMultiplier = 1000000ULL;
|
||||
constexpr int64_t microMultiplier = 1000ULL;
|
||||
|
||||
{
|
||||
BigIntData s(record.days());
|
||||
s = s.multiply(86400);
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.hours());
|
||||
s = s.multiply(3600);
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.minutes());
|
||||
s = s.multiply(60);
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.seconds());
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.milliseconds());
|
||||
s = s.multiply(milliMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.microseconds());
|
||||
s = s.multiply(microMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.nanoseconds());
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
|
||||
return resultNs;
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma402/#sec-isvalidduration
|
||||
static bool isValidDuration(const DurationRecord& record)
|
||||
{
|
||||
// Let sign be 0.
|
||||
int sign = 0;
|
||||
// For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
|
||||
for (double v : record) {
|
||||
if (!isValidDurationWork(v, sign)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If abs(years) ≥ 2**32, return false.
|
||||
if (std::abs(record.years()) >= (1ULL << 32)) {
|
||||
return false;
|
||||
}
|
||||
// If abs(months) ≥ 2**32, return false.
|
||||
if (std::abs(record.months()) >= (1ULL << 32)) {
|
||||
return false;
|
||||
}
|
||||
// If abs(weeks) ≥ 2**32, return false.
|
||||
if (std::abs(record.weeks()) >= (1ULL << 32)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let normalizedSeconds be days × 86,400 + hours × 3600 + minutes × 60 + seconds + ℝ(𝔽(milliseconds)) × 10**-3 + ℝ(𝔽(microseconds)) × 10**-6 + ℝ(𝔽(nanoseconds)) × 10**-9.
|
||||
// NOTE: The above step cannot be implemented directly using floating-point arithmetic. Multiplying by 10**-3, 10**-6, and 10**-9 respectively may be imprecise when milliseconds, microseconds, or nanoseconds is an unsafe integer. This multiplication can be implemented in C++ with an implementation of std::remquo() with sufficient bits in the quotient. String manipulation will also give an exact result, since the multiplication is by a power of 10.
|
||||
BigIntData normalizedNanoSeconds = totalNanoseconds(record);
|
||||
// If abs(normalizedSeconds) ≥ 2**53, return false.
|
||||
BigIntData limit(int64_t(1ULL << 53));
|
||||
limit = limit.multiply(1000000000ULL);
|
||||
if (normalizedNanoSeconds.greaterThanEqual(limit)) {
|
||||
return false;
|
||||
}
|
||||
limit = limit.multiply(-1);
|
||||
if (normalizedNanoSeconds.lessThanEqual(limit)) {
|
||||
return false;
|
||||
}
|
||||
// Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
static DurationRecord toDurationRecord(ExecutionState& state, const Value& input)
|
||||
{
|
||||
// If input is not an Object, then
|
||||
|
|
@ -541,7 +425,7 @@ static DurationRecord toDurationRecord(ExecutionState& state, const Value& input
|
|||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Invalid input for ToDurationRecord");
|
||||
}
|
||||
// If IsValidDuration( result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]) is false, then
|
||||
if (!isValidDuration(result)) {
|
||||
if (!result.isValid()) {
|
||||
// Throw a RangeError exception.
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "Invalid input for ToDurationRecord");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,11 +234,11 @@ static void appendInteger(StringBuilder& builder, Int128 value)
|
|||
|
||||
String* TemporalDurationObject::temporalDurationToString(ISO8601::Duration duration, Value precision)
|
||||
{
|
||||
auto balancedMicroseconds = static_cast<Int128>(duration.microseconds()) + static_cast<Int128>(std::trunc(duration.nanoseconds() / 1000));
|
||||
auto balancedNanoseconds = static_cast<Int128>(duration.nanoseconds()) % 1000;
|
||||
auto balancedMilliseconds = static_cast<Int128>(duration.milliseconds()) + (balancedMicroseconds / 1000);
|
||||
auto balancedMicroseconds = static_cast<Int128>(static_cast<int64_t>(duration.microseconds())) + static_cast<Int128>(static_cast<int64_t>(std::trunc(duration.nanoseconds() / 1000)));
|
||||
auto balancedNanoseconds = static_cast<Int128>(static_cast<int64_t>(duration.nanoseconds())) % 1000;
|
||||
auto balancedMilliseconds = static_cast<Int128>(static_cast<int64_t>(duration.milliseconds())) + (balancedMicroseconds / 1000);
|
||||
balancedMicroseconds = balancedMicroseconds % 1000;
|
||||
auto balancedSeconds = static_cast<Int128>(duration.seconds()) + (balancedMilliseconds / 1000);
|
||||
auto balancedSeconds = static_cast<Int128>(static_cast<int64_t>(duration.seconds())) + (balancedMilliseconds / 1000);
|
||||
balancedMilliseconds = balancedMilliseconds % 1000;
|
||||
|
||||
StringBuilder builder;
|
||||
|
|
@ -335,6 +335,104 @@ String* TemporalDurationObject::toString(ExecutionState& state, Value options)
|
|||
return temporalDurationToString(roundedDuration, precision.precision);
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.with
|
||||
TemporalDurationObject* TemporalDurationObject::with(ExecutionState& state, Value temporalDurationLike)
|
||||
{
|
||||
// Let duration be the this value.
|
||||
// Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
// Let temporalDurationLike be ? ToTemporalPartialDurationRecord(temporalDurationLike).
|
||||
auto temporalPartialDuration = toTemporalPartialDurationRecord(state, temporalDurationLike);
|
||||
|
||||
// Step 4 to 23
|
||||
ISO8601::Duration newDuration;
|
||||
size_t idx = 0;
|
||||
for (auto n : temporalPartialDuration) {
|
||||
if (n) {
|
||||
newDuration[idx] = n.value();
|
||||
} else {
|
||||
newDuration[idx] = m_duration[idx];
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
// Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
|
||||
if (!newDuration.isValid()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "Invalid duration value");
|
||||
}
|
||||
|
||||
return new TemporalDurationObject(state, newDuration);
|
||||
}
|
||||
|
||||
ISO8601::PartialDuration TemporalDurationObject::toTemporalPartialDurationRecord(ExecutionState& state, Value temporalDurationLike)
|
||||
{
|
||||
// If temporalDurationLike is not an Object, then
|
||||
if (!temporalDurationLike.isObject()) {
|
||||
// Throw a TypeError exception.
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "toTemporalPartialDurationRecord needs Object");
|
||||
}
|
||||
|
||||
// Let result be a new partial Duration Record with each field set to undefined.
|
||||
ISO8601::PartialDuration result;
|
||||
// NOTE: The following steps read properties and perform independent validation in alphabetical order.
|
||||
// Let days be ? Get(temporalDurationLike, "days").
|
||||
// If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days).
|
||||
// Let hours be ? Get(temporalDurationLike, "hours").
|
||||
// If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours).
|
||||
// Let microseconds be ? Get(temporalDurationLike, "microseconds").
|
||||
// If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds).
|
||||
// Let milliseconds be ? Get(temporalDurationLike, "milliseconds").
|
||||
// If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds).
|
||||
// Let minutes be ? Get(temporalDurationLike, "minutes").
|
||||
// If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes).
|
||||
// Let months be ? Get(temporalDurationLike, "months").
|
||||
// If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months).
|
||||
// Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds").
|
||||
// If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds).
|
||||
// Let seconds be ? Get(temporalDurationLike, "seconds").
|
||||
// If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds).
|
||||
// Let weeks be ? Get(temporalDurationLike, "weeks").
|
||||
// If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks).
|
||||
// Let years be ? Get(temporalDurationLike, "years").
|
||||
// If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years).
|
||||
|
||||
Object* s = temporalDurationLike.asObject();
|
||||
Value v;
|
||||
#define SET_ONCE(name) \
|
||||
v = s->get(state, ObjectPropertyName(state.context()->staticStrings().lazy##name())).value(state, s); \
|
||||
if (!v.isUndefined()) { \
|
||||
result.set##name(v.toIntegerIfIntergral(state)); \
|
||||
}
|
||||
|
||||
SET_ONCE(Days);
|
||||
SET_ONCE(Hours);
|
||||
SET_ONCE(Microseconds);
|
||||
SET_ONCE(Milliseconds);
|
||||
SET_ONCE(Minutes);
|
||||
SET_ONCE(Months);
|
||||
SET_ONCE(Nanoseconds);
|
||||
SET_ONCE(Seconds);
|
||||
SET_ONCE(Weeks);
|
||||
SET_ONCE(Years);
|
||||
|
||||
#undef SET_ONCE
|
||||
|
||||
// If years is undefined, and months is undefined, and weeks is undefined, and days is undefined, and hours is undefined, and minutes is undefined, and seconds is undefined, and milliseconds is undefined, and microseconds is undefined, and nanoseconds is undefined, throw a TypeError exception.
|
||||
bool allUndefined = true;
|
||||
for (const auto& s : result) {
|
||||
if (s.hasValue()) {
|
||||
allUndefined = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allUndefined) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "toTemporalPartialDurationRecord needs at least one duration value");
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
ISO8601::InternalDuration TemporalDurationObject::toInternalDurationRecord(ISO8601::Duration duration)
|
||||
{
|
||||
ISO8601::Duration dateDuration{
|
||||
|
|
@ -357,6 +455,54 @@ Int128 TemporalDurationObject::add24HourDaysToTimeDuration(ExecutionState& state
|
|||
return result;
|
||||
}
|
||||
|
||||
Int128 TemporalDurationObject::addTimeDuration(ExecutionState& state, Int128 one, Int128 two)
|
||||
{
|
||||
// Let result be one + two.
|
||||
auto result = one + two;
|
||||
// If abs(result) > maxTimeDuration, throw a RangeError exception.
|
||||
if (std::abs(result) > ISO8601::InternalDuration::maxTimeDuration) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "Total time in duration is out of range");
|
||||
return {};
|
||||
}
|
||||
// Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
ISO8601::Duration TemporalDurationObject::addDurations(ExecutionState& state, AddDurationsOperation operation, Value otherInput)
|
||||
{
|
||||
// Set other to ? ToTemporalDuration(other).
|
||||
auto otherDurationObject = Temporal::toTemporalDuration(state, otherInput);
|
||||
ISO8601::Duration other = otherDurationObject->duration();
|
||||
// If operation is subtract, set other to CreateNegatedTemporalDuration(other).
|
||||
if (operation == AddDurationsOperation::Subtract) {
|
||||
other = createNegatedTemporalDuration(otherDurationObject->duration());
|
||||
}
|
||||
// Let largestUnit1 be DefaultTemporalLargestUnit(duration).
|
||||
auto largestUnit1 = m_duration.defaultTemporalLargestUnit();
|
||||
// Let largestUnit2 be DefaultTemporalLargestUnit(other).
|
||||
auto largestUnit2 = other.defaultTemporalLargestUnit();
|
||||
// Let largestUnit be LargerOfTwoTemporalUnits(largestUnit1, largestUnit2).
|
||||
auto largestUnit = Temporal::largerOfTwoTemporalUnits(largestUnit1, largestUnit2);
|
||||
// If IsCalendarUnit(largestUnit) is true, throw a RangeError exception.
|
||||
if (Temporal::isCalendarUnit(largestUnit)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "can not add/subtract Calendar Unit duration");
|
||||
}
|
||||
// Let d1 be ToInternalDurationRecordWith24HourDays(duration).
|
||||
auto d1 = toInternalDurationRecordWith24HourDays(state, m_duration);
|
||||
// Let d2 be ToInternalDurationRecordWith24HourDays(other).
|
||||
auto d2 = toInternalDurationRecordWith24HourDays(state, other);
|
||||
// Let timeResult be ? AddTimeDuration(d1.[[Time]], d2.[[Time]]).
|
||||
auto timeResult = addTimeDuration(state, d1.time(), d2.time());
|
||||
// Let result be CombineDateAndTimeDuration(ZeroDateDuration(), timeResult).
|
||||
auto result = ISO8601::InternalDuration::combineDateAndTimeDuration({}, timeResult);
|
||||
// Return ? TemporalDurationFromInternal(result, largestUnit).
|
||||
auto resultDuration = temporalDurationFromInternal(state, result, largestUnit);
|
||||
if (!resultDuration.isValid()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "Result duration is out of range");
|
||||
}
|
||||
return resultDuration;
|
||||
}
|
||||
|
||||
ISO8601::InternalDuration TemporalDurationObject::toInternalDurationRecordWith24HourDays(ExecutionState& state, ISO8601::Duration duration)
|
||||
{
|
||||
// Let timeDuration be TimeDurationFromComponents(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
|
||||
|
|
|
|||
|
|
@ -80,6 +80,12 @@ public:
|
|||
String* toString(ExecutionState& state, Value options);
|
||||
static String* temporalDurationToString(ISO8601::Duration duration, Value precision);
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.with
|
||||
TemporalDurationObject* with(ExecutionState& state, Value temporalDurationLike);
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-totemporalpartialdurationrecord
|
||||
static ISO8601::PartialDuration toTemporalPartialDurationRecord(ExecutionState& state, Value temporalDurationLike);
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-tointernaldurationrecord
|
||||
static ISO8601::InternalDuration toInternalDurationRecord(ISO8601::Duration duration);
|
||||
|
||||
|
|
@ -98,6 +104,16 @@ public:
|
|||
// https://tc39.es/proposal-temporal/#sec-temporal-add24hourdaystonormalizedtimeduration
|
||||
static Int128 add24HourDaysToTimeDuration(ExecutionState& state, Int128 d, double days);
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-addtimeduration
|
||||
static Int128 addTimeDuration(ExecutionState& state, Int128 one, Int128 two);
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-adddurations
|
||||
enum class AddDurationsOperation {
|
||||
Add,
|
||||
Subtract
|
||||
};
|
||||
ISO8601::Duration addDurations(ExecutionState& state, AddDurationsOperation operation, Value other);
|
||||
|
||||
private:
|
||||
ISO8601::Duration m_duration;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ TemporalDurationObject* Temporal::toTemporalDuration(ExecutionState& state, cons
|
|||
|
||||
// Let result be a new Partial Duration Record with each field set to 0.
|
||||
// Let partial be ? ToTemporalPartialDurationRecord(item).
|
||||
auto partial = ISO8601::PartialDuration::toTemporalPartialDurationRecord(state, item);
|
||||
auto partial = TemporalDurationObject::toTemporalPartialDurationRecord(state, item);
|
||||
// If partial.[[Years]] is not undefined, set result.[[Years]] to partial.[[Years]].
|
||||
// If partial.[[Months]] is not undefined, set result.[[Months]] to partial.[[Months]].
|
||||
// If partial.[[Weeks]] is not undefined, set result.[[Weeks]] to partial.[[Weeks]].
|
||||
|
|
@ -480,6 +480,10 @@ TemporalDurationObject* Temporal::toTemporalDuration(ExecutionState& state, cons
|
|||
idx++;
|
||||
}
|
||||
|
||||
if (!duration.isValid()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, msg);
|
||||
}
|
||||
|
||||
// Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return new TemporalDurationObject(state, duration);
|
||||
}
|
||||
|
|
@ -1017,6 +1021,14 @@ Int128 Temporal::timeDurationFromEpochNanosecondsDifference(Int128 one, Int128 t
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Temporal::isCalendarUnit(ISO8601::DateTimeUnit unit)
|
||||
{
|
||||
if (unit == ISO8601::DateTimeUnit::Year || unit == ISO8601::DateTimeUnit::Month || unit == ISO8601::DateTimeUnit::Week) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TemporalObject::TemporalObject(ExecutionState& state)
|
||||
: TemporalObject(state, state.context()->globalObject()->objectPrototype())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -372,6 +372,9 @@ public:
|
|||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-timedurationfromepochnanosecondsdifference
|
||||
static Int128 timeDurationFromEpochNanosecondsDifference(Int128 one, Int128 two);
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-iscalendarunit
|
||||
static bool isCalendarUnit(ISO8601::DateTimeUnit unit);
|
||||
};
|
||||
|
||||
class TemporalObject : public DerivedObject {
|
||||
|
|
|
|||
|
|
@ -339,6 +339,124 @@ Optional<Duration> Duration::parseDurationString(String* input)
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool isValidDurationWork(double v, int& sign)
|
||||
{
|
||||
// If 𝔽(v) is not finite, return false.
|
||||
if (!std::isfinite(v)) {
|
||||
return false;
|
||||
}
|
||||
// If v < 0, then
|
||||
if (v < 0) {
|
||||
// If sign > 0, return false.
|
||||
if (sign > 0) {
|
||||
return false;
|
||||
}
|
||||
// Set sign to -1.
|
||||
sign = -1;
|
||||
} else if (v > 0) {
|
||||
// Else if v > 0, then
|
||||
// If sign < 0, return false.
|
||||
if (sign < 0) {
|
||||
return false;
|
||||
}
|
||||
// Set sign to 1.
|
||||
sign = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static BigIntData totalDateTimeNanoseconds(const Duration& record)
|
||||
{
|
||||
BigIntData resultNs;
|
||||
constexpr int64_t nanoMultiplier = 1000000000ULL;
|
||||
constexpr int64_t milliMultiplier = 1000000ULL;
|
||||
constexpr int64_t microMultiplier = 1000ULL;
|
||||
|
||||
{
|
||||
BigIntData s(record.days());
|
||||
s = s.multiply(86400);
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.hours());
|
||||
s = s.multiply(3600);
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.minutes());
|
||||
s = s.multiply(60);
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.seconds());
|
||||
s = s.multiply(nanoMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.milliseconds());
|
||||
s = s.multiply(milliMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.microseconds());
|
||||
s = s.multiply(microMultiplier);
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
{
|
||||
BigIntData s(record.nanoseconds());
|
||||
resultNs = resultNs.addition(s);
|
||||
}
|
||||
|
||||
return resultNs;
|
||||
}
|
||||
|
||||
|
||||
// https://tc39.es/ecma402/#sec-isvalidduration
|
||||
bool Duration::isValid() const
|
||||
{
|
||||
// Let sign be 0.
|
||||
int sign = 0;
|
||||
// For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
|
||||
for (double v : m_data) {
|
||||
if (!isValidDurationWork(v, sign)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If abs(years) ≥ 2**32, return false.
|
||||
if (std::abs(years()) >= (1ULL << 32)) {
|
||||
return false;
|
||||
}
|
||||
// If abs(months) ≥ 2**32, return false.
|
||||
if (std::abs(months()) >= (1ULL << 32)) {
|
||||
return false;
|
||||
}
|
||||
// If abs(weeks) ≥ 2**32, return false.
|
||||
if (std::abs(weeks()) >= (1ULL << 32)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let normalizedSeconds be days × 86,400 + hours × 3600 + minutes × 60 + seconds + ℝ(𝔽(milliseconds)) × 10**-3 + ℝ(𝔽(microseconds)) × 10**-6 + ℝ(𝔽(nanoseconds)) × 10**-9.
|
||||
// NOTE: The above step cannot be implemented directly using floating-point arithmetic. Multiplying by 10**-3, 10**-6, and 10**-9 respectively may be imprecise when milliseconds, microseconds, or nanoseconds is an unsafe integer. This multiplication can be implemented in C++ with an implementation of std::remquo() with sufficient bits in the quotient. String manipulation will also give an exact result, since the multiplication is by a power of 10.
|
||||
BigIntData normalizedNanoSeconds = totalDateTimeNanoseconds(*this);
|
||||
// If abs(normalizedSeconds) ≥ 2**53, return false.
|
||||
BigIntData limit(int64_t(1ULL << 53));
|
||||
limit = limit.multiply(1000000000ULL);
|
||||
if (normalizedNanoSeconds.greaterThanEqual(limit)) {
|
||||
return false;
|
||||
}
|
||||
limit = limit.multiply(-1);
|
||||
if (normalizedNanoSeconds.lessThanEqual(limit)) {
|
||||
return false;
|
||||
}
|
||||
// Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
String* Duration::typeName(ExecutionState& state, ISO8601::DateTimeUnit t)
|
||||
{
|
||||
switch (t) {
|
||||
|
|
@ -367,116 +485,46 @@ Int128 Duration::totalNanoseconds(ISO8601::DateTimeUnit unit) const
|
|||
constexpr int64_t microMultiplier = 1000ULL;
|
||||
|
||||
if (unit <= ISO8601::DateTimeUnit::Day) {
|
||||
Int128 s(days());
|
||||
Int128 s((int64_t)days());
|
||||
s *= 86400;
|
||||
s *= nanoMultiplier;
|
||||
resultNs += s;
|
||||
}
|
||||
if (unit <= ISO8601::DateTimeUnit::Hour) {
|
||||
Int128 s(hours());
|
||||
Int128 s((int64_t)hours());
|
||||
s *= 3600;
|
||||
s *= nanoMultiplier;
|
||||
resultNs += s;
|
||||
}
|
||||
if (unit <= ISO8601::DateTimeUnit::Minute) {
|
||||
Int128 s(minutes());
|
||||
Int128 s((int64_t)minutes());
|
||||
s *= 60;
|
||||
s *= nanoMultiplier;
|
||||
resultNs += s;
|
||||
}
|
||||
if (unit <= ISO8601::DateTimeUnit::Second) {
|
||||
Int128 s(seconds());
|
||||
Int128 s((int64_t)seconds());
|
||||
s *= nanoMultiplier;
|
||||
resultNs += s;
|
||||
}
|
||||
if (unit <= ISO8601::DateTimeUnit::Millisecond) {
|
||||
Int128 s(milliseconds());
|
||||
Int128 s((int64_t)milliseconds());
|
||||
s *= milliMultiplier;
|
||||
resultNs += s;
|
||||
}
|
||||
if (unit <= ISO8601::DateTimeUnit::Microsecond) {
|
||||
Int128 s(microseconds());
|
||||
Int128 s((int64_t)microseconds());
|
||||
s *= microMultiplier;
|
||||
resultNs += s;
|
||||
}
|
||||
if (unit <= ISO8601::DateTimeUnit::Nanosecond) {
|
||||
Int128 s(nanoseconds());
|
||||
Int128 s((int64_t)nanoseconds());
|
||||
resultNs += s;
|
||||
}
|
||||
|
||||
return resultNs;
|
||||
}
|
||||
|
||||
PartialDuration PartialDuration::toTemporalPartialDurationRecord(ExecutionState& state, const Value& temporalDurationLike)
|
||||
{
|
||||
// If temporalDurationLike is not an Object, then
|
||||
if (!temporalDurationLike.isObject()) {
|
||||
// Throw a TypeError exception.
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "toTemporalPartialDurationRecord needs Object");
|
||||
}
|
||||
|
||||
// Let result be a new partial Duration Record with each field set to undefined.
|
||||
PartialDuration result;
|
||||
// NOTE: The following steps read properties and perform independent validation in alphabetical order.
|
||||
// Let days be ? Get(temporalDurationLike, "days").
|
||||
// If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days).
|
||||
// Let hours be ? Get(temporalDurationLike, "hours").
|
||||
// If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours).
|
||||
// Let microseconds be ? Get(temporalDurationLike, "microseconds").
|
||||
// If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds).
|
||||
// Let milliseconds be ? Get(temporalDurationLike, "milliseconds").
|
||||
// If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds).
|
||||
// Let minutes be ? Get(temporalDurationLike, "minutes").
|
||||
// If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes).
|
||||
// Let months be ? Get(temporalDurationLike, "months").
|
||||
// If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months).
|
||||
// Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds").
|
||||
// If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds).
|
||||
// Let seconds be ? Get(temporalDurationLike, "seconds").
|
||||
// If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds).
|
||||
// Let weeks be ? Get(temporalDurationLike, "weeks").
|
||||
// If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks).
|
||||
// Let years be ? Get(temporalDurationLike, "years").
|
||||
// If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years).
|
||||
|
||||
Object* s = temporalDurationLike.asObject();
|
||||
Value v;
|
||||
#define SET_ONCE(name) \
|
||||
v = s->get(state, ObjectPropertyName(state.context()->staticStrings().lazy##name())).value(state, s); \
|
||||
if (!v.isUndefined()) { \
|
||||
result.set##name(v.toIntegerIfIntergral(state)); \
|
||||
}
|
||||
|
||||
SET_ONCE(Days);
|
||||
SET_ONCE(Hours);
|
||||
SET_ONCE(Microseconds);
|
||||
SET_ONCE(Milliseconds);
|
||||
SET_ONCE(Minutes);
|
||||
SET_ONCE(Months);
|
||||
SET_ONCE(Nanoseconds);
|
||||
SET_ONCE(Seconds);
|
||||
SET_ONCE(Weeks);
|
||||
SET_ONCE(Years);
|
||||
|
||||
#undef SET_ONCE
|
||||
|
||||
// If years is undefined, and months is undefined, and weeks is undefined, and days is undefined, and hours is undefined, and minutes is undefined, and seconds is undefined, and milliseconds is undefined, and microseconds is undefined, and nanoseconds is undefined, throw a TypeError exception.
|
||||
bool allUndefined = true;
|
||||
for (const auto& s : result) {
|
||||
if (s.hasValue()) {
|
||||
allUndefined = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allUndefined) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "toTemporalPartialDurationRecord needs at least one duration value");
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool canBeRFC9557Annotation(const ParserString& buffer)
|
||||
{
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-parseisodatetime
|
||||
|
|
|
|||
|
|
@ -225,6 +225,9 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-isvalidduration
|
||||
bool isValid() const;
|
||||
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-defaulttemporallargestunit
|
||||
DateTimeUnit defaultTemporalLargestUnit() const
|
||||
{
|
||||
|
|
@ -261,6 +264,9 @@ public:
|
|||
return operator[](static_cast<size_t>(idx));
|
||||
}
|
||||
|
||||
std::array<double, 10>::iterator begin() { return m_data.begin(); }
|
||||
std::array<double, 10>::iterator end() { return m_data.end(); }
|
||||
|
||||
std::array<double, 10>::const_iterator begin() const { return m_data.begin(); }
|
||||
std::array<double, 10>::const_iterator end() const { return m_data.end(); }
|
||||
|
||||
|
|
@ -279,9 +285,6 @@ class PartialDuration {
|
|||
std::array<Optional<double>, 10> m_data;
|
||||
|
||||
public:
|
||||
// https://tc39.es/proposal-temporal/#sec-temporal-totemporalpartialdurationrecord
|
||||
static PartialDuration toTemporalPartialDurationRecord(ExecutionState& state, const Value& temporalDurationLike);
|
||||
|
||||
Optional<double> operator[](size_t idx) const
|
||||
{
|
||||
return m_data[static_cast<unsigned>(idx)];
|
||||
|
|
|
|||
|
|
@ -182,54 +182,14 @@
|
|||
<test id="built-ins/Temporal/Duration/from/argument-duration-max"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/from/argument-duration-out-of-range"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/from/argument-duration-precision-exact-numerical-values"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/from/argument-object-invalid"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/from/argument-string-is-infinity"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/from/infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/from/negative-inifinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/large-number"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/max"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/mixed"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/negative-infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/out-of-range"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/basic"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/builtin"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/length"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/name"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/new-object"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/not-a-constructor"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/abs/subclassing-ignored"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-duration-max"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-duration-out-of-range"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-duration-precision-exact-numerical-values"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-mixed-sign"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-not-object"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-string"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-string-fractional-units-rounding-mode"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/argument-string-negative-fractional-units"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/balance-negative-result"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/balance-negative-time-units"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/basic"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/builtin"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/length"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/name"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/nanoseconds-is-number-max-safe-integer"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/negative-infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/no-calendar-units"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/non-integer-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/not-a-constructor"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/order-of-operations"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/precision-exact-mathematical-values"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/precision-no-floating-point-loss"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/result-out-of-range-1"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/result-out-of-range-2"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/result-out-of-range-3"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/add/subclassing-ignored"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/round/accepts-datetime-strings-for-relative-to"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/round/balance-negative-result"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/round/balance-subseconds"><reason>TODO</reason></test>
|
||||
|
|
@ -338,47 +298,6 @@
|
|||
<test id="built-ins/Temporal/Duration/prototype/round/valid-increments"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/round/year-zero"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-duration-max"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-duration-out-of-range"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-duration-precision-exact-numerical-values"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-mixed-sign"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-not-object"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-string"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-string-fractional-units-rounding-mode"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/argument-string-negative-fractional-units"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/balance-negative-result"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/balance-negative-time-units"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/basic"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/builtin"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/length"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/name"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/nanoseconds-is-number-max-safe-integer"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/negative-infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/no-calendar-units"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/non-integer-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/not-a-constructor"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/order-of-operations"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/precision-exact-mathematical-values"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/precision-no-floating-point-loss"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/result-out-of-range-1"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/result-out-of-range-2"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/result-out-of-range-3"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/subtract/subclassing-ignored"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/balance-subseconds"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/basic"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/builtin"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/length"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/max-value"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/name"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/negative-components"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/not-a-constructor"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/options"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toJSON/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toLocaleString/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toLocaleString/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toString/smallestunit-plurals-accepted"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/toString/total-of-duration-time-units-out-of-range"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/total/balance-negative-result"><reason>TODO</reason></test>
|
||||
|
|
@ -444,27 +363,6 @@
|
|||
<test id="built-ins/Temporal/Duration/prototype/total/unit-string-shorthand-string"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/total/unit-wrong-type"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/total/year-zero"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/valueOf/basic"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/valueOf/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/valueOf/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/all-negative"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/all-positive"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/argument-mixed-sign"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/branding"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/builtin"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/copy-properties-not-undefined"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/length"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/name"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/negative-infinity-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/non-integer-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/not-a-constructor"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/order-of-operations"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/partial-positive"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/sign-replace"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Duration/prototype/with/subclassing-ignored"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Instant/compare/argument-zoneddatetime"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Instant/from/argument-zoneddatetime"><reason>TODO</reason></test>
|
||||
<test id="built-ins/Temporal/Instant/prototype/equals/argument-zoneddatetime"><reason>TODO</reason></test>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue