Bug 1870251 - Part 4: New AO for creating calendar record from relativeTo. r=mgaudet

Changes from:
69a4b343f4

Depends on D196560

Differential Revision: https://phabricator.services.mozilla.com/D196561
This commit is contained in:
André Bargull 2024-01-15 12:18:52 +00:00
Родитель 030a2087b1
Коммит c366801500
1 изменённых файлов: 101 добавлений и 151 удалений

Просмотреть файл

@ -4051,6 +4051,40 @@ static bool ToRelativeTemporalObject(
return true; return true;
} }
/**
* CreateCalendarMethodsRecordFromRelativeTo ( plainRelativeTo, zonedRelativeTo,
* methods )
*/
static bool CreateCalendarMethodsRecordFromRelativeTo(
JSContext* cx, Handle<Wrapped<PlainDateObject*>> plainRelativeTo,
Handle<ZonedDateTime> zonedRelativeTo,
mozilla::EnumSet<CalendarMethod> methods,
MutableHandle<CalendarRecord> result) {
// Step 1.
if (zonedRelativeTo) {
return CreateCalendarMethodsRecord(cx, zonedRelativeTo.calendar(), methods,
result);
}
// Step 2.
if (plainRelativeTo) {
auto* unwrapped = plainRelativeTo.unwrap(cx);
if (!unwrapped) {
return false;
}
Rooted<CalendarValue> calendar(cx, unwrapped->calendar());
if (!calendar.wrap(cx)) {
return false;
}
return CreateCalendarMethodsRecord(cx, calendar, methods, result);
}
// Step 3.
return true;
}
static constexpr bool IsSafeInteger(int64_t x) { static constexpr bool IsSafeInteger(int64_t x) {
constexpr int64_t MaxSafeInteger = int64_t(1) << 53; constexpr int64_t MaxSafeInteger = int64_t(1) << 53;
constexpr int64_t MinSafeInteger = -MaxSafeInteger; constexpr int64_t MinSafeInteger = -MaxSafeInteger;
@ -6270,39 +6304,17 @@ static bool AddDurationToOrSubtractDurationFromDuration(
// Step 8. // Step 8.
Rooted<CalendarRecord> calendar(cx); Rooted<CalendarRecord> calendar(cx);
if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo,
// FIXME: spec bug - should "or" instead of "and" zonedRelativeTo,
{
// Step 9. CalendarMethod::DateAdd,
if (zonedRelativeTo || plainRelativeTo) { CalendarMethod::DateUntil,
// Step 9.a. },
Rooted<CalendarValue> calendarValue(cx); &calendar)) {
if (plainRelativeTo) { return false;
auto* unwrapped = plainRelativeTo.unwrap(cx);
if (!unwrapped) {
return false;
}
calendarValue = unwrapped->calendar();
if (!calendarValue.wrap(cx)) {
return false;
}
} else {
calendarValue = zonedRelativeTo.calendar();
}
// Step 9.b.
if (!CreateCalendarMethodsRecord(cx, calendarValue,
{
CalendarMethod::DateAdd,
CalendarMethod::DateUntil,
},
&calendar)) {
return false;
}
} }
// Step 10. // Step 9.
if (operation == DurationOperation::Subtract) { if (operation == DurationOperation::Subtract) {
other = other.negate(); other = other.negate();
} }
@ -6323,7 +6335,7 @@ static bool AddDurationToOrSubtractDurationFromDuration(
} }
} }
// Step 11. // Step 10.
auto* obj = CreateTemporalDuration(cx, result); auto* obj = CreateTemporalDuration(cx, result);
if (!obj) { if (!obj) {
return false; return false;
@ -6521,72 +6533,52 @@ static bool Duration_compare(JSContext* cx, unsigned argc, Value* vp) {
// Step 11. // Step 11.
Rooted<CalendarRecord> calendar(cx); Rooted<CalendarRecord> calendar(cx);
if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo,
// Step 12. zonedRelativeTo,
if (zonedRelativeTo || plainRelativeTo) { {
// Step 12.a. CalendarMethod::DateAdd,
Rooted<CalendarValue> calendarValue(cx); },
if (plainRelativeTo) { &calendar)) {
auto* unwrapped = plainRelativeTo.unwrap(cx); return false;
if (!unwrapped) {
return false;
}
calendarValue = unwrapped->calendar();
if (!calendarValue.wrap(cx)) {
return false;
}
} else {
calendarValue = zonedRelativeTo.calendar();
}
// Step 12.b.
if (!CreateCalendarMethodsRecord(cx, calendarValue,
{
CalendarMethod::DateAdd,
},
&calendar)) {
return false;
}
} }
// Step 13. // Step 12.
if (zonedRelativeTo && if (zonedRelativeTo &&
(calendarUnitsPresent || one.days != 0 || two.days != 0)) { (calendarUnitsPresent || one.days != 0 || two.days != 0)) {
// Step 13.a. // Step 12.a.
auto instant = zonedRelativeTo.instant(); auto instant = zonedRelativeTo.instant();
// Step 13.b. // Step 12.b.
PlainDateTime dateTime; PlainDateTime dateTime;
if (!GetPlainDateTimeFor(cx, timeZone, instant, &dateTime)) { if (!GetPlainDateTimeFor(cx, timeZone, instant, &dateTime)) {
return false; return false;
} }
// Step 13.c. // Step 12.c.
Instant after1; Instant after1;
if (!AddZonedDateTime(cx, instant, timeZone, calendar, one, dateTime, if (!AddZonedDateTime(cx, instant, timeZone, calendar, one, dateTime,
&after1)) { &after1)) {
return false; return false;
} }
// Step 13.d. // Step 12.d.
Instant after2; Instant after2;
if (!AddZonedDateTime(cx, instant, timeZone, calendar, two, dateTime, if (!AddZonedDateTime(cx, instant, timeZone, calendar, two, dateTime,
&after2)) { &after2)) {
return false; return false;
} }
// Steps 13.e-g. // Steps 12.e-g.
args.rval().setInt32(after1 < after2 ? -1 : after1 > after2 ? 1 : 0); args.rval().setInt32(after1 < after2 ? -1 : after1 > after2 ? 1 : 0);
return true; return true;
} }
// Steps 14-15. // Steps 13-14.
double days1, days2; double days1, days2;
if (calendarUnitsPresent) { if (calendarUnitsPresent) {
// FIXME: spec issue - directly throw an error if plainRelativeTo is undef. // FIXME: spec issue - directly throw an error if plainRelativeTo is undef.
// Step 14.a. // Step 13.a.
DateDuration unbalanceResult1; DateDuration unbalanceResult1;
if (plainRelativeTo) { if (plainRelativeTo) {
if (!UnbalanceDateDurationRelative(cx, one, TemporalUnit::Day, if (!UnbalanceDateDurationRelative(cx, one, TemporalUnit::Day,
@ -6602,7 +6594,7 @@ static bool Duration_compare(JSContext* cx, unsigned argc, Value* vp) {
MOZ_ASSERT(one.date() == unbalanceResult1.toDuration()); MOZ_ASSERT(one.date() == unbalanceResult1.toDuration());
} }
// Step 14.b. // Step 13.b.
DateDuration unbalanceResult2; DateDuration unbalanceResult2;
if (plainRelativeTo) { if (plainRelativeTo) {
if (!UnbalanceDateDurationRelative(cx, two, TemporalUnit::Day, if (!UnbalanceDateDurationRelative(cx, two, TemporalUnit::Day,
@ -6618,16 +6610,16 @@ static bool Duration_compare(JSContext* cx, unsigned argc, Value* vp) {
MOZ_ASSERT(two.date() == unbalanceResult2.toDuration()); MOZ_ASSERT(two.date() == unbalanceResult2.toDuration());
} }
// Step 14.c. // Step 13.c.
days1 = unbalanceResult1.days; days1 = unbalanceResult1.days;
// Step 14.d. // Step 13.d.
days2 = unbalanceResult2.days; days2 = unbalanceResult2.days;
} else { } else {
// Step 15.a. // Step 14.a.
days1 = one.days; days1 = one.days;
// Step 15.b. // Step 14.b.
days2 = two.days; days2 = two.days;
} }
@ -6669,7 +6661,7 @@ static bool Duration_compare(JSContext* cx, unsigned argc, Value* vp) {
two.nanoseconds, two.nanoseconds,
}; };
// Steps 16-21. // Steps 15-21.
// //
// Fast path when the total duration amount fits into an int64. // Fast path when the total duration amount fits into an int64.
if (auto ns1 = TotalDurationNanoseconds(oneTotal)) { if (auto ns1 = TotalDurationNanoseconds(oneTotal)) {
@ -6679,19 +6671,19 @@ static bool Duration_compare(JSContext* cx, unsigned argc, Value* vp) {
} }
} }
// Steps 16 and 18. // Steps 15 and 17.
Rooted<BigInt*> ns1(cx, TotalDurationNanosecondsSlow(cx, oneTotal)); Rooted<BigInt*> ns1(cx, TotalDurationNanosecondsSlow(cx, oneTotal));
if (!ns1) { if (!ns1) {
return false; return false;
} }
// Steps 17 and 19. // Steps 16 and 18.
auto* ns2 = TotalDurationNanosecondsSlow(cx, twoTotal); auto* ns2 = TotalDurationNanosecondsSlow(cx, twoTotal);
if (!ns2) { if (!ns2) {
return false; return false;
} }
// Step 20-21. // Step 19-21.
args.rval().setInt32(BigInt::compare(ns1, ns2)); args.rval().setInt32(BigInt::compare(ns1, ns2));
return true; return true;
} }
@ -7283,37 +7275,17 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) {
// Step 35. // Step 35.
Rooted<CalendarRecord> calendar(cx); Rooted<CalendarRecord> calendar(cx);
if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo,
// Step 36. zonedRelativeTo,
if (zonedRelativeTo || plainRelativeTo) { {
// Step 36.a. CalendarMethod::DateAdd,
Rooted<CalendarValue> calendarValue(cx); CalendarMethod::DateUntil,
if (plainRelativeTo) { },
auto* unwrapped = plainRelativeTo.unwrap(cx); &calendar)) {
if (!unwrapped) { return false;
return false;
}
calendarValue = unwrapped->calendar();
if (!calendarValue.wrap(cx)) {
return false;
}
} else {
calendarValue = zonedRelativeTo.calendar();
}
// Step 36.b.
if (!CreateCalendarMethodsRecord(cx, calendarValue,
{
CalendarMethod::DateAdd,
CalendarMethod::DateUntil,
},
&calendar)) {
return false;
}
} }
// Step 37. // Step 36.
DateDuration unbalanceResult; DateDuration unbalanceResult;
if (plainRelativeTo) { if (plainRelativeTo) {
if (!UnbalanceDateDurationRelative(cx, duration, largestUnit, if (!UnbalanceDateDurationRelative(cx, duration, largestUnit,
@ -7329,7 +7301,7 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) {
MOZ_ASSERT(duration.date() == unbalanceResult.toDuration()); MOZ_ASSERT(duration.date() == unbalanceResult.toDuration());
} }
// Steps 38-39. // Steps 37-38.
Duration roundInput = { Duration roundInput = {
unbalanceResult.years, unbalanceResult.months, unbalanceResult.weeks, unbalanceResult.years, unbalanceResult.months, unbalanceResult.weeks,
unbalanceResult.days, duration.hours, duration.minutes, unbalanceResult.days, duration.hours, duration.minutes,
@ -7351,10 +7323,10 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) {
} }
} }
// Steps 40-41. // Steps 39-40.
TimeDuration balanceResult; TimeDuration balanceResult;
if (zonedRelativeTo) { if (zonedRelativeTo) {
// Step 40.a. // Step 39.a.
Duration adjustResult; Duration adjustResult;
if (!AdjustRoundedDurationDays(cx, roundResult, roundingIncrement, if (!AdjustRoundedDurationDays(cx, roundResult, roundingIncrement,
smallestUnit, roundingMode, zonedRelativeTo, smallestUnit, roundingMode, zonedRelativeTo,
@ -7364,20 +7336,20 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) {
} }
roundResult = adjustResult; roundResult = adjustResult;
// Step 40.b. // Step 39.b.
if (!BalanceTimeDurationRelative( if (!BalanceTimeDurationRelative(
cx, roundResult, largestUnit, zonedRelativeTo, timeZone, cx, roundResult, largestUnit, zonedRelativeTo, timeZone,
precalculatedPlainDateTime, &balanceResult)) { precalculatedPlainDateTime, &balanceResult)) {
return false; return false;
} }
} else { } else {
// Step 41.a. // Step 40.a.
if (!BalanceTimeDuration(cx, roundResult, largestUnit, &balanceResult)) { if (!BalanceTimeDuration(cx, roundResult, largestUnit, &balanceResult)) {
return false; return false;
} }
} }
// Step 42. // Step 41.
Duration balanceInput = { Duration balanceInput = {
roundResult.years, roundResult.years,
roundResult.months, roundResult.months,
@ -7390,7 +7362,7 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) {
return false; return false;
} }
// Step 43. // Step 42.
auto* obj = CreateTemporalDuration(cx, { auto* obj = CreateTemporalDuration(cx, {
result.years, result.years,
result.months, result.months,
@ -7505,39 +7477,17 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) {
// Step 15. // Step 15.
Rooted<CalendarRecord> calendar(cx); Rooted<CalendarRecord> calendar(cx);
if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo,
// FIXME: spec bug - "or" instead of "and" between conditions zonedRelativeTo,
{
// Step 16. CalendarMethod::DateAdd,
if (zonedRelativeTo || plainRelativeTo) { CalendarMethod::DateUntil,
// Step 16.a. },
Rooted<CalendarValue> calendarValue(cx); &calendar)) {
if (plainRelativeTo) { return false;
auto* unwrapped = plainRelativeTo.unwrap(cx);
if (!unwrapped) {
return false;
}
calendarValue = unwrapped->calendar();
if (!calendarValue.wrap(cx)) {
return false;
}
} else {
calendarValue = zonedRelativeTo.calendar();
}
// Step 16.b.
if (!CreateCalendarMethodsRecord(cx, calendarValue,
{
CalendarMethod::DateAdd,
CalendarMethod::DateUntil,
},
&calendar)) {
return false;
}
} }
// Step 17. // Step 16.
DateDuration unbalanceResult; DateDuration unbalanceResult;
if (plainRelativeTo) { if (plainRelativeTo) {
if (!UnbalanceDateDurationRelative(cx, duration, unit, plainRelativeTo, if (!UnbalanceDateDurationRelative(cx, duration, unit, plainRelativeTo,
@ -7564,10 +7514,10 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) {
duration.nanoseconds, duration.nanoseconds,
}; };
// Steps 18-19. // Steps 17-18.
TimeDuration balanceResult; TimeDuration balanceResult;
if (zonedRelativeTo) { if (zonedRelativeTo) {
// Step 18.a // Step 17.a
Rooted<ZonedDateTime> intermediate(cx); Rooted<ZonedDateTime> intermediate(cx);
if (!MoveRelativeZonedDateTime( if (!MoveRelativeZonedDateTime(
cx, zonedRelativeTo, calendar, timeZone, cx, zonedRelativeTo, calendar, timeZone,
@ -7577,20 +7527,20 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) {
return false; return false;
} }
// Step 18.b. // Step 17.b.
if (!BalancePossiblyInfiniteTimeDurationRelative( if (!BalancePossiblyInfiniteTimeDurationRelative(
cx, balanceInput, unit, intermediate, timeZone, &balanceResult)) { cx, balanceInput, unit, intermediate, timeZone, &balanceResult)) {
return false; return false;
} }
} else { } else {
// Step 19. // Step 18.
if (!BalancePossiblyInfiniteTimeDuration(cx, balanceInput, unit, if (!BalancePossiblyInfiniteTimeDuration(cx, balanceInput, unit,
&balanceResult)) { &balanceResult)) {
return false; return false;
} }
} }
// Steps 20-21. // Steps 19-20.
for (double v : { for (double v : {
balanceResult.days, balanceResult.days,
balanceResult.hours, balanceResult.hours,
@ -7607,9 +7557,9 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) {
} }
MOZ_ASSERT(IsValidDuration(balanceResult.toDuration())); MOZ_ASSERT(IsValidDuration(balanceResult.toDuration()));
// Step 19. (Not applicable in our implementation.) // Step 21. (Not applicable in our implementation.)
// Step 20. // Step 22.
Duration roundInput = { Duration roundInput = {
unbalanceResult.years, unbalanceResult.months, unbalanceResult.years, unbalanceResult.months,
unbalanceResult.weeks, balanceResult.days, unbalanceResult.weeks, balanceResult.days,
@ -7632,7 +7582,7 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) {
} }
} }
// Step 21. // Step 23.
args.rval().setNumber(total); args.rval().setNumber(total);
return true; return true;
} }