Implement Temporal.PlainTime.{ since, until, round, equals }

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2025-09-10 14:02:40 +09:00 committed by MuHong Byun
commit 90d8da7fe8
9 changed files with 267 additions and 284 deletions

View file

@ -349,7 +349,12 @@ static Value builtinTemporalPlainTimeConstructor(ExecutionState& state, Value th
static Value builtinTemporalPlainTimeFrom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
return TemporalPlainTimeObject::toTemporalTime(state, argv[0], argc > 1 ? argv[1] : Value());
return Temporal::toTemporalTime(state, argv[0], argc > 1 ? argv[1] : Value());
}
static Value builtinTemporalPlainTimeCompare(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
return Value(TemporalPlainTimeObject::compare(state, argv[0], argv[1]));
}
#define RESOLVE_THIS_BINDING_TO_PLAINTIME(NAME, BUILT_IN_METHOD) \
@ -400,6 +405,30 @@ static Value builtinTemporalPlainTimeSubtract(ExecutionState& state, Value thisV
return plainTime->addDurationToTime(state, TemporalPlainTimeObject::AddDurationToTimeOperation::Subtract, argv[0]);
}
static Value builtinTemporalPlainTimeSince(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINTIME(plainTime, Since);
return plainTime->since(state, argv[0], argc > 1 ? argv[1] : Value());
}
static Value builtinTemporalPlainTimeUntil(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINTIME(plainTime, Until);
return plainTime->until(state, argv[0], argc > 1 ? argv[1] : Value());
}
static Value builtinTemporalPlainTimeRound(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINTIME2(plainTime, round);
return plainTime->round(state, argv[0]);
}
static Value builtinTemporalPlainTimeEquals(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINTIME(plainTime, Equals);
return Value(plainTime->equals(state, argv[0]));
}
#define RESOLVE_THIS_BINDING_TO_PLAINDATE(NAME, BUILT_IN_METHOD) \
if (!thisValue.isObject() || !thisValue.asObject()->isTemporalPlainDateObject()) { \
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, state.context()->staticStrings().lazyCapitalPlainDate().string(), true, state.context()->staticStrings().lazy##BUILT_IN_METHOD().string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
@ -684,6 +713,7 @@ void GlobalObject::installTemporal(ExecutionState& state)
m_temporalPlainTime->setGlobalIntrinsicObject(state);
m_temporalPlainTime->directDefineOwnProperty(state, ObjectPropertyName(strings->from), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->from, builtinTemporalPlainTimeFrom, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTime->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyCompare()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyCompare(), builtinTemporalPlainTimeCompare, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype = m_temporalPlainTime->getFunctionPrototype(state).asObject();
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
@ -696,6 +726,10 @@ void GlobalObject::installTemporal(ExecutionState& state)
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->with), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->with, builtinTemporalPlainTimeWith, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->add), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->add, builtinTemporalPlainTimeAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySubtract()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySubtract(), builtinTemporalPlainTimeSubtract, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySince()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySince(), builtinTemporalPlainTimeSince, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyUntil()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyUntil(), builtinTemporalPlainTimeUntil, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->round), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->round, builtinTemporalPlainTimeRound, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyEquals()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyEquals(), builtinTemporalPlainTimeEquals, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
#define DEFINE_PLAINTIME_PROTOTYPE_GETTER_PROPERTY(name, stringName, Name) \
{ \

View file

@ -83,6 +83,8 @@ public:
// 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);

View file

@ -50,6 +50,7 @@
#include "runtime/DateObject.h"
#include "runtime/TemporalDurationObject.h"
#include "runtime/TemporalInstantObject.h"
#include "runtime/TemporalPlainTimeObject.h"
#include "intl/Intl.h"
namespace Escargot {
@ -551,6 +552,66 @@ TemporalInstantObject* Temporal::toTemporalInstant(ExecutionState& state, Value
return new TemporalInstantObject(state, state.context()->globalObject()->temporalInstantPrototype(), parsed.value().epochNanoseconds());
}
// https://tc39.es/proposal-temporal/#sec-temporal-totemporaltime
TemporalPlainTimeObject* Temporal::toTemporalTime(ExecutionState& state, Value item, Value options)
{
ISO8601::PlainTime result;
// If options is not present, set options to undefined.
// If item is an Object, then
if (item.isObject()) {
// If item has an [[InitializedTemporalTime]] internal slot, then
if (item.asObject()->isTemporalPlainTimeObject()) {
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Perform ? GetTemporalOverflowOption(resolvedOptions).
if (resolvedOptions) {
Temporal::getTemporalOverflowOption(state, resolvedOptions);
}
// Return ! CreateTemporalTime(item.[[Time]]).
return new TemporalPlainTimeObject(state, state.context()->globalObject()->temporalPlainTimePrototype(),
item.asObject()->asTemporalPlainTimeObject()->plainTime());
}
// TODO If item has an [[InitializedTemporalDateTime]] internal slot, then...
// TODO If item has an [[InitializedTemporalDateTime]] internal slot, then...
// Let result be ? ToTemporalTimeRecord(item).
auto resultRecord = TemporalPlainTimeObject::toTemporalTimeRecord(state, item, NullOption);
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
auto overflow = Temporal::getTemporalOverflowOption(state, resolvedOptions);
// Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], overflow).
result = TemporalPlainTimeObject::regulateTime(state, resultRecord.hour().value(), resultRecord.minute().value(), resultRecord.second().value(), resultRecord.millisecond().value(),
resultRecord.microsecond().value(), resultRecord.nanosecond().value(), overflow);
} else {
// Else,
// If item is not a String, throw a TypeError exception.
if (!item.isString()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "ToTemporalTime needs Object or String");
}
// Let parseResult be ? ParseISODateTime(item, « TemporalTimeString »).
auto parseDateTimeResult = ISO8601::parseCalendarDateTime(item.asString());
auto parseTimeResult = ISO8601::parseTime(item.asString());
// If ParseText(StringToCodePoints(item), AmbiguousTemporalTimeString) is a Parse Node, throw a RangeError exception.
// Assert: parseResult.[[Time]] is not start-of-day.
if (!parseTimeResult && (!parseDateTimeResult || !std::get<1>(parseDateTimeResult.value()))) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "ToTemporalTime needs ISO Time string");
}
if ((parseDateTimeResult && std::get<2>(parseDateTimeResult.value()) && std::get<2>(parseDateTimeResult.value()).value().m_z) || (parseTimeResult && std::get<1>(parseTimeResult.value()) && std::get<1>(parseTimeResult.value()).value().m_z)) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "ToTemporalTime needs ISO Time string without UTC designator");
}
// Set result to parseResult.[[Time]].
if (parseDateTimeResult && std::get<1>(parseDateTimeResult.value())) {
result = std::get<1>(parseDateTimeResult.value()).value();
} else {
result = std::get<0>(parseTimeResult.value());
}
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Perform ? GetTemporalOverflowOption(resolvedOptions).
Temporal::getTemporalOverflowOption(state, resolvedOptions);
}
return new TemporalPlainTimeObject(state, state.context()->globalObject()->temporalPlainTimePrototype(), result);
}
Optional<unsigned> Temporal::getTemporalFractionalSecondDigitsOption(ExecutionState& state, Optional<Object*> resolvedOptions)
{
constexpr auto msg = "The value you gave for GetTemporalFractionalSecondDigitsOption is invalid";
@ -1189,6 +1250,36 @@ ISO8601::Duration Temporal::balanceTime(int64_t hour, int64_t minute, int64_t se
return ISO8601::Duration({ int64_t(0), int64_t(0), int64_t(0), days, hour, minute, second, millisecond, microsecond, nanosecond });
}
Int128 Temporal::differenceTime(ISO8601::PlainTime time1, ISO8601::PlainTime time2)
{
// Let hours be time2.[[Hour]] - time1.[[Hour]].
// Let minutes be time2.[[Minute]] - time1.[[Minute]].
// Let seconds be time2.[[Second]] - time1.[[Second]].
// Let milliseconds be time2.[[Millisecond]] - time1.[[Millisecond]].
// Let microseconds be time2.[[Microsecond]] - time1.[[Microsecond]].
// Let nanoseconds be time2.[[Nanosecond]] - time1.[[Nanosecond]].
#define DEFINE_DIFF(name, capitalizedName) \
int32_t name##s = time2.name() - time1.name();
PLAIN_TIME_UNITS(DEFINE_DIFF)
#undef DEFINE_DIFF
// Let timeDuration be TimeDurationFromComponents(hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
// Assert: abs(timeDuration) < nsPerDay.
// Return timeDuration.
return timeDurationFromComponents(hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
}
Int128 Temporal::timeDurationFromComponents(double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds)
{
// Set minutes to minutes + hours × 60.
// Set seconds to seconds + minutes × 60.
// Set milliseconds to milliseconds + seconds × 1000.
// Set microseconds to microseconds + milliseconds × 1000.
// Set nanoseconds to nanoseconds + microseconds × 1000.
// Assert: abs(nanoseconds) ≤ maxTimeDuration.
// Return nanoseconds.
return ISO8601::Duration({ 0.0, 0.0, 0.0, 0.0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }).totalNanoseconds(ISO8601::DateTimeUnit::Hour);
}
TemporalObject::TemporalObject(ExecutionState& state)
: TemporalObject(state, state.context()->globalObject()->objectPrototype())
{

View file

@ -326,6 +326,9 @@ public:
// https://tc39.es/proposal-temporal/#sec-temporal-totemporalinstant
static TemporalInstantObject* toTemporalInstant(ExecutionState& state, Value item);
// https://tc39.es/proposal-temporal/#sec-temporal-totemporaltime
static TemporalPlainTimeObject* toTemporalTime(ExecutionState& state, Value item, Value optionsInput);
// https://tc39.es/proposal-temporal/#sec-temporal-gettemporalfractionalseconddigitsoption
// NullOption means AUTO
static Optional<unsigned> getTemporalFractionalSecondDigitsOption(ExecutionState& state, Optional<Object*> resolvedOptions);
@ -393,6 +396,12 @@ public:
// https://tc39.es/proposal-temporal/#sec-temporal-balancetime
static ISO8601::Duration balanceTime(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond);
static ISO8601::Duration balanceTime(int64_t hour, int64_t minute, int64_t second, int64_t millisecond, int64_t microsecond, int64_t nanosecond);
// https://tc39.es/proposal-temporal/#sec-temporal-differencetime
static Int128 differenceTime(ISO8601::PlainTime time1, ISO8601::PlainTime time2);
// https://tc39.es/proposal-temporal/#sec-temporal-timedurationfromcomponents
static Int128 timeDurationFromComponents(double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds);
};
class TemporalObject : public DerivedObject {

View file

@ -57,66 +57,6 @@ TemporalPlainTimeObject::TemporalPlainTimeObject(ExecutionState& state, Object*
{
}
TemporalPlainTimeObject* TemporalPlainTimeObject::toTemporalTime(ExecutionState& state, Value item, Value options)
{
ISO8601::PlainTime result;
// If options is not present, set options to undefined.
// If item is an Object, then
if (item.isObject()) {
// If item has an [[InitializedTemporalTime]] internal slot, then
if (item.asObject()->isTemporalPlainTimeObject()) {
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Perform ? GetTemporalOverflowOption(resolvedOptions).
if (resolvedOptions) {
Temporal::getTemporalOverflowOption(state, resolvedOptions);
}
// Return ! CreateTemporalTime(item.[[Time]]).
return new TemporalPlainTimeObject(state, state.context()->globalObject()->temporalPlainTimePrototype(),
item.asObject()->asTemporalPlainTimeObject()->plainTime());
}
// TODO If item has an [[InitializedTemporalDateTime]] internal slot, then...
// TODO If item has an [[InitializedTemporalDateTime]] internal slot, then...
// Let result be ? ToTemporalTimeRecord(item).
auto resultRecord = toTemporalTimeRecord(state, item, NullOption);
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
auto overflow = Temporal::getTemporalOverflowOption(state, resolvedOptions);
// Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], overflow).
result = regulateTime(state, resultRecord.hour().value(), resultRecord.minute().value(), resultRecord.second().value(), resultRecord.millisecond().value(),
resultRecord.microsecond().value(), resultRecord.nanosecond().value(), overflow);
} else {
// Else,
// If item is not a String, throw a TypeError exception.
if (!item.isString()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "ToTemporalTime needs Object or String");
}
// Let parseResult be ? ParseISODateTime(item, « TemporalTimeString »).
auto parseDateTimeResult = ISO8601::parseCalendarDateTime(item.asString());
auto parseTimeResult = ISO8601::parseTime(item.asString());
// If ParseText(StringToCodePoints(item), AmbiguousTemporalTimeString) is a Parse Node, throw a RangeError exception.
// Assert: parseResult.[[Time]] is not start-of-day.
if (!parseTimeResult && (!parseDateTimeResult || !std::get<1>(parseDateTimeResult.value()))) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "ToTemporalTime needs ISO Time string");
}
if ((parseDateTimeResult && std::get<2>(parseDateTimeResult.value()) && std::get<2>(parseDateTimeResult.value()).value().m_z) || (parseTimeResult && std::get<1>(parseTimeResult.value()) && std::get<1>(parseTimeResult.value()).value().m_z)) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "ToTemporalTime needs ISO Time string without UTC designator");
}
// Set result to parseResult.[[Time]].
if (parseDateTimeResult && std::get<1>(parseDateTimeResult.value())) {
result = std::get<1>(parseDateTimeResult.value()).value();
} else {
result = std::get<0>(parseTimeResult.value());
}
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Perform ? GetTemporalOverflowOption(resolvedOptions).
Temporal::getTemporalOverflowOption(state, resolvedOptions);
}
return new TemporalPlainTimeObject(state, state.context()->globalObject()->temporalPlainTimePrototype(), result);
}
ISO8601::PartialPlainTime TemporalPlainTimeObject::toTemporalTimeRecord(ExecutionState& state, Value temporalTimeLike, Optional<bool> completeness)
{
// If completeness is not present, set completeness to complete.
@ -251,6 +191,29 @@ ISO8601::Duration TemporalPlainTimeObject::roundTime(ExecutionState& state, ISO8
return ISO8601::Duration();
}
ISO8601::Duration TemporalPlainTimeObject::differenceTemporalPlainTime(ExecutionState& state, DifferenceTemporalPlainTime operation, Value otherInput, Value options)
{
// Set other to ? ToTemporalTime(other).
auto other = Temporal::toTemporalTime(state, otherInput, Value());
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Let settings be ? GetDifferenceSettings(operation, resolvedOptions, time, « », nanosecond, hour).
auto settings = Temporal::getDifferenceSettings(state, operation == DifferenceTemporalPlainTime::Since, resolvedOptions, ISO8601::DateTimeUnitCategory::Time, nullptr, 0, TemporalUnit::Nanosecond, TemporalUnit::Hour);
// Let timeDuration be DifferenceTime(temporalTime.[[Time]], other.[[Time]]).
auto timeDuration = Temporal::differenceTime(plainTime(), other->plainTime());
// Set timeDuration to ! RoundTimeDuration(timeDuration, settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
timeDuration = TemporalDurationObject::roundTimeDuration(state, timeDuration, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode);
// Let duration be CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration).
auto duration = ISO8601::InternalDuration::combineDateAndTimeDuration({}, timeDuration);
// Let result be ! TemporalDurationFromInternal(duration, settings.[[LargestUnit]]).
auto result = TemporalDurationObject::temporalDurationFromInternal(state, duration, settings.largestUnit);
// If operation is since, set result to CreateNegatedTemporalDuration(result).
if (operation == DifferenceTemporalPlainTime::Since) {
result = TemporalDurationObject::createNegatedTemporalDuration(result);
}
// Return result.
return result;
}
TemporalPlainTimeObject* TemporalPlainTimeObject::addDurationToTime(ExecutionState& state, AddDurationToTimeOperation operation, Value temporalDurationLike)
{
@ -419,6 +382,83 @@ String* TemporalPlainTimeObject::toString(ExecutionState& state, Value options)
precision.precision);
}
TemporalDurationObject* TemporalPlainTimeObject::since(ExecutionState& state, Value other, Value options)
{
return new TemporalDurationObject(state, differenceTemporalPlainTime(state, DifferenceTemporalPlainTime::Since, other, options));
}
TemporalDurationObject* TemporalPlainTimeObject::until(ExecutionState& state, Value other, Value options)
{
return new TemporalDurationObject(state, differenceTemporalPlainTime(state, DifferenceTemporalPlainTime::Until, other, options));
}
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.round
TemporalPlainTimeObject* TemporalPlainTimeObject::round(ExecutionState& state, Value roundToInput)
{
// Let plainTime be the this value.
// Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
Optional<Object*> roundTo;
// If roundTo is undefined, then
if (roundToInput.isUndefined()) {
// Throw a TypeError exception.
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Invalid roundTo value");
} else if (roundToInput.isString()) {
// If roundTo is a String, then
// Let paramString be roundTo.
// Set roundTo to OrdinaryObjectCreate(null).
// Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
roundTo = new Object(state, Object::PrototypeIsNull);
roundTo->directDefineOwnProperty(state, state.context()->staticStrings().lazySmallestUnit(),
ObjectPropertyDescriptor(roundToInput, ObjectPropertyDescriptor::AllPresent));
} else {
// Else,
// Set roundTo to ? GetOptionsObject(roundTo).
roundTo = Intl::getOptionsObject(state, roundToInput);
}
// NOTE: The following steps read options and perform independent validation in alphabetical order (GetRoundingIncrementOption reads "roundingIncrement" and GetRoundingModeOption reads "roundingMode").
// Let roundingIncrement be ? GetRoundingIncrementOption(roundTo).
auto roundingIncrement = Temporal::getRoundingIncrementOption(state, roundTo);
// Let roundingMode be ? GetRoundingModeOption(roundTo, half-expand).
auto roundingMode = Temporal::getRoundingModeOption(state, roundTo, state.context()->staticStrings().lazyHalfExpand().string());
// Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
auto smallestUnit = Temporal::getTemporalUnitValuedOption(state, roundTo,
state.context()->staticStrings().lazySmallestUnit().string(), Value(Value::EmptyValue));
// Perform ? ValidateTemporalUnitValue(smallestUnit, time).
Temporal::validateTemporalUnitValue(state, smallestUnit, ISO8601::DateTimeUnitCategory::Time, nullptr, 0);
// Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
auto maximum = Temporal::maximumTemporalDurationRoundingIncrement(toDateTimeUnit(smallestUnit.value()));
// Assert: maximum is not unset.
// Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
Temporal::validateTemporalRoundingIncrement(state, roundingIncrement, maximum.value(), false);
// Let result be RoundTime(plainTime.[[Time]], roundingIncrement, smallestUnit, roundingMode).
// ExecutionState& state, ISO8601::PlainTime plainTime, double increment, ISO8601::DateTimeUnit unit, ISO8601::RoundingMode roundingMode
auto result = roundTime(state, plainTime(), roundingIncrement, toDateTimeUnit(smallestUnit.value()), roundingMode);
// Return ! CreateTemporalTime(result).
return new TemporalPlainTimeObject(state, state.context()->globalObject()->temporalPlainTimePrototype(),
ISO8601::PlainTime(result.hours(), result.minutes(), result.seconds(), result.milliseconds(), result.microseconds(), result.nanoseconds()));
}
bool TemporalPlainTimeObject::equals(ExecutionState& state, Value otherInput)
{
auto other = Temporal::toTemporalTime(state, otherInput, Value());
return plainTime() == other->plainTime();
}
int TemporalPlainTimeObject::compare(ExecutionState& state, Value one, Value two)
{
auto time1 = Temporal::toTemporalTime(state, one, Value())->plainTime();
auto time2 = Temporal::toTemporalTime(state, two, Value())->plainTime();
#define DEFINE_ISO8601_PLAIN_TIME_FIELD(name, capitalizedName) \
if (time1.name() > time2.name()) \
return 1; \
if (time1.name() < time2.name()) \
return -1;
PLAIN_TIME_UNITS(DEFINE_ISO8601_PLAIN_TIME_FIELD);
#undef DEFINE_ISO8601_PLAIN_TIME_FIELD
return 0;
}
} // namespace Escargot
#endif

