Implement Temporal.PlainYearMonth.{ until, since }

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2025-10-13 16:44:53 +09:00 committed by Patrick Kim
commit 600fa1a906
9 changed files with 131 additions and 148 deletions

View file

@ -698,6 +698,18 @@ static Value builtinTemporalPlainYearMonthSubtract(ExecutionState& state, Value
return plainYearMonth->addDurationToYearMonth(state, TemporalPlainYearMonthObject::AddDurationToYearMonthOperation::Subtract, argv[0], argc > 1 ? argv[1] : Value());
}
static Value builtinTemporalPlainYearMonthUntil(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINYEARMONTH(plainYearMonth, Until);
return plainYearMonth->until(state, argv[0], argc > 1 ? argv[1] : Value());
}
static Value builtinTemporalPlainYearMonthSince(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINYEARMONTH(plainYearMonth, Since);
return plainYearMonth->since(state, argv[0], argc > 1 ? argv[1] : Value());
}
void GlobalObject::initializeTemporal(ExecutionState& state)
{
ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(
@ -1003,6 +1015,8 @@ void GlobalObject::installTemporal(ExecutionState& state)
m_temporalPlainYearMonthPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyToPlainDate()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyToPlainDate(), builtinTemporalPlainYearMonthToPlainDate, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainYearMonthPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->add), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->add, builtinTemporalPlainYearMonthAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainYearMonthPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySubtract()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySubtract(), builtinTemporalPlainYearMonthSubtract, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainYearMonthPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyUntil()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyUntil(), builtinTemporalPlainYearMonthUntil, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainYearMonthPrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySince()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySince(), builtinTemporalPlainYearMonthSince, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
{
AtomicString name(state.context(), "get calendarId");

View file

@ -833,8 +833,7 @@ TimeZone Temporal::toTemporalTimezoneIdentifier(ExecutionState& state, const Val
if (record.m_z) {
return TimeZone(int64_t(0));
} else if (record.m_nameOrOffset && record.m_nameOrOffset.id().value() == 0) {
const std::string& s = record.m_nameOrOffset.get<0>();
return TimeZone(String::fromUTF8(s.data(), s.length()));
return TimeZone(record.m_nameOrOffset.get<0>());
} else if (record.m_nameOrOffset && record.m_nameOrOffset.id().value() == 1) {
return TimeZone(record.m_nameOrOffset.get<1>());
} else if (record.m_offset) {
@ -2283,6 +2282,9 @@ static Nudged nudgeToCalendarUnit(ExecutionState& state, int32_t sign, const ISO
auto endDateTime = ISO8601::PlainDateTime(end, isoDateTime.plainTime());
Int128 startEpochNs = Temporal::getEpochNanosecondsFor(state, timeZone, startDateTime, TemporalDisambiguationOption::Compatible);
Int128 endEpochNs = Temporal::getEpochNanosecondsFor(state, timeZone, endDateTime, TemporalDisambiguationOption::Compatible);
if (!(sign != 1 || ((startEpochNs <= destEpochNs) && (destEpochNs <= endEpochNs))) || !(sign == 1 || ((endEpochNs <= destEpochNs) && (destEpochNs <= startEpochNs)))) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "date time is out of range of ECMAScript representation");
}
ASSERT(sign != 1 || ((startEpochNs <= destEpochNs) && (destEpochNs <= endEpochNs)));
ASSERT(sign == 1 || ((endEpochNs <= destEpochNs) && (destEpochNs <= startEpochNs)));
ASSERT(startEpochNs != endEpochNs);
@ -2464,6 +2466,20 @@ bool Temporal::isoYearMonthWithinLimits(ISO8601::PlainDate plainDate)
return isValid;
}
ISO8601::Duration Temporal::adjustDateDurationRecord(ExecutionState& state, ISO8601::Duration dateDuration, double days, Optional<double> weeks, Optional<double> months)
{
// If weeks is not present, set weeks to dateDuration.[[Weeks]].
if (!weeks) {
weeks = dateDuration.weeks();
}
// If months is not present, set months to dateDuration.[[Months]].
if (!months) {
months = dateDuration.months();
}
// Return ? CreateDateDurationRecord(dateDuration.[[Years]], months, weeks, days).
return ISO8601::Duration({ dateDuration.years(), months.value(), weeks.value(), days });
}
} // namespace Escargot
#endif

View file

@ -383,6 +383,9 @@ public:
// https://tc39.es/proposal-temporal/#sec-temporal-balanceisodate
static ISO8601::PlainDate balanceISODate(ExecutionState& state, double year, double month, double day);
// https://tc39.es/proposal-temporal/#sec-temporal-adjustdatedurationrecord
static ISO8601::Duration adjustDateDurationRecord(ExecutionState& state, ISO8601::Duration dateDuration, double days, Optional<double> weeks, Optional<double> months);
};
} // namespace Escargot

