diff --git a/harness/temporalHelpers.js b/harness/temporalHelpers.js index 8ad27bb2b3..161a179f52 100644 --- a/harness/temporalHelpers.js +++ b/harness/temporalHelpers.js @@ -23,6 +23,7 @@ function formatPropertyName(propertyKey, objectName = "") { return objectName ? `${objectName}.${propertyKey}` : propertyKey; } } +const SKIP_SYMBOL = Symbol("Skip"); var TemporalHelpers = { /* @@ -1381,6 +1382,38 @@ var TemporalHelpers = { }); }, + /* + * Used for substituteMethod to indicate default behavior instead of a + * substituted value + */ + SUBSTITUTE_SKIP: SKIP_SYMBOL, + + /* + * substituteMethod(object, propertyName, values): + * + * Defines an own property @object.@propertyName that will, for each + * subsequent call to the method previously defined as + * @object.@propertyName: + * - Call the method, if no more values remain + * - Call the method, if the value in @values for the corresponding call + * is SUBSTITUTE_SKIP + * - Otherwise, return the corresponding value in @value + */ + substituteMethod(object, propertyName, values) { + let calls = 0; + const method = object[propertyName]; + object[propertyName] = function () { + if (calls >= values.length) { + return method.apply(object, arguments); + } else if (values[calls] === SKIP_SYMBOL) { + calls++; + return method.apply(object, arguments); + } else { + return values[calls++]; + } + }; + }, + /* * calendarObserver: * A custom calendar that behaves exactly like the ISO 8601 calendar but diff --git a/test/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js b/test/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js new file mode 100644 index 0000000000..a0f79a441b --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js @@ -0,0 +1,119 @@ +// 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: > + Called abstract operation NanosecondsToDays can throw three different RangeErrors when paired with a ZonedDateTime. +info: | + 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ) + 19. If days < 0 and sign = 1, throw a RangeError exception. + 20. If days > 0 and sign = -1, throw a RangeError exception. + ... + 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. +features: [Temporal, BigInt] +includes: [temporalHelpers.js] +---*/ + +const dayNs = 86_400_000_000_000; +const dayDuration = Temporal.Duration.from({ days: 1 }); +const epochInstant = new Temporal.Instant(0n); + +function timeZoneSubstituteValues( + getPossibleInstantsFor, + getOffsetNanosecondsFor +) { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod( + tz, + "getPossibleInstantsFor", + getPossibleInstantsFor + ); + TemporalHelpers.substituteMethod( + tz, + "getOffsetNanosecondsFor", + getOffsetNanosecondsFor + ); + return tz; +} + +// NanosecondsToDays.19: days < 0 and sign = 1 +let zdt = new Temporal.ZonedDateTime( + -1n, // Set DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [ + TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally for first call, AddDuration step 9 + [epochInstant], // Returned for AddDuration step 10, setting _endNs_ -> DifferenceZonedDateTime _ns2_ + [epochInstant], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + ], + [ + // Behave normally in 4 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Adding day to day sets largestUnit to 'day', avoids having any week/month/year components in differences + dayDuration.add(dayDuration, { + relativeTo: zdt, + }) +); + +// NanosecondsToDays.20: days > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 1n, // Set DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [ + TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally for first call, AddDuration step 9 + [epochInstant], // Returned for AddDuration step 10, setting _endNs_ -> DifferenceZonedDateTime _ns2_ + [epochInstant], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + ], + [ + // Behave normally in 4 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + -dayNs + 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + dayNs - 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Adding day to day sets largestUnit to 'day', avoids having any week/month/year components in differences + dayDuration.add(dayDuration, { + relativeTo: zdt, + }) +); + +// NanosecondsToDays.22: nanoseconds > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 0n, // Set DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [ + TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally for first call, AddDuration step 9 + [new Temporal.Instant(-1n)], // Returned for AddDuration step 10, setting _endNs_ -> DifferenceZonedDateTime _ns2_ + [new Temporal.Instant(-2n)], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [new Temporal.Instant(-4n)], // Returned for NanosecondsToDays step 18.a, setting _oneDayFartherNs_ + ], + [ + // Behave normally in 4 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Adding day to day sets largestUnit to 'day', avoids having any week/month/year components in differences + dayDuration.add(dayDuration, { + relativeTo: zdt, + }) +); diff --git a/test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js b/test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js new file mode 100644 index 0000000000..bebb9c411d --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js @@ -0,0 +1,101 @@ +// 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.round +description: > + Called abstract operation NanosecondsToDays can throw three different RangeErrors when paired with a ZonedDateTime. +info: | + 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ) + 19. If days < 0 and sign = 1, throw a RangeError exception. + 20. If days > 0 and sign = -1, throw a RangeError exception. + ... + 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. +features: [Temporal, BigInt] +includes: [temporalHelpers.js] +---*/ + +const oneNsDuration = Temporal.Duration.from({ nanoseconds: 1 }); +const negOneNsDuration = Temporal.Duration.from({ nanoseconds: -1 }); +const dayNs = 86_400_000_000_000; +const epochInstant = new Temporal.Instant(0n); + +function timeZoneSubstituteValues( + getPossibleInstantsFor, + getOffsetNanosecondsFor +) { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod( + tz, + "getPossibleInstantsFor", + getPossibleInstantsFor + ); + TemporalHelpers.substituteMethod( + tz, + "getOffsetNanosecondsFor", + getOffsetNanosecondsFor + ); + return tz; +} + +// NanosecondsToDays.19: days < 0 and sign = 1 +let zdt = new Temporal.ZonedDateTime( + 0n, // Sets _startNs_ to 0 + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + 0, // Returned for RoundDuration step 6.c.i, setting _intermediate_ - making _startNs_ 0 in NanosecondsToDays + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Using 1ns duration sets _nanoseconds_ to 1 and _sign_ to 1 + oneNsDuration.round({ + relativeTo: zdt, + smallestUnit: "days", + }) +); + +// NanosecondsToDays.20: days > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 0n, // Sets _startNs_ to 0 + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + 0, // Returned for RoundDuration step 6.c.i, setting _intermediate_ - making _startNs_ 0 in NanosecondsToDays + -dayNs + 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + dayNs - 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 + negOneNsDuration.round({ + relativeTo: zdt, + smallestUnit: "days", + }) +); + +// NanosecondsToDays.22: nanoseconds > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 0n, // Sets _startNs_ to 0 + timeZoneSubstituteValues( + [ + [new Temporal.Instant(-2n)], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [new Temporal.Instant(-4n)], // Returned for NanosecondsToDays step 18.a, setting _oneDayFartherNs_ + ], + [ + 0, // Returned for RoundDuration step 6.c.i, setting _intermediate_ - making _startNs_ 0 in NanosecondsToDays + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Using -1ns duration sets _nanoseocnds_ to -1 and _sign_ to -1 + negOneNsDuration.round({ + relativeTo: zdt, + smallestUnit: "days", + }) +); diff --git a/test/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js b/test/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js new file mode 100644 index 0000000000..3e1e54e67c --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js @@ -0,0 +1,119 @@ +// 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: > + Called abstract operation NanosecondsToDays can throw three different RangeErrors when paired with a ZonedDateTime. +info: | + 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ) + 19. If days < 0 and sign = 1, throw a RangeError exception. + 20. If days > 0 and sign = -1, throw a RangeError exception. + ... + 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. +features: [Temporal, BigInt] +includes: [temporalHelpers.js] +---*/ + +const dayNs = 86_400_000_000_000; +const dayDuration = Temporal.Duration.from({ days: 1 }); +const epochInstant = new Temporal.Instant(0n); + +function timeZoneSubstituteValues( + getPossibleInstantsFor, + getOffsetNanosecondsFor +) { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod( + tz, + "getPossibleInstantsFor", + getPossibleInstantsFor + ); + TemporalHelpers.substituteMethod( + tz, + "getOffsetNanosecondsFor", + getOffsetNanosecondsFor + ); + return tz; +} + +// NanosecondsToDays.19: days < 0 and sign = 1 +let zdt = new Temporal.ZonedDateTime( + -1n, // Set DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [ + TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally for first call, AddDuration step 9 + [epochInstant], // Returned for AddDuration step 10, setting _endNs_ -> DifferenceZonedDateTime _ns2_ + [epochInstant], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + ], + [ + // Behave normally in 4 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Subtracting day from day sets largestUnit to 'day', avoids having any week/month/year components in difference + dayDuration.subtract(dayDuration, { + relativeTo: zdt, + }) +); + +// NanosecondsToDays.20: days > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 1n, // Set DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [ + TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally for first call, AddDuration step 9 + [epochInstant], // Returned for AddDuration step 10, setting _endNs_ -> DifferenceZonedDateTime _ns2_ + [epochInstant], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + ], + [ + // Behave normally in 4 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + -dayNs + 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + dayNs - 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Subtracting day from day sets largestUnit to 'day', avoids having any week/month/year components in difference + dayDuration.subtract(dayDuration, { + relativeTo: zdt, + }) +); + +// NanosecondsToDays.22: nanoseconds > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 0n, // Set DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [ + TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally for first call, AddDuration step 9 + [new Temporal.Instant(-1n)], // Returned for AddDuration step 10, setting _endNs_ -> DifferenceZonedDateTime _ns2_ + [new Temporal.Instant(-2n)], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [new Temporal.Instant(-4n)], // Returned for NanosecondsToDays step 18.a, setting _oneDayFartherNs_ + ], + [ + // Behave normally in 4 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Subtracting day from day sets largestUnit to 'day', avoids having any week/month/year components in difference + dayDuration.subtract(dayDuration, { + relativeTo: zdt, + }) +); diff --git a/test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js b/test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js new file mode 100644 index 0000000000..b3a26f76ec --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-nanoseconds-to-days-range-errors.js @@ -0,0 +1,98 @@ +// 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: > + Called abstract operation NanosecondsToDays can throw three different RangeErrors when paired with a ZonedDateTime. +info: | + 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ) + 19. If days < 0 and sign = 1, throw a RangeError exception. + 20. If days > 0 and sign = -1, throw a RangeError exception. + ... + 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. +features: [Temporal, BigInt] +includes: [temporalHelpers.js] +---*/ + +const oneNsDuration = Temporal.Duration.from({ nanoseconds: 1 }); +const negOneNsDuration = Temporal.Duration.from({ nanoseconds: -1 }); +const dayNs = 86_400_000_000_000; +const epochInstant = new Temporal.Instant(0n); + +function timeZoneSubstituteValues( + getPossibleInstantsFor, + getOffsetNanosecondsFor +) { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod( + tz, + "getPossibleInstantsFor", + getPossibleInstantsFor + ); + TemporalHelpers.substituteMethod( + tz, + "getOffsetNanosecondsFor", + getOffsetNanosecondsFor + ); + return tz; +} + +// NanosecondsToDays.19: days < 0 and sign = 1 +let zdt = new Temporal.ZonedDateTime( + 0n, // Sets _startNs_ to 0 + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Using 1ns duration _nanoseconds_ to 1 and _sign_ to 1 + oneNsDuration.total({ + relativeTo: zdt, + unit: "day", + }) +); + +// NanosecondsToDays.20: days > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 0n, // Sets _startNs_ to 0 + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + -dayNs + 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + dayNs - 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 + negOneNsDuration.total({ + relativeTo: zdt, + unit: "day", + }) +); + +// NanosecondsToDays.22: nanoseconds > 0 and sign = -1 +zdt = new Temporal.ZonedDateTime( + 0n, // Sets _startNs_ to 0 + timeZoneSubstituteValues( + [ + [new Temporal.Instant(-2n)], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [new Temporal.Instant(-4n)], // Returned for NanosecondsToDays step 18.a, setting _oneDayFartherNs_ + ], + [ + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 + negOneNsDuration.total({ + relativeTo: zdt, + unit: "day", + }) +); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-range-errors.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-range-errors.js new file mode 100644 index 0000000000..5b02dd9afa --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/nanoseconds-to-days-range-errors.js @@ -0,0 +1,102 @@ +// 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: > + Called abstract operation NanosecondsToDays can throw three different RangeErrors when paired with a ZonedDateTime. +info: | + 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ) + 19. If days < 0 and sign = 1, throw a RangeError exception. + 20. If days > 0 and sign = -1, throw a RangeError exception. + ... + 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. +features: [Temporal, BigInt] +includes: [temporalHelpers.js] +---*/ + +function timeZoneSubstituteValues( + getPossibleInstantsFor, + getOffsetNanosecondsFor +) { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod( + tz, + "getPossibleInstantsFor", + getPossibleInstantsFor + ); + TemporalHelpers.substituteMethod( + tz, + "getOffsetNanosecondsFor", + getOffsetNanosecondsFor + ); + return tz; +} + +const dayNs = 86_400_000_000_000; +const zeroZDT = new Temporal.ZonedDateTime(0n, "UTC"); +const oneZDT = new Temporal.ZonedDateTime(1n, "UTC"); +const epochInstant = new Temporal.Instant(0n); +const options = { largestUnit: "days" }; + +// NanosecondsToDays.19: days < 0 and sign = 1 +let start = new Temporal.ZonedDateTime( + 0n, // Sets DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + // Behave normally in 2 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + start.since( + oneZDT, // Sets DifferenceZonedDateTime _ns2_ + options + ) +); + +// NanosecondsToDays.20: days > 0 and sign = -1 +start = new Temporal.ZonedDateTime( + 1n, // Sets DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + // Behave normally in 2 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + -dayNs + 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + dayNs - 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + start.since( + zeroZDT, // Sets DifferenceZonedDateTime _ns2_ + options + ) +); + +// NanosecondsToDays.22: nanoseconds > 0 and sign = -1 +start = new Temporal.ZonedDateTime( + 1n, // Sets DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [[new Temporal.Instant(-1n)]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + // Behave normally in 2 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + start.since( + zeroZDT, // Sets DifferenceZonedDateTime _ns2_ + options + ) +); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-range-errors.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-range-errors.js new file mode 100644 index 0000000000..3c0e4a15e4 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/nanoseconds-to-days-range-errors.js @@ -0,0 +1,102 @@ +// 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: > + Called abstract operation NanosecondsToDays can throw three different RangeErrors when paired with a ZonedDateTime. +info: | + 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ) + 19. If days < 0 and sign = 1, throw a RangeError exception. + 20. If days > 0 and sign = -1, throw a RangeError exception. + ... + 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. +features: [Temporal, BigInt] +includes: [temporalHelpers.js] +---*/ + +function timeZoneSubstituteValues( + getPossibleInstantsFor, + getOffsetNanosecondsFor +) { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod( + tz, + "getPossibleInstantsFor", + getPossibleInstantsFor + ); + TemporalHelpers.substituteMethod( + tz, + "getOffsetNanosecondsFor", + getOffsetNanosecondsFor + ); + return tz; +} + +const dayNs = 86_400_000_000_000; +const zeroZDT = new Temporal.ZonedDateTime(0n, "UTC"); +const oneZDT = new Temporal.ZonedDateTime(1n, "UTC"); +const epochInstant = new Temporal.Instant(0n); +const options = { largestUnit: "days" }; + +// NanosecondsToDays.19: days < 0 and sign = 1 +let start = new Temporal.ZonedDateTime( + 0n, // Sets DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + // Behave normally in 2 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + start.until( + oneZDT, // Sets DifferenceZonedDateTime _ns2_ + options + ) +); + +// NanosecondsToDays.20: days > 0 and sign = -1 +start = new Temporal.ZonedDateTime( + 1n, // Sets DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [[epochInstant]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + // Behave normally in 2 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + -dayNs + 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + dayNs - 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + start.until( + zeroZDT, // Sets DifferenceZonedDateTime _ns2_ + options + ) +); + +// NanosecondsToDays.22: nanoseconds > 0 and sign = -1 +start = new Temporal.ZonedDateTime( + 1n, // Sets DifferenceZonedDateTime _ns1_ + timeZoneSubstituteValues( + [[new Temporal.Instant(-1n)]], // Returned for NanosecondsToDays step 14, setting _intermediateNs_ + [ + // Behave normally in 2 calls made prior to NanosecondsToDays + TemporalHelpers.SUBSTITUTE_SKIP, + TemporalHelpers.SUBSTITUTE_SKIP, + dayNs - 1, // Returned for NanosecondsToDays step 7, setting _startDateTime_ + -dayNs + 1, // Returned for NanosecondsToDays step 11, setting _endDateTime_ + ] + ) +); +assert.throws(RangeError, () => + start.until( + zeroZDT, // Sets DifferenceZonedDateTime _ns2_ + options + ) +);