View file

@ -34,9 +34,6 @@ public:
return true;
}
// https://tc39.es/proposal-temporal/#sec-temporal-totemporaltime
static TemporalPlainTimeObject* toTemporalTime(ExecutionState& state, Value item, Value optionsInput);
// https://tc39.es/proposal-temporal/#sec-temporal-totemporaltimerecord
static ISO8601::PartialPlainTime toTemporalTimeRecord(ExecutionState& state, Value temporalTimeLike, Optional<bool> completeness);
@ -65,7 +62,29 @@ public:
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tostring
String* toString(ExecutionState& state, Value options);
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.since
TemporalDurationObject* since(ExecutionState& state, Value other, Value options);
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.until
TemporalDurationObject* until(ExecutionState& state, Value other, Value options);
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.round
TemporalPlainTimeObject* round(ExecutionState& state, Value roundToInput);
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.equals
bool equals(ExecutionState& state, Value otherInput);
// https://tc39.es/proposal-temporal/#sec-temporal.plaintime.compare
static int compare(ExecutionState& state, Value one, Value two);
private:
// https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplaintime
enum class DifferenceTemporalPlainTime {
Until,
Since
};
ISO8601::Duration differenceTemporalPlainTime(ExecutionState& state, DifferenceTemporalPlainTime operation, Value other, Value options);
ISO8601::PlainTime* m_plainTime;
};