View file

@ -87,9 +87,9 @@ public:
static int compare(ExecutionState& state, Value one, Value two);
static int compareISODate(ExecutionState& state, TemporalPlainDateObject* one, TemporalPlainDateObject* two);
protected:
ISO8601::PlainDate computeISODate(ExecutionState& state);
protected:
// https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplaindate
enum class DifferenceTemporalPlainDate {
Until,

View file

@ -255,6 +255,85 @@ TemporalPlainYearMonthObject* TemporalPlainYearMonthObject::addDurationToYearMon
icuDate, calendar);
}
ISO8601::Duration TemporalPlainYearMonthObject::differenceTemporalPlainYearMonth(ExecutionState& state, DifferenceTemporalYearMonth operation, Value otherInput, Value options)
{
// Set other to ? ToTemporalYearMonth(other).
auto other = Temporal::toTemporalYearMonth(state, otherInput, Value());
// Let calendar be yearMonth.[[Calendar]].
auto calendar = calendarID();
// If CalendarEquals(calendar, other.[[Calendar]]) is false, throw a RangeError exception.
if (calendar != other->calendarID()) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "Calendar mismatch");
}
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Let settings be ? GetDifferenceSettings(operation, resolvedOptions, date, « week, day », month, year).
TemporalUnit disallowedUnits[2] = { TemporalUnit::Week, TemporalUnit::Day };
auto settings = Temporal::getDifferenceSettings(state, operation == DifferenceTemporalYearMonth::Since, resolvedOptions, ISO8601::DateTimeUnitCategory::Date, disallowedUnits, 2, TemporalUnit::Month, TemporalUnit::Year);
// If CompareISODate(yearMonth.[[ISODate]], other.[[ISODate]]) = 0, then
if (TemporalPlainDateObject::compareISODate(state, this, other) == 0) {
// Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
return ISO8601::Duration();
}
// Let thisFields be ISODateToFields(calendar, yearMonth.[[ISODate]], year-month).
// Set thisFields.[[Day]] to 1.
CalendarFieldsRecord thisFields;
auto isoDate = computeISODate(state);
thisFields.year = isoDate.year();
thisFields.month = isoDate.month();
thisFields.day = 1;
// Let thisDate be ? CalendarDateFromFields(calendar, thisFields, constrain).
auto thisDate = new TemporalPlainDateObject(state, state.context()->globalObject()->temporalPlainDatePrototype(),
Temporal::calendarDateFromFields(state, calendar, thisFields, TemporalOverflowOption::Constrain), calendar);
// Let otherFields be ISODateToFields(calendar, other.[[ISODate]], year-month).
// Set otherFields.[[Day]] to 1.
CalendarFieldsRecord otherFields;
isoDate = other->computeISODate(state);
otherFields.year = isoDate.year();
otherFields.month = isoDate.month();
otherFields.day = 1;
// Let otherDate be ? CalendarDateFromFields(calendar, otherFields, constrain).
auto otherDate = new TemporalPlainDateObject(state, state.context()->globalObject()->temporalPlainDatePrototype(),
Temporal::calendarDateFromFields(state, calendar, otherFields, TemporalOverflowOption::Constrain), calendar);
// Let dateDifference be CalendarDateUntil(calendar, thisDate, otherDate, settings.[[LargestUnit]]).
auto dateDifference = Temporal::calendarDateUntil(calendar, thisDate->computeISODate(state), otherDate->computeISODate(state), toTemporalUnit(settings.largestUnit));
// Let yearsMonthsDifference be ! AdjustDateDurationRecord(dateDifference, 0, 0).
auto yearsMonthsDifference = Temporal::adjustDateDurationRecord(state, dateDifference, 0, 0, NullOption);
// Let duration be CombineDateAndTimeDuration(yearsMonthsDifference, 0).
auto duration = ISO8601::InternalDuration::combineDateAndTimeDuration(yearsMonthsDifference, 0);
// If settings.[[SmallestUnit]] is not month or settings.[[RoundingIncrement]] ≠ 1, then
if (settings.smallestUnit != ISO8601::DateTimeUnit::Day || settings.roundingIncrement != 1) {
// Let isoDateTime be CombineISODateAndTimeRecord(thisDate, MidnightTimeRecord()).
auto isoDateTime = computeISODate(state);
// Let isoDateTimeOther be CombineISODateAndTimeRecord(otherDate, MidnightTimeRecord()).
auto isoDateTimeOther = other->computeISODate(state);
// Let destEpochNs be GetUTCEpochNanoseconds(isoDateTimeOther).
auto destEpochNs = ISO8601::ExactTime::fromISOPartsAndOffset(isoDateTimeOther.year(), isoDateTimeOther.month(), isoDateTimeOther.day(), 0, 0, 0, 0, 0, 0, 0).epochNanoseconds();
// Set duration to ? RoundRelativeDuration(duration, destEpochNs, isoDateTime, unset, calendar, settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
duration = Temporal::roundRelativeDuration(state, duration, destEpochNs, ISO8601::PlainDateTime(isoDateTime, ISO8601::PlainTime()), NullOption, calendar, toTemporalUnit(settings.largestUnit), settings.roundingIncrement, toTemporalUnit(settings.smallestUnit), settings.roundingMode);
}
// Let result be ! TemporalDurationFromInternal(duration, day).
auto result = TemporalDurationObject::temporalDurationFromInternal(state, duration, ISO8601::DateTimeUnit::Day);
// If operation is since, set result to CreateNegatedTemporalDuration(result).
if (operation == DifferenceTemporalYearMonth::Since) {
result = TemporalDurationObject::createNegatedTemporalDuration(result);
}
// Return result.
return result;
}
TemporalDurationObject* TemporalPlainYearMonthObject::since(ExecutionState& state, Value other, Value options)
{
return new TemporalDurationObject(state, differenceTemporalPlainYearMonth(state, DifferenceTemporalYearMonth::Since, other, options));
}
TemporalDurationObject* TemporalPlainYearMonthObject::until(ExecutionState& state, Value other, Value options)
{
return new TemporalDurationObject(state, differenceTemporalPlainYearMonth(state, DifferenceTemporalYearMonth::Until, other, options));
}
} // namespace Escargot
#endif

