diff --git a/test/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js index ced56a7461..b773dc7c97 100644 --- a/test/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js @@ -46,13 +46,13 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( years: ["year"], months: ["month"], weeks: ["week"], - days: ["day"], - hours: ["day"], - minutes: ["day"], - seconds: ["day"], - milliseconds: ["day"], - microseconds: ["day"], - nanoseconds: ["day"] + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] } ); @@ -64,10 +64,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( one.add(two, { relativeTo, largestUnit }); }, { - years: ["year", "day"], - months: ["month", "day"], - weeks: ["week", "day"], - days: ["day", "day"], + years: ["year"], + months: ["month"], + weeks: ["week"], + days: [], hours: [], minutes: [], seconds: [], diff --git a/test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely-1.js b/test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely-1.js deleted file mode 100644 index cfb3b2e5f8..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely-1.js +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.add -description: > - NanosecondsToDays can loop arbitrarily long, performing observable operations each iteration. -info: | - NanosecondsToDays ( nanoseconds, relativeTo ) - - ... - 15. If sign is 1, then - a. Repeat, while days > 0 and intermediateNs > endNs, - i. Set days to days - 1. - ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], - relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - ... -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calls = []; -const duration = Temporal.Duration.from({ days: 1 }); - -function createRelativeTo(count) { - const tz = new Temporal.TimeZone("UTC"); - // Record calls in calls[] - TemporalHelpers.observeMethod(calls, tz, "getPossibleInstantsFor"); - const cal = new Temporal.Calendar("iso8601"); - // Return _count_ days for the second call to dateUntil, behaving normally after - TemporalHelpers.substituteMethod(cal, "dateUntil", [ - TemporalHelpers.SUBSTITUTE_SKIP, - Temporal.Duration.from({ days: count }), - ]); - return new Temporal.ZonedDateTime(0n, tz, cal); -} - -let zdt = createRelativeTo(200); -calls.splice(0); // Reset calls list after ZonedDateTime construction -duration.add(duration, { - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 200 + 2, - "Expected duration.add to call getPossibleInstantsFor correct number of times" -); - -zdt = createRelativeTo(300); -calls.splice(0); // Reset calls list after previous loop + ZonedDateTime construction -duration.add(duration, { - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 300 + 2, - "Expected duration.add to call getPossibleInstantsFor correct number of times" -); diff --git a/test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely-2.js b/test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely.js similarity index 100% rename from test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely-2.js rename to test/built-ins/Temporal/Duration/prototype/add/nanoseconds-to-days-loop-indefinitely.js diff --git a/test/built-ins/Temporal/Duration/prototype/add/order-of-operations.js b/test/built-ins/Temporal/Duration/prototype/add/order-of-operations.js index 7c65dd8f97..0cb316f5c7 100644 --- a/test/built-ins/Temporal/Duration/prototype/add/order-of-operations.js +++ b/test/built-ins/Temporal/Duration/prototype/add/order-of-operations.js @@ -229,9 +229,6 @@ const expectedOpsForPlainRelativeToNoCalendarOperations = [ // InterpretTemporalDateTimeFields "get options.relativeTo.calendar.dateFromFields", "call options.relativeTo.calendar.dateFromFields", - // AddDuration - "get options.relativeTo.calendar.dateUntil", - "call options.relativeTo.calendar.dateUntil", ]; const noCalendarInstance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); @@ -355,9 +352,6 @@ const expectedOpsForZonedRelativeTo = expected.concat([ "call options.relativeTo.timeZone.getOffsetNanosecondsFor", "get options.relativeTo.timeZone.getOffsetNanosecondsFor", "call options.relativeTo.timeZone.getOffsetNanosecondsFor", - // AddDuration → DifferenceZonedDateTime → NanosecondsToDays → DifferenceISODateTime - "get options.relativeTo.calendar.dateUntil", - "call options.relativeTo.calendar.dateUntil", // AddDuration → DifferenceZonedDateTime → NanosecondsToDays → AddZonedDateTime 1 "get options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", diff --git a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js index 951417a6d3..98e7b8e3cf 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js @@ -76,13 +76,13 @@ features: [Temporal] ---*/ // Check with smallestUnit nanoseconds but roundingIncrement > 1; each call -// should result in two calls to dateUntil() originating from -// AdjustRoundedDurationDays, one with largestUnit equal to the largest unit in -// the duration higher than "day", and one with largestUnit: "day". +// should result in one call to dateUntil() originating from +// AdjustRoundedDurationDays, with largestUnit equal to the largest unit in +// the duration higher than "day". // Additionally one call with largestUnit: "month" in BalanceDurationRelative -// when the largestUnit given to round() is "year", and one call with -// largestUnit: "day" when the largestUnit given to round() is "year", "month", -// "week", or "day". +// when the largestUnit given to round() is "year". +// Other calls have largestUnit: "day" so the difference is taken in ISO +// calendar space. const durations = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], @@ -104,16 +104,16 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( duration.round({ largestUnit, roundingIncrement: 2, roundingMode: 'ceil', relativeTo }); }, { - years: ["year", "day", "day", "month"], - months: ["month", "day", "day"], - weeks: ["week", "day", "day"], - days: ["day", "day", "day"], - hours: ["day", "day"], - minutes: ["day", "day"], - seconds: ["day", "day"], - milliseconds: ["day", "day"], - microseconds: ["day", "day"], - nanoseconds: ["day", "day"] + years: ["year", "month"], + months: ["month"], + weeks: ["week"], + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] } ); @@ -142,18 +142,18 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( // Check the paths that call dateUntil() in RoundDuration. These paths do not // call dateUntil() in AdjustRoundedDurationDays. Note that there is no -// largestUnit: "month" call in BalanceDurationRelative and no largestUnit: -// "day" call in BalanceDuration, because the durations have rounded down to 0. +// largestUnit: "month" call in BalanceDurationRelative, because the durations +// have rounded down to 0. TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( (calendar, largestUnit) => { - const duration = new Temporal.Duration(0, 0, 0, 0, 1, 1, 1, 1, 1, 1); + const duration = new Temporal.Duration(0, 1, 0, 0, 1, 1, 1, 1, 1, 1); const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); duration.round({ largestUnit, smallestUnit: largestUnit, relativeTo }); }, { - years: ["day", "year"], - months: ["day"], - weeks: ["day"], - days: ["day"] + years: ["year"], + months: [], + weeks: [], + days: [] } ); diff --git a/test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely-1.js b/test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely-1.js deleted file mode 100644 index 5613cd7e8c..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely-1.js +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2022 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.duration.prototype.round -description: > - NanosecondsToDays can loop arbitrarily long, performing observable operations each iteration. -info: | - NanosecondsToDays ( nanoseconds, relativeTo ) - - ... - 15. If sign is 1, then - a. Repeat, while days > 0 and intermediateNs > endNs, - i. Set days to days - 1. - ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], - relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - ... -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calls = []; -const duration = Temporal.Duration.from({ days: 1 }); - -function createRelativeTo(count) { - const tz = new Temporal.TimeZone("UTC"); - // Record calls in calls[] - TemporalHelpers.observeMethod(calls, tz, "getPossibleInstantsFor"); - const cal = new Temporal.Calendar("iso8601"); - // Return _count_ days for the first call to dateUntil, behaving normally after - TemporalHelpers.substituteMethod(cal, "dateUntil", [ - Temporal.Duration.from({ days: count }), - ]); - return new Temporal.ZonedDateTime(0n, tz, cal); -} - -let zdt = createRelativeTo(200); -calls.splice(0); // Reset calls list after ZonedDateTime construction -duration.round({ - largestUnit: "days", - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 200 + 2, - "Expected duration.round to call getPossibleInstantsFor correct number of times" -); - -zdt = createRelativeTo(300); -calls.splice(0); // Reset calls list after previous loop + ZonedDateTime construction -duration.round({ - largestUnit: "days", - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 300 + 2, - "Expected duration.round to call getPossibleInstantsFor correct number of times" -); diff --git a/test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely-2.js b/test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely.js similarity index 100% rename from test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely-2.js rename to test/built-ins/Temporal/Duration/prototype/round/nanoseconds-to-days-loop-indefinitely.js diff --git a/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js b/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js index fad6339db9..8b6cc03d33 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js +++ b/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js @@ -380,8 +380,6 @@ const expectedOpsForMinimalYearRoundingZoned = expectedOpsForZonedRelativeTo.con "call options.relativeTo.timeZone.getOffsetNanosecondsFor", "get options.relativeTo.timeZone.getOffsetNanosecondsFor", // 11. GetPlainDateTimeFor "call options.relativeTo.timeZone.getOffsetNanosecondsFor", - "get options.relativeTo.calendar.dateUntil", // 12. DifferenceISODateTime - "call options.relativeTo.calendar.dateUntil", // NanosecondsToDays → AddDaysToZonedDateTime "get options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", @@ -421,8 +419,6 @@ const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([ "call options.relativeTo.timeZone.getOffsetNanosecondsFor", "get options.relativeTo.timeZone.getOffsetNanosecondsFor", // 11. GetPlainDateTimeFor "call options.relativeTo.timeZone.getOffsetNanosecondsFor", - "get options.relativeTo.calendar.dateUntil", // 12. DifferenceISODateTime - "call options.relativeTo.calendar.dateUntil", // NanosecondsToDays → AddDaysToZonedDateTime "get options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", diff --git a/test/built-ins/Temporal/Duration/prototype/round/zero-day-length-2.js b/test/built-ins/Temporal/Duration/prototype/round/zero-day-length-2.js deleted file mode 100644 index 60d5fbee15..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/round/zero-day-length-2.js +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2023 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.round -description: A malicious time zone resulting a day length of zero is handled correctly -info: | - Based on a test by André Bargull. - - RoundDuration step 6: - d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). - e. Set _days_ to _days_ + _result_.[[Days]] + _result_.[[Nanoseconds]] / _result_.[[DayLength]]. - - NanosecondsToDays steps 19-23: - 19. If _days_ < 0 and _sign_ = 1, throw a *RangeError* exception. - 20. If _days_ > 0 and _sign_ = -1, throw a *RangeError* exception. - 21. If _nanoseconds_ < 0, then - a. Assert: sign is -1. - 22. If _nanoseconds_ > 0 and _sign_ = -1, throw a *RangeError* exception. - 23. Assert: The inequality abs(_nanoseconds_) < abs(_dayLengthNs_) holds. -features: [Temporal] ----*/ - -const instance = new Temporal.Duration(0, 0, 0, 0, 24, 0, 0, 0, 0, 1); - -const tz = new class extends Temporal.TimeZone { - #getPossibleInstantsForCalls = 0; - - getPossibleInstantsFor(dt) { - this.#getPossibleInstantsForCalls++; - - if (this.#getPossibleInstantsForCalls <= 2) { - return [new Temporal.Instant(86400_000_000_000n + 2n)] - } - return super.getPossibleInstantsFor(dt); - } -}("UTC"); - -const cal = new class extends Temporal.Calendar { - #dateUntilCalls = 0; - - dateUntil(one, two, options) { - this.#dateUntilCalls++; - - if (this.#dateUntilCalls === 1) { - return new Temporal.Duration(0, 0, 0, -2); - } - return super.dateUntil(one, two, options); - } -}("iso8601"); - -const relativeTo = new Temporal.ZonedDateTime(0n, tz, cal); -assert.throws(RangeError, () => instance.round({ relativeTo, smallestUnit: "days" })); diff --git a/test/built-ins/Temporal/Duration/prototype/round/zero-day-length-1.js b/test/built-ins/Temporal/Duration/prototype/round/zero-day-length.js similarity index 100% rename from test/built-ins/Temporal/Duration/prototype/round/zero-day-length-1.js rename to test/built-ins/Temporal/Duration/prototype/round/zero-day-length.js diff --git a/test/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js index ef5fbbfedb..0f4ac38f2e 100644 --- a/test/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js @@ -46,13 +46,13 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( years: ["year"], months: ["month"], weeks: ["week"], - days: ["day"], - hours: ["day"], - minutes: ["day"], - seconds: ["day"], - milliseconds: ["day"], - microseconds: ["day"], - nanoseconds: ["day"] + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] } ); @@ -64,10 +64,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( two.subtract(one, { relativeTo }); }, { - years: ["year", "day"], - months: ["month", "day"], - weeks: ["week", "day"], - days: ["day", "day"], + years: ["year"], + months: ["month"], + weeks: ["week"], + days: [], hours: [], minutes: [], seconds: [], diff --git a/test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely-1.js b/test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely-1.js deleted file mode 100644 index 240be973f0..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely-1.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.subtract -description: > - NanosecondsToDays can loop arbitrarily long, performing observable operations each iteration. -info: | - NanosecondsToDays ( nanoseconds, relativeTo ) - - ... - 15. If sign is 1, then - a. Repeat, while days > 0 and intermediateNs > endNs, - i. Set days to days - 1. - ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], - relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - ... -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calls = []; -const duration = Temporal.Duration.from({ days: 1 }); -const other = Temporal.Duration.from({ hours: 1 }); - -function createRelativeTo(count) { - const tz = new Temporal.TimeZone("UTC"); - // Record calls in calls[] - TemporalHelpers.observeMethod(calls, tz, "getPossibleInstantsFor"); - const cal = new Temporal.Calendar("iso8601"); - // Return _count_ days for the second call to dateUntil, behaving normally after - TemporalHelpers.substituteMethod(cal, "dateUntil", [ - TemporalHelpers.SUBSTITUTE_SKIP, - Temporal.Duration.from({ days: count }), - ]); - return new Temporal.ZonedDateTime(0n, tz, cal); -} - -let zdt = createRelativeTo(200); -calls.splice(0); // Reset calls list after ZonedDateTime construction -duration.subtract(other, { - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 200 + 2, - "Expected duration.subtract to call getPossibleInstantsFor correct number of times" -); - -zdt = createRelativeTo(300); -calls.splice(0); // Reset calls list after previous loop + ZonedDateTime construction -duration.subtract(other, { - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 300 + 2, - "Expected duration.subtract to call getPossibleInstantsFor correct number of times" -); diff --git a/test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely-2.js b/test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely.js similarity index 100% rename from test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely-2.js rename to test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-to-days-loop-indefinitely.js diff --git a/test/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js b/test/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js index 1653736102..3c421fff54 100644 --- a/test/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js +++ b/test/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js @@ -229,9 +229,6 @@ const expectedOpsForPlainRelativeToNoCalendarOperations = [ // InterpretTemporalDateTimeFields "get options.relativeTo.calendar.dateFromFields", "call options.relativeTo.calendar.dateFromFields", - // AddDuration - "get options.relativeTo.calendar.dateUntil", - "call options.relativeTo.calendar.dateUntil", ]; const noCalendarInstance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); @@ -355,9 +352,6 @@ const expectedOpsForZonedRelativeTo = expected.concat([ "call options.relativeTo.timeZone.getOffsetNanosecondsFor", "get options.relativeTo.timeZone.getOffsetNanosecondsFor", "call options.relativeTo.timeZone.getOffsetNanosecondsFor", - // AddDuration → DifferenceZonedDateTime → NanosecondsToDays → DifferenceISODateTime - "get options.relativeTo.calendar.dateUntil", - "call options.relativeTo.calendar.dateUntil", // AddDuration → DifferenceZonedDateTime → NanosecondsToDays → AddZonedDateTime 1 "get options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", diff --git a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js index d9fb7ec05e..8a74793867 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js @@ -44,10 +44,9 @@ includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ -// Check the paths that go through NanosecondsToDays: one call to dateUntil() in -// BalanceDuration and one in RoundDuration with largestUnit: "day" when the -// unit is "year", "month", "week", or "day", and one extra call with -// largestUnit: "year" in RoundDuration when the unit is "year". +// Check the paths that go through NanosecondsToDays: only one call with +// largestUnit: "year" in RoundDuration when the unit is "year". The others all +// have largestUnit: "day" so the difference is taken in ISO calendar space. const duration = new Temporal.Duration(0, 1, 1, 1, 1, 1, 1, 1, 1, 1); @@ -57,10 +56,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( duration.total({ unit, relativeTo }); }, { - years: ["day", "day", "year"], - months: ["day", "day"], - weeks: ["day", "day"], - days: ["day", "day"], + years: ["year"], + months: [], + weeks: [], + days: [], hours: [], minutes: [], seconds: [], @@ -74,7 +73,7 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( (calendar, unit) => { - const duration = new Temporal.Duration(5); + const duration = new Temporal.Duration(5, 1); const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar); duration.total({ unit, relativeTo }); }, diff --git a/test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely-1.js b/test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely-1.js deleted file mode 100644 index 912c21be8a..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely-1.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.total -description: > - NanosecondsToDays can loop arbitrarily long, performing observable operations each iteration. -info: | - NanosecondsToDays ( nanoseconds, relativeTo ) - - ... - 15. If sign is 1, then - a. Repeat, while days > 0 and intermediateNs > endNs, - i. Set days to days - 1. - ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], - relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - ... -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calls = []; -const duration = Temporal.Duration.from({ days: 1 }); - -function createRelativeTo(count) { - const tz = new Temporal.TimeZone("UTC"); - // Record calls in calls[] - TemporalHelpers.observeMethod(calls, tz, "getPossibleInstantsFor"); - const cal = new Temporal.Calendar("iso8601"); - // Return _count_ days for the first call to dateUntil, behaving normally after - TemporalHelpers.substituteMethod(cal, "dateUntil", [ - Temporal.Duration.from({ days: count }), - ]); - return new Temporal.ZonedDateTime(0n, tz, cal); -} - -let zdt = createRelativeTo(200); -calls.splice(0); // Reset calls list after ZonedDateTime construction -duration.total({ - unit: "day", - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 200 + 3, - "Expected duration.total to call getPossibleInstantsFor correct number of times" -); - -zdt = createRelativeTo(300); -calls.splice(0); // Reset calls list after previous loop + ZonedDateTime construction -duration.total({ - unit: "day", - relativeTo: zdt, -}); -assert.sameValue( - calls.length, - 300 + 3, - "Expected duration.total to call getPossibleInstantsFor correct number of times" -); diff --git a/test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely-2.js b/test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely.js similarity index 100% rename from test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely-2.js rename to test/built-ins/Temporal/Duration/prototype/total/nanoseconds-to-days-loop-indefinitely.js diff --git a/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js b/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js index 8ab58638a7..8ad302108e 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js +++ b/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js @@ -281,8 +281,6 @@ const expectedOpsForMinimalYearRoundingZoned = expectedOpsForZonedRelativeTo.con "call options.relativeTo.timeZone.getOffsetNanosecondsFor", "get options.relativeTo.timeZone.getOffsetNanosecondsFor", // 11. GetPlainDateTimeFor "call options.relativeTo.timeZone.getOffsetNanosecondsFor", - "get options.relativeTo.calendar.dateUntil", // 12. DifferenceISODateTime - "call options.relativeTo.calendar.dateUntil", // BalancePossiblyInfiniteDuration → NanosecondsToDays → AddDaysToZonedDateTime "get options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", @@ -328,8 +326,6 @@ const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([ "call options.relativeTo.timeZone.getOffsetNanosecondsFor", "get options.relativeTo.timeZone.getOffsetNanosecondsFor", // 11. GetPlainDateTimeFor "call options.relativeTo.timeZone.getOffsetNanosecondsFor", - "get options.relativeTo.calendar.dateUntil", // 12. DifferenceISODateTime - "call options.relativeTo.calendar.dateUntil", // BalancePossiblyInfiniteTimeDurationRelative → NanosecondsToDays → AddDaysToZonedDateTime "get options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", diff --git a/test/built-ins/Temporal/Duration/prototype/total/zero-day-length-2.js b/test/built-ins/Temporal/Duration/prototype/total/zero-day-length-2.js deleted file mode 100644 index 7d4d75205f..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/total/zero-day-length-2.js +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2023 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.round -description: A malicious time zone resulting a day length of zero is handled correctly -info: | - Based on a test by André Bargull. - - RoundDuration step 6: - d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). - e. Set _days_ to _days_ + _result_.[[Days]] + _result_.[[Nanoseconds]] / _result_.[[DayLength]]. - - NanosecondsToDays steps 19-23: - 19. If _days_ < 0 and _sign_ = 1, throw a *RangeError* exception. - 20. If _days_ > 0 and _sign_ = -1, throw a *RangeError* exception. - 21. If _nanoseconds_ < 0, then - a. Assert: sign is -1. - 22. If _nanoseconds_ > 0 and _sign_ = -1, throw a *RangeError* exception. - 23. Assert: The inequality abs(_nanoseconds_) < abs(_dayLengthNs_) holds. -features: [Temporal] ----*/ - -const instance = new Temporal.Duration(0, 0, 0, 0, 24, 0, 0, 0, 0, 1); - -const tz = new class extends Temporal.TimeZone { - #getPossibleInstantsForCalls = 0; - - getPossibleInstantsFor(dt) { - this.#getPossibleInstantsForCalls++; - - if (this.#getPossibleInstantsForCalls <= 2) { - return [new Temporal.Instant(86400_000_000_000n + 2n)] - } - return super.getPossibleInstantsFor(dt); - } -}("UTC"); - -const cal = new class extends Temporal.Calendar { - #dateUntilCalls = 0; - - dateUntil(one, two, options) { - this.#dateUntilCalls++; - - if (this.#dateUntilCalls === 1) { - return new Temporal.Duration(0, 0, 0, -2); - } - return super.dateUntil(one, two, options); - } -}("iso8601"); - -const relativeTo = new Temporal.ZonedDateTime(0n, tz, cal); -assert.throws(RangeError, () => instance.total({ relativeTo, unit: "days" })); diff --git a/test/built-ins/Temporal/Duration/prototype/total/zero-day-length-1.js b/test/built-ins/Temporal/Duration/prototype/total/zero-day-length.js similarity index 100% rename from test/built-ins/Temporal/Duration/prototype/total/zero-day-length-1.js rename to test/built-ins/Temporal/Duration/prototype/total/zero-day-length.js diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js index 1c47820624..e7d05784ff 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js @@ -13,5 +13,5 @@ features: [Temporal] const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); const instance = new Temporal.PlainDate(2000, 5, 2, calendar); const argument = new Temporal.PlainDate(2022, 6, 14, calendar); -instance.since(argument); +instance.since(argument, { largestUnit: "months" }); assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js index 1d52ad2046..8febb2b34e 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -22,6 +22,6 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( years: ["year"], months: ["month"], weeks: ["week"], - days: ["day"] + days: [] } ); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-invalid-return.js b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-invalid-return.js index 6ecd46d277..27c463b6f9 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-invalid-return.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-invalid-return.js @@ -32,5 +32,9 @@ const tests = [ ]; for (const [test, description = typeof test] of tests) { const plainDate = new Temporal.PlainDate(2000, 5, 2, new CustomCalendar(test)); - assert.throws(TypeError, () => plainDate.since("2022-06-20"), `Expected error with ${description}`); + assert.throws( + TypeError, + () => plainDate.since("2022-06-20", { largestUnit: "years" }), + `Expected error with ${description}` + ); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/custom.js b/test/built-ins/Temporal/PlainDate/prototype/since/custom.js index d768512f54..a59f4af781 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/custom.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/custom.js @@ -9,7 +9,7 @@ features: [Temporal] ---*/ const result = new Temporal.Duration(1, 3, 5, 7, 9); -const options = {}; +const options = { largestUnit: "years" }; let calls = 0; class CustomCalendar extends Temporal.Calendar { constructor() { @@ -20,7 +20,7 @@ class CustomCalendar extends Temporal.Calendar { assert.sameValue(args.length, 3, "Three arguments"); assert.sameValue(args[0], plainDate, "First argument"); assert.sameValue(args[1], other, "Second argument"); - assert.sameValue(args[2].largestUnit, "day", "Third argument: largestUnit"); + assert.sameValue(args[2].largestUnit, "year", "Third argument: largestUnit"); return result; } } diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js b/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js index 8eb8ca076f..3adeae51fd 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js @@ -86,8 +86,8 @@ const instance = new Temporal.PlainDate(2000, 5, 2, ownCalendar); const otherDatePropertyBag = TemporalHelpers.propertyBagObserver(actual, { year: 2001, - month: 5, - monthCode: 'M05', + month: 6, + monthCode: "M06", day: 2, calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), }, "other"); @@ -107,8 +107,8 @@ function createOptionsObserver({ smallestUnit = "days", largestUnit = "auto", ro // clear any observable things that happened while constructing the objects actual.splice(0); -// basic order of observable operations, without rounding: -instance.since(otherDatePropertyBag, createOptionsObserver()); +// basic order of observable operations with calendar call, without rounding: +instance.since(otherDatePropertyBag, createOptionsObserver({ largestUnit: "years" })); assert.compareArray(actual, expected, "order of operations"); actual.splice(0); // clear @@ -138,6 +138,24 @@ instance.since(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "year assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call: +const otherDatePropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + "get this.calendar.dateAdd", // 7.c.i + "call this.calendar.dateAdd", // 7.e + "call this.calendar.dateAdd", // 7.g + "call this.calendar.dateAdd", // 7.y MoveRelativeDate +]); // (7.o not called because months and weeks == 0) +instance.since(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); +actual.splice(0); // clear + // code path through RoundDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateAdd", // 10.b diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js index 32f3812d6d..ad5c782d4f 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js @@ -13,5 +13,5 @@ features: [Temporal] const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); const instance = new Temporal.PlainDate(2000, 5, 2, calendar); const argument = new Temporal.PlainDate(2022, 6, 14, calendar); -instance.until(argument); +instance.until(argument, { largestUnit: "months" }); assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js index 49cfdbbc71..f85e886ebe 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -22,6 +22,6 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( years: ["year"], months: ["month"], weeks: ["week"], - days: ["day"] + days: [] } ); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js index 5e66a55532..a7f898c5de 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js @@ -32,5 +32,8 @@ const tests = [ ]; for (const [test, description = typeof test] of tests) { const plainDate = new Temporal.PlainDate(2000, 5, 2, new CustomCalendar(test)); - assert.throws(TypeError, () => plainDate.until("2022-06-20"), `Expected error with ${description}`); + assert.throws( + TypeError, () => plainDate.until("2022-06-20", { largestUnit: "years" }), + `Expected error with ${description}` + ); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/custom.js b/test/built-ins/Temporal/PlainDate/prototype/until/custom.js index 1d332af5c6..d11dc68640 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/custom.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/custom.js @@ -9,7 +9,7 @@ features: [Temporal] ---*/ const result = new Temporal.Duration(1, 3, 5, 7, 9); -const options = {}; +const options = { largestUnit: "years" }; let calls = 0; class CustomCalendar extends Temporal.Calendar { constructor() { @@ -20,7 +20,7 @@ class CustomCalendar extends Temporal.Calendar { assert.sameValue(args.length, 3, "Three arguments"); assert.sameValue(args[0], plainDate, "First argument"); assert.sameValue(args[1], other, "Second argument"); - assert.sameValue(args[2].largestUnit, "day", "Third argument: largestUnit"); + assert.sameValue(args[2].largestUnit, "year", "Third argument: largestUnit"); return result; } } diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js b/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js index 0cf68208bb..9a5b27fee3 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js @@ -86,8 +86,8 @@ const instance = new Temporal.PlainDate(2000, 5, 2, ownCalendar); const otherDatePropertyBag = TemporalHelpers.propertyBagObserver(actual, { year: 2001, - month: 5, - monthCode: "M05", + month: 6, + monthCode: "M06", day: 2, calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), }, "other"); @@ -107,8 +107,8 @@ function createOptionsObserver({ smallestUnit = "days", largestUnit = "auto", ro // clear any observable things that happened while constructing the objects actual.splice(0); -// basic order of observable operations, without rounding: -instance.until(otherDatePropertyBag, createOptionsObserver()); +// basic order of observable operations with calendar call, without rounding: +instance.until(otherDatePropertyBag, createOptionsObserver({ largestUnit: "years" })); assert.compareArray(actual, expected, "order of operations"); actual.splice(0); // clear @@ -139,6 +139,24 @@ instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "year assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call: +const otherDatePropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + "get this.calendar.dateAdd", // 7.c.i + "call this.calendar.dateAdd", // 7.e + "call this.calendar.dateAdd", // 7.g + "call this.calendar.dateAdd", // 7.y MoveRelativeDate +]); // (7.o not called because months and weeks == 0) +instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); +actual.splice(0); // clear + // code path through RoundDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateAdd", // 10.b diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/balance-infinite-nanoseconds-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/balance-infinite-nanoseconds-duration.js deleted file mode 100644 index 236cc9fb7a..0000000000 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/balance-infinite-nanoseconds-duration.js +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2022 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.plaindatetime.prototype.since -description: > - BalanceDuration throws when the result duration is invalid. -info: | - DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, - y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2, - calendar, largestUnit, options ) - - ... - 12. Let dateDifference be ? CalendarDateUntil(calendar, date1, date2, untilOptions). - 13. Let balanceResult be ? BalanceDuration(dateDifference.[[Days]], timeDifference.[[Hours]], - timeDifference.[[Minutes]], timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], - timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]], largestUnit). - ... - - BalanceDuration ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, - largestUnit [ , relativeTo ] ) - - ... - 3. Else, - a. Set nanoseconds to ! TotalDurationNanoseconds(days, hours, minutes, seconds, milliseconds, - microseconds, nanoseconds, 0). - ... - 15. Return ? CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, - milliseconds × sign, microseconds × sign, nanoseconds × sign). -features: [Temporal] ----*/ - -var cal = new class extends Temporal.Calendar { - dateUntil(date1, date2, options) { - return Temporal.Duration.from({days: Number.MAX_VALUE}); - } -}("iso8601"); - -var dt1 = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, cal); -var dt2 = new Temporal.PlainDateTime(1970, 1, 2, 0, 0, 0, 0, 0, 0, cal); -var options = {largestUnit: "nanoseconds"}; - -assert.throws(RangeError, () => dt1.since(dt2, options)); -assert.throws(RangeError, () => dt2.since(dt1, options)); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js index b36cab23ac..c4cc4df467 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js @@ -13,5 +13,5 @@ features: [Temporal] const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); const argument = new Temporal.PlainDateTime(2022, 6, 14, 18, 21, 36, 660, 690, 387, calendar); -instance.since(argument); +instance.since(argument, { largestUnit: "months" }); assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js index b6f71c759d..0f2b56f9af 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -25,12 +25,12 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( years: ["year"], months: ["month"], weeks: ["week"], - days: ["day"], - hours: ["day"], - minutes: ["day"], - seconds: ["day"], - milliseconds: ["day"], - microseconds: ["day"], - nanoseconds: ["day"] + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] } ); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js index 13899ff959..ced1b1d57e 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js @@ -131,8 +131,8 @@ function createOptionsObserver({ smallestUnit = "nanoseconds", largestUnit = "au // clear any observable things that happened while constructing the objects actual.splice(0); -// basic order of observable operations, without rounding: -instance.since(otherDateTimePropertyBag, createOptionsObserver()); +// basic order of observable operations with calendar call, without rounding: +instance.since(otherDateTimePropertyBag, createOptionsObserver({ largestUnit: "years" })); assert.compareArray(actual, expected, "order of operations"); actual.splice(0); // clear @@ -168,6 +168,30 @@ instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: " assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call: +const otherDatePropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + day: 2, + hour: 12, + minute: 34, + second: 56, + millisecond: 987, + microsecond: 654, + nanosecond: 321, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + "get this.calendar.dateAdd", // 7.c.i + "call this.calendar.dateAdd", // 7.e + "call this.calendar.dateAdd", // 7.g + "call this.calendar.dateAdd", // 7.y MoveRelativeDate +]); // (7.o not called because months and weeks == 0) +instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); +actual.splice(0); // clear + // code path through RoundDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateAdd", // 10.b diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/balance-infinite-nanoseconds-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/balance-infinite-nanoseconds-duration.js deleted file mode 100644 index 153c2324fd..0000000000 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/balance-infinite-nanoseconds-duration.js +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2022 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.plaindatetime.prototype.since -description: > - BalanceDuration throws when the result duration is invalid. -info: | - DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, - y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2, - calendar, largestUnit, options ) - - ... - 12. Let dateDifference be ? CalendarDateUntil(calendar, date1, date2, untilOptions). - 13. Let balanceResult be ? BalanceDuration(dateDifference.[[Days]], timeDifference.[[Hours]], - timeDifference.[[Minutes]], timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], - timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]], largestUnit). - ... - - BalanceDuration ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, - largestUnit [ , relativeTo ] ) - - ... - 3. Else, - a. Set nanoseconds to ! TotalDurationNanoseconds(days, hours, minutes, seconds, milliseconds, - microseconds, nanoseconds, 0). - ... - 15. Return ? CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, - milliseconds × sign, microseconds × sign, nanoseconds × sign). -features: [Temporal] ----*/ - -var cal = new class extends Temporal.Calendar { - dateUntil(date1, date2, options) { - return Temporal.Duration.from({days: Number.MAX_VALUE}); - } -}("iso8601"); - -var dt1 = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, cal); -var dt2 = new Temporal.PlainDateTime(1970, 1, 2, 0, 0, 0, 0, 0, 0, cal); -var options = {largestUnit: "nanoseconds"}; - -assert.throws(RangeError, () => dt1.until(dt2, options)); -assert.throws(RangeError, () => dt2.until(dt1, options)); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js index a83d413dee..111ba10c35 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js @@ -13,5 +13,5 @@ features: [Temporal] const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); const argument = new Temporal.PlainDateTime(2022, 6, 14, 18, 21, 36, 660, 690, 387, calendar); -instance.until(argument); +instance.until(argument, { largestUnit: "months" }); assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js index c3e0447a15..5e444caf38 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -25,12 +25,12 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( years: ["year"], months: ["month"], weeks: ["week"], - days: ["day"], - hours: ["day"], - minutes: ["day"], - seconds: ["day"], - milliseconds: ["day"], - microseconds: ["day"], - nanoseconds: ["day"] + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] } ); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js index 7370f65bfc..a15ce67156 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js @@ -131,8 +131,8 @@ function createOptionsObserver({ smallestUnit = "nanoseconds", largestUnit = "au // clear any observable things that happened while constructing the objects actual.splice(0); -// basic order of observable operations, without rounding: -instance.until(otherDateTimePropertyBag, createOptionsObserver()); +// basic order of observable operations with calendar call, without rounding: +instance.until(otherDateTimePropertyBag, createOptionsObserver({ largestUnit: "years" })); assert.compareArray(actual, expected, "order of operations"); actual.splice(0); // clear @@ -168,6 +168,30 @@ instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: " assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call: +const otherDatePropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + day: 2, + hour: 12, + minute: 34, + second: 56, + millisecond: 987, + microsecond: 654, + nanosecond: 321, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + "get this.calendar.dateAdd", // 7.c.i + "call this.calendar.dateAdd", // 7.e + "call this.calendar.dateAdd", // 7.g + "call this.calendar.dateAdd", // 7.y MoveRelativeDate +]); // (7.o not called because months and weeks == 0) +instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); +actual.splice(0); // clear + // code path through RoundDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateAdd", // 10.b diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js index 315aaecd95..d281177251 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js @@ -100,8 +100,8 @@ const instance = new Temporal.PlainYearMonth(2000, 5, ownCalendar, 1); const otherYearMonthPropertyBag = TemporalHelpers.propertyBagObserver(actual, { year: 2001, - month: 5, - monthCode: "M05", + month: 6, + monthCode: "M06", calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), }, "other"); @@ -150,6 +150,23 @@ instance.since(otherYearMonthPropertyBag, createOptionsObserver({ smallestUnit: assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call +const otherYearMonthPropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + "get this.calendar.dateAdd", // 7.c.i + "call this.calendar.dateAdd", // 7.e + "call this.calendar.dateAdd", // 7.g + "call this.calendar.dateAdd", // 7.y MoveRelativeDate +]); // (7.o not called because months and weeks == 0) +instance.since(otherYearMonthPropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years"); +actual.splice(0); // clear + // code path through RoundDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateAdd", // 10.b diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js index fca9e43e6d..5a72f1e7db 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js @@ -100,8 +100,8 @@ const instance = new Temporal.PlainYearMonth(2000, 5, ownCalendar, 1); const otherYearMonthPropertyBag = TemporalHelpers.propertyBagObserver(actual, { year: 2001, - month: 5, - monthCode: "M05", + month: 6, + monthCode: "M06", calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), }, "other"); @@ -150,6 +150,23 @@ instance.until(otherYearMonthPropertyBag, createOptionsObserver({ smallestUnit: assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call +const otherYearMonthPropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + "get this.calendar.dateAdd", // 7.c.i + "call this.calendar.dateAdd", // 7.e + "call this.calendar.dateAdd", // 7.g + "call this.calendar.dateAdd", // 7.y MoveRelativeDate +]); // (7.o not called because months and weeks == 0) +instance.until(otherYearMonthPropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years"); +actual.splice(0); // clear + // code path through RoundDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateAdd", // 10.b diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js index 24f34ef3e8..aca6c7bf7a 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-null-prototype-options.js @@ -14,4 +14,4 @@ const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); const instance = new Temporal.ZonedDateTime(0n, "UTC", calendar); const argument = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); instance.since(argument, { largestUnit: "year" }); -assert.sameValue(calendar.dateUntilCallCount, 2, "dateUntil should have been called on the calendar"); +assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js index 6365c6224c..6f6e4eaf08 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -55,10 +55,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( later.since(earlier, { largestUnit }); }, { - years: ["year", "day"], - months: ["month", "day"], - weeks: ["week", "day"], - days: ["day", "day"], + years: ["year"], + months: ["month"], + weeks: ["week"], + days: [], hours: [], minutes: [], seconds: [], @@ -72,15 +72,15 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( (calendar, largestUnit) => { - const earlier = new Temporal.ZonedDateTime(0n, "UTC", calendar); + const earlier = new Temporal.ZonedDateTime(-31536000_000_000_000n /* = -365 days */, "UTC", calendar); const later = new Temporal.ZonedDateTime(86_399_999_999_999n, "UTC", calendar); later.since(earlier, { largestUnit, roundingIncrement: 2, roundingMode: 'ceil' }); }, { - years: ["year", "day", "day", "day"], - months: ["month", "day", "day", "day"], - weeks: ["week", "day", "day", "day"], - days: ["day", "day", "day", "day"], + years: ["year", "year"], + months: ["month", "month"], + weeks: ["week", "week"], + days: [], hours: [], minutes: [], seconds: [], @@ -100,10 +100,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( later.since(earlier, { smallestUnit }); }, { - years: ["year", "day", "day", "year"], - months: ["month", "day", "day"], - weeks: ["week", "day", "day"], - days: ["day", "day", "day"], + years: ["year", "year"], + months: ["month"], + weeks: ["week"], + days: [], hours: [], minutes: [], seconds: [], diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely-1.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely-1.js deleted file mode 100644 index 1bb9a0bd95..0000000000 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely-1.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.zoneddatetime.prototype.since -description: > - NanosecondsToDays can loop arbitrarily long, performing observable operations each iteration. -info: | - NanosecondsToDays ( nanoseconds, relativeTo ) - - ... - 15. If sign is 1, then - a. Repeat, while days > 0 and intermediateNs > endNs, - i. Set days to days - 1. - ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], - relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - ... -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calls = []; -const dayLengthNs = 86400000000000n; -const other = new Temporal.ZonedDateTime(dayLengthNs, "UTC", "iso8601"); - -function createRelativeTo(count) { - const tz = new Temporal.TimeZone("UTC"); - // Record calls in calls[] - TemporalHelpers.observeMethod(calls, tz, "getPossibleInstantsFor"); - const cal = new Temporal.Calendar("iso8601"); - // Return _count_ days for the second call to dateUntil, behaving normally after - TemporalHelpers.substituteMethod(cal, "dateUntil", [ - TemporalHelpers.SUBSTITUTE_SKIP, - Temporal.Duration.from({ days: count }), - ]); - return new Temporal.ZonedDateTime(0n, tz, cal); -} - -let zdt = createRelativeTo(200); -calls.splice(0); // Reset calls list after ZonedDateTime construction -zdt.since(other, { - largestUnit: "day", -}); -assert.sameValue( - calls.length, - 200 + 1, - "Expected ZonedDateTime.since to call getPossibleInstantsFor correct number of times" -); - -zdt = createRelativeTo(300); -calls.splice(0); // Reset calls list after previous loop + ZonedDateTime construction -zdt.since(other, { - largestUnit: "day", -}); -assert.sameValue( - calls.length, - 300 + 1, - "Expected ZonedDateTime.since to call getPossibleInstantsFor correct number of times" -); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely-2.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely.js similarity index 100% rename from test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely-2.js rename to test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-loop-indefinitely.js diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js index 889272a97f..9e067ee70a 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js @@ -108,6 +108,18 @@ const ownTimeZone = TemporalHelpers.timeZoneObserver(actual, "this.timeZone"); const ownCalendar = TemporalHelpers.calendarObserver(actual, "this.calendar"); const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, ownTimeZone, ownCalendar); +const dstTimeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const ownDstTimeZone = TemporalHelpers.timeZoneObserver(actual, "this.timeZone", { + getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor, + getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor, +}); +const otherDstTimeZone = TemporalHelpers.timeZoneObserver(actual, "other.timeZone", { + getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor, + getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor, +}); +/* 2000-10-29T01:30-07:00, in the middle of the first repeated hour: */ +const fallBackInstance = new Temporal.ZonedDateTime(972808200_000_000_000n, ownDstTimeZone, ownCalendar); + const otherDateTimePropertyBag = TemporalHelpers.propertyBagObserver(actual, { year: 2004, month: 5, @@ -169,6 +181,139 @@ assert.compareArray(actual, expected.concat([ ]), "order of operations with identical dates and largestUnit a calendar unit"); actual.splice(0); // clear +// two ZonedDateTimes that denote the same wall-clock time in the time zone can +// avoid calling some calendar methods: +const fallBackPropertyBag = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 10, + monthCode: "M10", + day: 29, + hour: 1, + minute: 30, + second: 0, + millisecond: 0, + microsecond: 0, + nanosecond: 0, + offset: "-08:00", + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), + timeZone: otherDstTimeZone, +}, "other"); +fallBackInstance.since(fallBackPropertyBag, createOptionsObserver({ largestUnit: "days" })); +assert.compareArray(actual, [ + // ToTemporalZonedDateTime + "get other.calendar", + "has other.calendar.dateAdd", + "has other.calendar.dateFromFields", + "has other.calendar.dateUntil", + "has other.calendar.day", + "has other.calendar.dayOfWeek", + "has other.calendar.dayOfYear", + "has other.calendar.daysInMonth", + "has other.calendar.daysInWeek", + "has other.calendar.daysInYear", + "has other.calendar.fields", + "has other.calendar.id", + "has other.calendar.inLeapYear", + "has other.calendar.mergeFields", + "has other.calendar.month", + "has other.calendar.monthCode", + "has other.calendar.monthDayFromFields", + "has other.calendar.monthsInYear", + "has other.calendar.weekOfYear", + "has other.calendar.year", + "has other.calendar.yearMonthFromFields", + "has other.calendar.yearOfWeek", + "get other.calendar.fields", + "call other.calendar.fields", + "get other.day", + "get other.day.valueOf", + "call other.day.valueOf", + "get other.hour", + "get other.hour.valueOf", + "call other.hour.valueOf", + "get other.microsecond", + "get other.microsecond.valueOf", + "call other.microsecond.valueOf", + "get other.millisecond", + "get other.millisecond.valueOf", + "call other.millisecond.valueOf", + "get other.minute", + "get other.minute.valueOf", + "call other.minute.valueOf", + "get other.month", + "get other.month.valueOf", + "call other.month.valueOf", + "get other.monthCode", + "get other.monthCode.toString", + "call other.monthCode.toString", + "get other.nanosecond", + "get other.nanosecond.valueOf", + "call other.nanosecond.valueOf", + "get other.offset", + "get other.offset.toString", + "call other.offset.toString", + "get other.second", + "get other.second.valueOf", + "call other.second.valueOf", + "get other.timeZone", + "get other.year", + "get other.year.valueOf", + "call other.year.valueOf", + "has other.timeZone.getOffsetNanosecondsFor", + "has other.timeZone.getPossibleInstantsFor", + "has other.timeZone.id", + "get other.calendar.dateFromFields", + "call other.calendar.dateFromFields", + "get other.timeZone.getPossibleInstantsFor", + "call other.timeZone.getPossibleInstantsFor", + "get other.timeZone.getOffsetNanosecondsFor", + "call other.timeZone.getOffsetNanosecondsFor", + // NOTE: extra because of wall-clock time ambiguity: + "get other.timeZone.getOffsetNanosecondsFor", + "call other.timeZone.getOffsetNanosecondsFor", + // CalendarEquals + "get this.calendar.id", + "get other.calendar.id", + // CopyDataProperties + "ownKeys options", + "getOwnPropertyDescriptor options.roundingIncrement", + "get options.roundingIncrement", + "getOwnPropertyDescriptor options.roundingMode", + "get options.roundingMode", + "getOwnPropertyDescriptor options.largestUnit", + "get options.largestUnit", + "getOwnPropertyDescriptor options.smallestUnit", + "get options.smallestUnit", + "getOwnPropertyDescriptor options.additional", + "get options.additional", + // GetDifferenceSettings + "get options.largestUnit.toString", + "call options.largestUnit.toString", + "get options.roundingIncrement.valueOf", + "call options.roundingIncrement.valueOf", + "get options.roundingMode.toString", + "call options.roundingMode.toString", + "get options.smallestUnit.toString", + "call options.smallestUnit.toString", + // TimeZoneEquals + "get this.timeZone.id", + "get other.timeZone.id", + // DifferenceZonedDateTime + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + // NanosecondsToDays + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + // NanosecondsToDays → AddDaysToZonedDateTime + "get this.timeZone.getPossibleInstantsFor", + "call this.timeZone.getPossibleInstantsFor", +], "order of operations with identical wall-clock times and largestUnit a calendar unit"); +actual.splice(0); // clear + // Making largestUnit a calendar unit adds the following observable operations: const expectedOpsForCalendarDifference = [ // TimeZoneEquals @@ -192,9 +337,6 @@ const expectedOpsForCalendarDifference = [ "call this.timeZone.getOffsetNanosecondsFor", "get this.timeZone.getOffsetNanosecondsFor", "call this.timeZone.getOffsetNanosecondsFor", - // NanosecondsToDays → DifferenceISODateTime - "get this.calendar.dateUntil", - "call this.calendar.dateUntil", // NanosecondsToDays → AddDaysToZonedDateTime "get this.timeZone.getPossibleInstantsFor", "call this.timeZone.getPossibleInstantsFor", @@ -218,9 +360,6 @@ const expectedOpsForCalendarRounding = [ "call this.timeZone.getOffsetNanosecondsFor", "get this.timeZone.getOffsetNanosecondsFor", "call this.timeZone.getOffsetNanosecondsFor", - // RoundDuration → NanosecondsToDays → DifferenceISODateTime - "get this.calendar.dateUntil", - "call this.calendar.dateUntil", // RoundDuration → NanosecondsToDays → AddDaysToZonedDateTime "get this.timeZone.getPossibleInstantsFor", "call this.timeZone.getPossibleInstantsFor", diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js index da645b430b..adb200001c 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js @@ -14,4 +14,4 @@ const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); const instance = new Temporal.ZonedDateTime(0n, "UTC", calendar); const argument = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); instance.until(argument, { largestUnit: "year" }); -assert.sameValue(calendar.dateUntilCallCount, 2, "dateUntil should have been called on the calendar"); +assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js index c07900f71b..6842f08dcf 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -55,10 +55,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( earlier.until(later, { largestUnit }); }, { - years: ["year", "day"], - months: ["month", "day"], - weeks: ["week", "day"], - days: ["day", "day"], + years: ["year"], + months: ["month"], + weeks: ["week"], + days: [], hours: [], minutes: [], seconds: [], @@ -72,15 +72,15 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( (calendar, largestUnit) => { - const earlier = new Temporal.ZonedDateTime(0n, "UTC", calendar); + const earlier = new Temporal.ZonedDateTime(-31536000_000_000_000n /* = -365 days */, "UTC", calendar); const later = new Temporal.ZonedDateTime(86_399_999_999_999n, "UTC", calendar); earlier.until(later, { largestUnit, roundingIncrement: 2, roundingMode: 'ceil' }); }, { - years: ["year", "day", "day", "day"], - months: ["month", "day", "day", "day"], - weeks: ["week", "day", "day", "day"], - days: ["day", "day", "day", "day"], + years: ["year", "year"], + months: ["month", "month"], + weeks: ["week", "week"], + days: [], hours: [], minutes: [], seconds: [], @@ -100,10 +100,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( earlier.until(later, { smallestUnit }); }, { - years: ["year", "day", "day", "year"], - months: ["month", "day", "day"], - weeks: ["week", "day", "day"], - days: ["day", "day", "day"], + years: ["year", "year"], + months: ["month"], + weeks: ["week"], + days: [], hours: [], minutes: [], seconds: [], diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely-1.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely-1.js deleted file mode 100644 index fc2ef8e782..0000000000 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely-1.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.zoneddatetime.prototype.until -description: > - NanosecondsToDays can loop arbitrarily long, performing observable operations each iteration. -info: | - NanosecondsToDays ( nanoseconds, relativeTo ) - - ... - 15. If sign is 1, then - a. Repeat, while days > 0 and intermediateNs > endNs, - i. Set days to days - 1. - ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], - relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - ... -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calls = []; -const dayLengthNs = 86400000000000n; -const other = new Temporal.ZonedDateTime(dayLengthNs, "UTC", "iso8601"); - -function createRelativeTo(count) { - const tz = new Temporal.TimeZone("UTC"); - // Record calls in calls[] - TemporalHelpers.observeMethod(calls, tz, "getPossibleInstantsFor"); - const cal = new Temporal.Calendar("iso8601"); - // Return _count_ days for the second call to dateUntil, behaving normally after - TemporalHelpers.substituteMethod(cal, "dateUntil", [ - TemporalHelpers.SUBSTITUTE_SKIP, - Temporal.Duration.from({ days: count }), - ]); - return new Temporal.ZonedDateTime(0n, tz, cal); -} - -let zdt = createRelativeTo(200); -calls.splice(0); // Reset calls list after ZonedDateTime construction -zdt.until(other, { - largestUnit: "day", -}); -assert.sameValue( - calls.length, - 200 + 1, - "Expected ZonedDateTime.until to call getPossibleInstantsFor correct number of times" -); - -zdt = createRelativeTo(300); -calls.splice(0); // Reset calls list after previous loop + ZonedDateTime construction -zdt.until(other, { - largestUnit: "day", -}); -assert.sameValue( - calls.length, - 300 + 1, - "Expected ZonedDateTime.until to call getPossibleInstantsFor correct number of times" -); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely-2.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely.js similarity index 100% rename from test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely-2.js rename to test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-loop-indefinitely.js diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js index 173edb99da..a7ddb56da3 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js @@ -108,6 +108,18 @@ const ownTimeZone = TemporalHelpers.timeZoneObserver(actual, "this.timeZone"); const ownCalendar = TemporalHelpers.calendarObserver(actual, "this.calendar"); const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, ownTimeZone, ownCalendar); +const dstTimeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const ownDstTimeZone = TemporalHelpers.timeZoneObserver(actual, "this.timeZone", { + getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor, + getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor, +}); +const otherDstTimeZone = TemporalHelpers.timeZoneObserver(actual, "other.timeZone", { + getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor, + getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor, +}); +/* 2000-10-29T01:30-07:00, in the middle of the first repeated hour: */ +const fallBackInstance = new Temporal.ZonedDateTime(972808200_000_000_000n, ownDstTimeZone, ownCalendar); + const otherDateTimePropertyBag = TemporalHelpers.propertyBagObserver(actual, { year: 2004, month: 5, @@ -169,6 +181,139 @@ assert.compareArray(actual, expected.concat([ ]), "order of operations with identical dates and largestUnit a calendar unit"); actual.splice(0); // clear +// two ZonedDateTimes that denote the same wall-clock time in the time zone can +// avoid calling some calendar methods: +const fallBackPropertyBag = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 10, + monthCode: "M10", + day: 29, + hour: 1, + minute: 30, + second: 0, + millisecond: 0, + microsecond: 0, + nanosecond: 0, + offset: "-08:00", + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), + timeZone: otherDstTimeZone, +}, "other"); +fallBackInstance.until(fallBackPropertyBag, createOptionsObserver({ largestUnit: "days" })); +assert.compareArray(actual, [ + // ToTemporalZonedDateTime + "get other.calendar", + "has other.calendar.dateAdd", + "has other.calendar.dateFromFields", + "has other.calendar.dateUntil", + "has other.calendar.day", + "has other.calendar.dayOfWeek", + "has other.calendar.dayOfYear", + "has other.calendar.daysInMonth", + "has other.calendar.daysInWeek", + "has other.calendar.daysInYear", + "has other.calendar.fields", + "has other.calendar.id", + "has other.calendar.inLeapYear", + "has other.calendar.mergeFields", + "has other.calendar.month", + "has other.calendar.monthCode", + "has other.calendar.monthDayFromFields", + "has other.calendar.monthsInYear", + "has other.calendar.weekOfYear", + "has other.calendar.year", + "has other.calendar.yearMonthFromFields", + "has other.calendar.yearOfWeek", + "get other.calendar.fields", + "call other.calendar.fields", + "get other.day", + "get other.day.valueOf", + "call other.day.valueOf", + "get other.hour", + "get other.hour.valueOf", + "call other.hour.valueOf", + "get other.microsecond", + "get other.microsecond.valueOf", + "call other.microsecond.valueOf", + "get other.millisecond", + "get other.millisecond.valueOf", + "call other.millisecond.valueOf", + "get other.minute", + "get other.minute.valueOf", + "call other.minute.valueOf", + "get other.month", + "get other.month.valueOf", + "call other.month.valueOf", + "get other.monthCode", + "get other.monthCode.toString", + "call other.monthCode.toString", + "get other.nanosecond", + "get other.nanosecond.valueOf", + "call other.nanosecond.valueOf", + "get other.offset", + "get other.offset.toString", + "call other.offset.toString", + "get other.second", + "get other.second.valueOf", + "call other.second.valueOf", + "get other.timeZone", + "get other.year", + "get other.year.valueOf", + "call other.year.valueOf", + "has other.timeZone.getOffsetNanosecondsFor", + "has other.timeZone.getPossibleInstantsFor", + "has other.timeZone.id", + "get other.calendar.dateFromFields", + "call other.calendar.dateFromFields", + "get other.timeZone.getPossibleInstantsFor", + "call other.timeZone.getPossibleInstantsFor", + "get other.timeZone.getOffsetNanosecondsFor", + "call other.timeZone.getOffsetNanosecondsFor", + // NOTE: extra because of wall-clock time ambiguity: + "get other.timeZone.getOffsetNanosecondsFor", + "call other.timeZone.getOffsetNanosecondsFor", + // CalendarEquals + "get this.calendar.id", + "get other.calendar.id", + // CopyDataProperties + "ownKeys options", + "getOwnPropertyDescriptor options.roundingIncrement", + "get options.roundingIncrement", + "getOwnPropertyDescriptor options.roundingMode", + "get options.roundingMode", + "getOwnPropertyDescriptor options.largestUnit", + "get options.largestUnit", + "getOwnPropertyDescriptor options.smallestUnit", + "get options.smallestUnit", + "getOwnPropertyDescriptor options.additional", + "get options.additional", + // GetDifferenceSettings + "get options.largestUnit.toString", + "call options.largestUnit.toString", + "get options.roundingIncrement.valueOf", + "call options.roundingIncrement.valueOf", + "get options.roundingMode.toString", + "call options.roundingMode.toString", + "get options.smallestUnit.toString", + "call options.smallestUnit.toString", + // TimeZoneEquals + "get this.timeZone.id", + "get other.timeZone.id", + // DifferenceZonedDateTime + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + // NanosecondsToDays + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + "get this.timeZone.getOffsetNanosecondsFor", + "call this.timeZone.getOffsetNanosecondsFor", + // NanosecondsToDays → AddDaysToZonedDateTime + "get this.timeZone.getPossibleInstantsFor", + "call this.timeZone.getPossibleInstantsFor", +], "order of operations with identical wall-clock times and largestUnit a calendar unit"); +actual.splice(0); // clear + // Making largestUnit a calendar unit adds the following observable operations: const expectedOpsForCalendarDifference = [ // TimeZoneEquals @@ -192,9 +337,6 @@ const expectedOpsForCalendarDifference = [ "call this.timeZone.getOffsetNanosecondsFor", "get this.timeZone.getOffsetNanosecondsFor", "call this.timeZone.getOffsetNanosecondsFor", - // NanosecondsToDays → DifferenceISODateTime - "get this.calendar.dateUntil", - "call this.calendar.dateUntil", // NanosecondsToDays → AddDaysToZonedDateTime "get this.timeZone.getPossibleInstantsFor", "call this.timeZone.getPossibleInstantsFor", @@ -218,9 +360,6 @@ const expectedOpsForCalendarRounding = [ "call this.timeZone.getOffsetNanosecondsFor", "get this.timeZone.getOffsetNanosecondsFor", "call this.timeZone.getOffsetNanosecondsFor", - // RoundDuration → NanosecondsToDays → DifferenceISODateTime - "get this.calendar.dateUntil", - "call this.calendar.dateUntil", // RoundDuration → NanosecondsToDays → AddDaysToZonedDateTime "get this.timeZone.getPossibleInstantsFor", "call this.timeZone.getPossibleInstantsFor",