View file

@ -1152,7 +1152,7 @@ static Optional<std::tuple<PlainTime, Optional<TimeZoneRecord>>> parseTime(Parse
Optional<std::tuple<PlainTime, Optional<TimeZoneRecord>>> parseTime(String* input)
{
ParserString buffer(input);
if (toupper(*buffer) == 'T') {
if (!buffer.atEnd() && toupper(*buffer) == 'T') {
buffer.advance();
}
auto result = parseTime(buffer, true);

View file

@ -396,6 +396,13 @@ public:
PLAIN_TIME_UNITS(DEFINE_ISO8601_PLAIN_TIME_FIELD);
#undef DEFINE_ISO8601_PLAIN_TIME_FIELD
bool operator==(const PlainTime& other) const
{
return m_hour == other.m_hour && m_minute == other.m_minute
&& m_second == other.m_second && m_millisecond == other.m_millisecond
&& m_microsecond == other.m_microsecond && m_nanosecond == other.m_nanosecond;
}
private:
uint8_t m_hour{ 0 };
uint8_t m_minute{ 0 };

View file

@ -1773,243 +1773,24 @@
<test id="built-ins/Temporal/PlainMonthDay/refisoyear-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainMonthDay/refisoyear-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainMonthDay/subclass"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-cast"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/basic"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/exhaustive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/use-internal-slots"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/compare/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/from/argument-plaindatetime"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/from/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/from/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-cast"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/basic"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/equals/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/roundto-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-cast"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/basic"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/largestunit"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/options-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/options-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/plaintime-propertybag-no-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/result-sub-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/round-cross-unit-boundary"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/since/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-cast"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/basic"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/largestunit"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/options-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/options-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/plaintime-propertybag-no-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/result-sub-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/round-cross-unit-boundary"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/until/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainTime/throws-if-time-is-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/argument-invalid"><reason>TODO</reason></test>