View file

@ -59,7 +59,16 @@ public:
};
TemporalPlainYearMonthObject* addDurationToYearMonth(ExecutionState& state, AddDurationToYearMonthOperation operation, Value temporalDurationLike, Value options);
TemporalDurationObject* since(ExecutionState& state, Value other, Value options);
TemporalDurationObject* until(ExecutionState& state, Value other, Value options);
private:
// https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplainyearmonth
enum class DifferenceTemporalYearMonth {
Until,
Since
};
ISO8601::Duration differenceTemporalPlainYearMonth(ExecutionState& state, DifferenceTemporalYearMonth operation, Value other, Value options);
};
} // namespace Escargot

View file

@ -1000,7 +1000,7 @@ Optional<int64_t> parseUTCOffset(String* string, DateTimeParseOption option)
return result;
}
static Optional<Variant<std::string, int64_t>> parseTimeZoneAnnotation(ParserString& buffer)
static Optional<Variant<TimeZoneID, int64_t>> parseTimeZoneAnnotation(ParserString& buffer)
{
// https://tc39.es/proposal-temporal/#prod-TimeZoneAnnotation
// TimeZoneAnnotation :
@ -1032,7 +1032,7 @@ static Optional<Variant<std::string, int64_t>> parseTimeZoneAnnotation(ParserStr
if (*buffer != ']')
return NullOption;
buffer.advance();
return Variant<std::string, int64_t>::create<1>(offset.value());
return Variant<TimeZoneID, int64_t>::create<1>(offset.value());
}
case 'E': {
// "Etc/GMT+20" and "]" => length is 11.
@ -1052,7 +1052,7 @@ static Optional<Variant<std::string, int64_t>> parseTimeZoneAnnotation(ParserStr
hour = (secondHourCharacter - '0') + 10 * (firstHourCharacter - '0');
if (hour < 24 && buffer[10] == ']') {
buffer.advanceBy(11);
return Variant<std::string, int64_t>::create<1>(nsPerHour * hour * factor);
return Variant<TimeZoneID, int64_t>::create<1>(nsPerHour * hour * factor);
}
}
}
@ -1143,7 +1143,7 @@ static Optional<Variant<std::string, int64_t>> parseTimeZoneAnnotation(ParserStr
if (*buffer != ']')
return NullOption;
buffer.advance();
return Variant<std::string, int64_t>::create<0>(result);
return Variant<TimeZoneID, int64_t>::create<0>(String::fromASCII(result.data(), result.size()));
}
}
}

