commit 0dc775dede89fe0be5c399744f58d36e98ccf8b0
parent c00c4e31e95d7cd6e2d4b526312644d2334b6b13
Author: Sandor Molnar <smolnar@mozilla.com>
Date: Wed, 5 Nov 2025 21:14:53 +0200
Revert "Bug 1997196: Fix ZonedDateTime differences where earlier wall-clock time is later exact time, or vice versa. r=dminor" for causing temporal spider-monkey perma failures.
This reverts commit 2cb0264d426c57d78dca652778c06af684d98c03.
Diffstat:
6 files changed, 92 insertions(+), 132 deletions(-)
diff --git a/js/src/builtin/temporal/Duration.cpp b/js/src/builtin/temporal/Duration.cpp
@@ -2031,18 +2031,18 @@ struct DurationNudge {
};
/**
- * NudgeToCalendarUnit ( sign, duration, originEpochNs, destEpochNs,
- * isoDateTime, timeZone, calendar, increment, unit, roundingMode )
+ * NudgeToCalendarUnit ( sign, duration, destEpochNs, isoDateTime, timeZone,
+ * calendar, increment, unit, roundingMode )
*/
-static bool NudgeToCalendarUnit(
- JSContext* cx, const InternalDuration& duration,
- const EpochNanoseconds& originEpochNs, const EpochNanoseconds& destEpochNs,
- const ISODateTime& isoDateTime, Handle<TimeZoneValue> timeZone,
- Handle<CalendarValue> calendar, Increment increment, TemporalUnit unit,
- TemporalRoundingMode roundingMode, DurationNudge* result) {
+static bool NudgeToCalendarUnit(JSContext* cx, const InternalDuration& duration,
+ const EpochNanoseconds& destEpochNs,
+ const ISODateTime& isoDateTime,
+ Handle<TimeZoneValue> timeZone,
+ Handle<CalendarValue> calendar,
+ Increment increment, TemporalUnit unit,
+ TemporalRoundingMode roundingMode,
+ DurationNudge* result) {
MOZ_ASSERT(IsValidDuration(duration));
- MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(originEpochNs));
- MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(originEpochNs));
MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(destEpochNs));
MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(destEpochNs));
MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime));
@@ -2160,56 +2160,46 @@ static bool NudgeToCalendarUnit(
// Step 6.
MOZ_ASSERT_IF(sign < 0, r1 <= 0 && r1 > r2);
- // Steps 7-8.
- EpochNanoseconds startEpochNs;
- if (r1 == 0) {
- // Step 7.a.
- startEpochNs = originEpochNs;
- } else {
- // Step 8.a.
- ISODate start;
- if (!CalendarDateAdd(cx, calendar, isoDateTime.date, startDuration,
- TemporalOverflow::Constrain, &start)) {
- return false;
- }
-
- // Step 8.b.
- auto startDateTime = ISODateTime{start, isoDateTime.time};
- MOZ_ASSERT(ISODateTimeWithinLimits(startDateTime));
-
- // Steps 8.c-d.
- EpochNanoseconds startEpochNs;
- if (!timeZone) {
- // Step 8.c.
- startEpochNs = GetUTCEpochNanoseconds(startDateTime);
- } else {
- // Step 8.d.
- if (!GetEpochNanosecondsFor(cx, timeZone, startDateTime,
- TemporalDisambiguation::Compatible,
- &startEpochNs)) {
- return false;
- }
- }
+ // Step 7.
+ ISODate start;
+ if (!CalendarDateAdd(cx, calendar, isoDateTime.date, startDuration,
+ TemporalOverflow::Constrain, &start)) {
+ return false;
}
- // Step 9.
+ // Step 8.
ISODate end;
if (!CalendarDateAdd(cx, calendar, isoDateTime.date, endDuration,
TemporalOverflow::Constrain, &end)) {
return false;
}
+ // Step 9.
+ auto startDateTime = ISODateTime{start, isoDateTime.time};
+ MOZ_ASSERT(ISODateTimeWithinLimits(startDateTime));
+
// Step 10.
auto endDateTime = ISODateTime{end, isoDateTime.time};
MOZ_ASSERT(ISODateTimeWithinLimits(endDateTime));
// Steps 11-12.
+ EpochNanoseconds startEpochNs;
EpochNanoseconds endEpochNs;
if (!timeZone) {
// Step 11.a.
+ startEpochNs = GetUTCEpochNanoseconds(startDateTime);
+
+ // Step 11.b.
endEpochNs = GetUTCEpochNanoseconds(endDateTime);
} else {
// Step 12.a.
+ if (!GetEpochNanosecondsFor(cx, timeZone, startDateTime,
+ TemporalDisambiguation::Compatible,
+ &startEpochNs)) {
+ return false;
+ }
+
+ // Step 12.b.
if (!GetEpochNanosecondsFor(cx, timeZone, endDateTime,
TemporalDisambiguation::Compatible,
&endEpochNs)) {
@@ -2677,19 +2667,16 @@ static bool BubbleRelativeDuration(
}
/**
- * RoundRelativeDuration ( duration, originEpochNs, destEpochNs, isoDateTime,
- * timeZone, calendar, largestUnit, increment, smallestUnit, roundingMode )
+ * RoundRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone,
+ * calendar, largestUnit, increment, smallestUnit, roundingMode )
*/
bool js::temporal::RoundRelativeDuration(
JSContext* cx, const InternalDuration& duration,
- const EpochNanoseconds& originEpochNs, const EpochNanoseconds& destEpochNs,
- const ISODateTime& isoDateTime, Handle<TimeZoneValue> timeZone,
- Handle<CalendarValue> calendar, TemporalUnit largestUnit,
- Increment increment, TemporalUnit smallestUnit,
+ const EpochNanoseconds& destEpochNs, const ISODateTime& isoDateTime,
+ Handle<TimeZoneValue> timeZone, Handle<CalendarValue> calendar,
+ TemporalUnit largestUnit, Increment increment, TemporalUnit smallestUnit,
TemporalRoundingMode roundingMode, InternalDuration* result) {
MOZ_ASSERT(IsValidDuration(duration));
- MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(originEpochNs));
- MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(originEpochNs));
MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(destEpochNs));
MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(destEpochNs));
MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime));
@@ -2705,9 +2692,9 @@ bool js::temporal::RoundRelativeDuration(
DurationNudge nudge;
if (irregularLengthUnit) {
// Step 5.a.
- if (!NudgeToCalendarUnit(cx, duration, originEpochNs, destEpochNs,
- isoDateTime, timeZone, calendar, increment,
- smallestUnit, roundingMode, &nudge)) {
+ if (!NudgeToCalendarUnit(cx, duration, destEpochNs, isoDateTime, timeZone,
+ calendar, increment, smallestUnit, roundingMode,
+ &nudge)) {
return false;
}
} else if (timeZone) {
@@ -2744,17 +2731,17 @@ bool js::temporal::RoundRelativeDuration(
}
/**
- * TotalRelativeDuration ( duration, originEpochNs, destEpochNs, isoDateTime,
- * timeZone, calendar, unit )
+ * TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone,
+ * calendar, unit )
*/
-bool js::temporal::TotalRelativeDuration(
- JSContext* cx, const InternalDuration& duration,
- const EpochNanoseconds& originEpochNs, const EpochNanoseconds& destEpochNs,
- const ISODateTime& isoDateTime, JS::Handle<TimeZoneValue> timeZone,
- JS::Handle<CalendarValue> calendar, TemporalUnit unit, double* result) {
+bool js::temporal::TotalRelativeDuration(JSContext* cx,
+ const InternalDuration& duration,
+ const EpochNanoseconds& destEpochNs,
+ const ISODateTime& isoDateTime,
+ JS::Handle<TimeZoneValue> timeZone,
+ JS::Handle<CalendarValue> calendar,
+ TemporalUnit unit, double* result) {
MOZ_ASSERT(IsValidDuration(duration));
- MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(originEpochNs));
- MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(originEpochNs));
MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(destEpochNs));
MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(destEpochNs));
MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime));
@@ -2763,8 +2750,8 @@ bool js::temporal::TotalRelativeDuration(
// Steps 1.a-b.
DurationNudge nudge;
- if (!NudgeToCalendarUnit(cx, duration, originEpochNs, destEpochNs,
- isoDateTime, timeZone, calendar, Increment{1}, unit,
+ if (!NudgeToCalendarUnit(cx, duration, destEpochNs, isoDateTime, timeZone,
+ calendar, Increment{1}, unit,
TemporalRoundingMode::Trunc, &nudge)) {
return false;
}
diff --git a/js/src/builtin/temporal/Duration.h b/js/src/builtin/temporal/Duration.h
@@ -239,23 +239,21 @@ TimeDuration RoundTimeDuration(const TimeDuration& duration,
TemporalRoundingMode roundingMode);
/**
- * RoundRelativeDuration ( duration, originEpochNs, destEpochNs, isoDateTime,
- * timeZone, calendar, largestUnit, increment, smallestUnit, roundingMode )
+ * RoundRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone,
+ * calendar, largestUnit, increment, smallestUnit, roundingMode )
*/
bool RoundRelativeDuration(
JSContext* cx, const InternalDuration& duration,
- const EpochNanoseconds& originEpochNs, const EpochNanoseconds& destEpochNs,
- const ISODateTime& isoDateTime, JS::Handle<TimeZoneValue> timeZone,
- JS::Handle<CalendarValue> calendar, TemporalUnit largestUnit,
- Increment increment, TemporalUnit smallestUnit,
+ const EpochNanoseconds& destEpochNs, const ISODateTime& isoDateTime,
+ JS::Handle<TimeZoneValue> timeZone, JS::Handle<CalendarValue> calendar,
+ TemporalUnit largestUnit, Increment increment, TemporalUnit smallestUnit,
TemporalRoundingMode roundingMode, InternalDuration* result);
/**
- * TotalRelativeDuration ( duration, originEpochNs, destEpochNs, isoDateTime,
- * timeZone, calendar, unit )
+ * TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone,
+ * calendar, unit )
*/
bool TotalRelativeDuration(JSContext* cx, const InternalDuration& duration,
- const EpochNanoseconds& originEpochNs,
const EpochNanoseconds& destEpochNs,
const ISODateTime& isoDateTime,
JS::Handle<TimeZoneValue> timeZone,
diff --git a/js/src/builtin/temporal/PlainDate.cpp b/js/src/builtin/temporal/PlainDate.cpp
@@ -644,19 +644,16 @@ static bool DifferenceTemporalPlainDate(JSContext* cx,
auto isoDateTime = ISODateTime{temporalDate.date(), {}};
// Step 8.b.
- auto originEpochNs = GetUTCEpochNanoseconds(isoDateTime);
-
- // Step 8.c.
auto isoDateTimeOther = ISODateTime{other.date(), {}};
- // Step 8.d.
+ // Step 8.c.
auto destEpochNs = GetUTCEpochNanoseconds(isoDateTimeOther);
- // Step 8.e.
+ // Step 8.d.
Rooted<TimeZoneValue> timeZone(cx, TimeZoneValue{});
- if (!RoundRelativeDuration(cx, duration, originEpochNs, destEpochNs,
- isoDateTime, timeZone, temporalDate.calendar(),
- settings.largestUnit, settings.roundingIncrement,
+ if (!RoundRelativeDuration(cx, duration, destEpochNs, isoDateTime, timeZone,
+ temporalDate.calendar(), settings.largestUnit,
+ settings.roundingIncrement,
settings.smallestUnit, settings.roundingMode,
&duration)) {
return false;
diff --git a/js/src/builtin/temporal/PlainDateTime.cpp b/js/src/builtin/temporal/PlainDateTime.cpp
@@ -602,15 +602,12 @@ bool js::temporal::DifferencePlainDateTimeWithRounding(
}
// Step 5.
- auto originEpochNs = GetUTCEpochNanoseconds(isoDateTime1);
-
- // Step 6.
auto destEpochNs = GetUTCEpochNanoseconds(isoDateTime2);
- // Step 7.
+ // Step 6.
Rooted<TimeZoneValue> timeZone(cx, TimeZoneValue{});
return RoundRelativeDuration(
- cx, diff, originEpochNs, destEpochNs, isoDateTime1, timeZone, calendar,
+ cx, diff, destEpochNs, isoDateTime1, timeZone, calendar,
settings.largestUnit, settings.roundingIncrement, settings.smallestUnit,
settings.roundingMode, result);
}
@@ -664,15 +661,12 @@ bool js::temporal::DifferencePlainDateTimeWithTotal(
}
// Step 5.
- auto originEpochNs = GetUTCEpochNanoseconds(isoDateTime1);
-
- // Step 6.
auto destEpochNs = GetUTCEpochNanoseconds(isoDateTime2);
- // Step 7.
+ // Step 6.
Rooted<TimeZoneValue> timeZone(cx, TimeZoneValue{});
- return TotalRelativeDuration(cx, diff, originEpochNs, destEpochNs,
- isoDateTime1, timeZone, calendar, unit, result);
+ return TotalRelativeDuration(cx, diff, destEpochNs, isoDateTime1, timeZone,
+ calendar, unit, result);
}
/**
diff --git a/js/src/builtin/temporal/PlainYearMonth.cpp b/js/src/builtin/temporal/PlainYearMonth.cpp
@@ -442,22 +442,16 @@ static bool DifferenceTemporalPlainYearMonth(JSContext* cx,
if (settings.smallestUnit != TemporalUnit::Month ||
settings.roundingIncrement != Increment{1}) {
// Step 16.a.
- auto isoDateTime = ISODateTime{thisDate, {}};
+ auto destEpochNs = GetUTCEpochNanoseconds(ISODateTime{otherDate, {}});
- // Step 16.b.
- auto originEpochNs = GetUTCEpochNanoseconds(isoDateTime);
-
- // Step 16.c.
- auto isoDateTimeOther = ISODateTime{otherDate, {}};
+ // Steps 16.b-c.
+ auto dateTime = ISODateTime{thisDate, {}};
// Step 16.d.
- auto destEpochNs = GetUTCEpochNanoseconds(isoDateTimeOther);
-
- // Step 16.e.
Rooted<TimeZoneValue> timeZone(cx, TimeZoneValue{});
if (!RoundRelativeDuration(
- cx, duration, originEpochNs, destEpochNs, isoDateTime, timeZone,
- calendar, settings.largestUnit, settings.roundingIncrement,
+ cx, duration, destEpochNs, dateTime, timeZone, calendar,
+ settings.largestUnit, settings.roundingIncrement,
settings.smallestUnit, settings.roundingMode, &duration)) {
return false;
}
diff --git a/js/src/builtin/temporal/ZonedDateTime.cpp b/js/src/builtin/temporal/ZonedDateTime.cpp
@@ -688,39 +688,29 @@ static bool DifferenceZonedDateTime(JSContext* cx, const EpochNanoseconds& ns1,
}
// Step 4.
- if (CompareISODate(startDateTime.date, endDateTime.date) == 0) {
- // Step 4.a.
- auto timeDuration = TimeDurationFromEpochNanosecondsDifference(ns2, ns1);
-
- // Step 4.b.
- *result = {{}, timeDuration};
- return true;
- }
-
- // Step 5.
int32_t sign = (ns2 - ns1 < EpochDuration{}) ? -1 : 1;
- // Step 6.
+ // Step 5.
int32_t maxDayCorrection = 1 + (sign > 0);
- // Step 7.
+ // Step 6.
int32_t dayCorrection = 0;
- // Step 8.
+ // Step 7.
auto timeDuration = DifferenceTime(startDateTime.time, endDateTime.time);
- // Step 9.
+ // Step 8.
if (TimeDurationSign(timeDuration) == -sign) {
dayCorrection += 1;
}
- // Steps 10-11.
+ // Steps 9-10.
while (dayCorrection <= maxDayCorrection) {
- // Step 11.a.
+ // Step 10.a.
auto intermediateDate =
BalanceISODate(endDateTime.date, -dayCorrection * sign);
- // Step 11.b.
+ // Step 10.b.
auto intermediateDateTime =
ISODateTime{intermediateDate, startDateTime.time};
if (!ISODateTimeWithinLimits(intermediateDateTime)) {
@@ -729,7 +719,7 @@ static bool DifferenceZonedDateTime(JSContext* cx, const EpochNanoseconds& ns1,
return false;
}
- // Step 11.c.
+ // Step 10.c.
EpochNanoseconds intermediateNs;
if (!GetEpochNanosecondsFor(cx, timeZone, intermediateDateTime,
TemporalDisambiguation::Compatible,
@@ -737,26 +727,26 @@ static bool DifferenceZonedDateTime(JSContext* cx, const EpochNanoseconds& ns1,
return false;
}
- // Step 11.d.
+ // Step 10.d.
auto timeDuration =
TimeDurationFromEpochNanosecondsDifference(ns2, intermediateNs);
- // Step 11.e.
+ // Step 10.e.
int32_t timeSign = TimeDurationSign(timeDuration);
- // Step 11.f.
+ // Step 10.f.
if (sign != -timeSign) {
- // Step 13.
+ // Step 12.
auto dateLargestUnit = std::min(largestUnit, TemporalUnit::Day);
- // Step 14.
+ // Step 13.
DateDuration dateDifference;
if (!CalendarDateUntil(cx, calendar, startDateTime.date, intermediateDate,
dateLargestUnit, &dateDifference)) {
return false;
}
- // Step 15.
+ // Step 14.
MOZ_ASSERT(DateDurationSign(dateDifference) *
TimeDurationSign(timeDuration) >=
0);
@@ -764,11 +754,11 @@ static bool DifferenceZonedDateTime(JSContext* cx, const EpochNanoseconds& ns1,
return true;
}
- // Step 11.g.
+ // Step 10.g.
dayCorrection += 1;
}
- // Step 12.
+ // Step 11.
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr,
JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT);
@@ -823,9 +813,9 @@ bool js::temporal::DifferenceZonedDateTimeWithRounding(
// Step 5.
return RoundRelativeDuration(
- cx, difference, ns1, ns2, dateTime, timeZone, calendar,
- settings.largestUnit, settings.roundingIncrement, settings.smallestUnit,
- settings.roundingMode, result);
+ cx, difference, ns2, dateTime, timeZone, calendar, settings.largestUnit,
+ settings.roundingIncrement, settings.smallestUnit, settings.roundingMode,
+ result);
}
/**
@@ -865,7 +855,7 @@ bool js::temporal::DifferenceZonedDateTimeWithTotal(
}
// Step 5.
- return TotalRelativeDuration(cx, difference, ns1, ns2, dateTime, timeZone,
+ return TotalRelativeDuration(cx, difference, ns2, dateTime, timeZone,
calendar, unit, result);
}