View file

@ -219,7 +219,7 @@ public:
template <typename T>
Duration(std::initializer_list<T> list)
{
memset(m_data.data(), 0, sizeof(double) * m_data.size());
m_data.fill(0);
size_t idx = 0;
for (auto n : list) {
m_data[idx++] = n;
@ -542,9 +542,9 @@ using TimeZone = Variant<TimeZoneID, int64_t>;
struct TimeZoneRecord {
bool m_z;
Optional<int64_t> m_offset;
Variant<std::string, int64_t> m_nameOrOffset;
Variant<TimeZoneID, int64_t> m_nameOrOffset = Variant<TimeZoneID, int64_t>::empty();
TimeZoneRecord(bool z = false, Optional<int64_t> offset = NullOption, Variant<std::string, int64_t> nameOrOffset = Variant<std::string, int64_t>())
TimeZoneRecord(bool z = false, Optional<int64_t> offset = NullOption, Variant<TimeZoneID, int64_t> nameOrOffset = Variant<TimeZoneID, int64_t>::empty())
: m_z(z)
, m_offset(offset)
, m_nameOrOffset(nameOrOffset)

View file

@ -449,7 +449,6 @@
<test id="built-ins/Temporal/PlainDate/prototype/since/argument-plaindatetime"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-slots"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/since/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/since/throws-if-rounded-date-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/subtract/argument-duration-max"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-calendar-annotation"><reason>TODO</reason></test>
@ -540,7 +539,6 @@
<test id="built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-slots"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/until/throws-if-rounded-date-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/with/overflow-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/with/plaindatelike-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDate/prototype/withCalendar/calendar-temporal-object"><reason>TODO</reason></test>
@ -1461,149 +1459,15 @@
<test id="built-ins/Temporal/PlainYearMonth/prototype/equals/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/equals/use-internal-slots"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/equals/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-casting"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-propertybag-calendar-case-insensitive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-propertybag-calendar-invalid-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-propertybag-calendar-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-propertybag-calendar-leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-propertybag-calendar-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-propertybag-calendar-year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-limits"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/builtin-calendar-no-array-iteration"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-auto"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-disallowed-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-months"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-smallestunit-mismatch"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-years"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/options-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/options-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/round-cross-unit-boundary"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/symmetry"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/throws-if-rounded-date-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/throws-if-year-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/since/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-duration-max"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/subtract/throws-if-year-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/limits"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-casting"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-propertybag-calendar-case-insensitive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-propertybag-calendar-invalid-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-propertybag-calendar-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-propertybag-calendar-leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-propertybag-calendar-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-propertybag-calendar-year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-limits"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-auto"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-disallowed-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-months"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-smallestunit-mismatch"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-years"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/options-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/options-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/round-cross-unit-boundary"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-as-expected"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/throws-if-rounded-date-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/throws-if-year-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/until/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainYearMonth/prototype/with/yearmonthlike-invalid"><reason>TODO</reason></test>
<test id="built-ins/Temporal/ZonedDateTime/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/ZonedDateTime/calendar-case-insensitive"><reason>TODO</reason></test>
@ -2610,7 +2474,6 @@
<test id="intl402/Temporal/PlainYearMonth/prototype/equals/compare-calendar"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/since/canonicalize-calendar"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/since/mixed-calendar-invalid"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/toLocaleString/calendar-mismatch"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle"><reason>TODO</reason></test>
@ -2627,7 +2490,6 @@
<test id="intl402/Temporal/PlainYearMonth/prototype/toString/calendarname-undefined"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/toString/calendarname-wrong-type"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/until/canonicalize-calendar"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/until/mixed-calendar-invalid"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/with/minimum-valid-year-month"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainYearMonth/prototype/with/non-iso-calendar-fields"><reason>TODO</reason></test>