Temporal: Coverage for Temporal.Duration

This commit is contained in:
André Bargull 2024-11-19 16:30:22 +01:00 committed by Philip Chimento
parent 4aa9379068
commit 2ea91c02d0
14 changed files with 603 additions and 0 deletions

View File

@ -0,0 +1,32 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.compare
description: >
Throws RangeError when adding duration to ZonedDateTime relativeTo fails.
info: |
Temporal.Duration.compare ( one, two [ , options ] )
12. If zonedRelativeTo is not undefined, and either TemporalUnitCategory(largestUnit1)
or TemporalUnitCategory(largestUnit2) is date, then
...
c. Let after1 be ? AddZonedDateTime(zonedRelativeTo.[[EpochNanoseconds]], timeZone,
calendar, duration1, constrain).
d. Let after2 be ? AddZonedDateTime(zonedRelativeTo.[[EpochNanoseconds]], timeZone,
calendar, duration2, constrain).
...
features: [Temporal]
---*/
var blank = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
var oneDay = new Temporal.Duration(0, 0, 0, 1);
var relativeTo = new Temporal.ZonedDateTime(864n * 10n**19n, "UTC");
var options = {
relativeTo
};
assert.throws(RangeError, () => Temporal.Duration.compare(oneDay, blank, options));
assert.throws(RangeError, () => Temporal.Duration.compare(blank, oneDay, options));

View File

@ -0,0 +1,54 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.from
description: >
Throws RangeError when when any duration component is Infinity.
info: |
Temporal.Duration.from ( item )
1. Return ? ToTemporalDuration(item).
ToTemporalDuration ( item )
...
2. If item is not an Object, then
...
b. Return ? ParseTemporalDurationString(item).
...
ParseTemporalDurationString ( isoString )
...
44. Return ? CreateTemporalDuration(yearsMV, monthsMV, weeksMV, daysMV, hoursMV,
minutesMV, secondsMV, millisecondsMV, microsecondsMV, nanosecondsMV).
CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds,
milliseconds, microseconds, nanoseconds [ , newTarget ] )
1. If IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds,
microseconds, nanoseconds) is false, throw a RangeError exception.
...
IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds,
microseconds, nanoseconds )
...
2. For each value v of « years, months, weeks, days, hours, minutes, seconds,
milliseconds, microseconds, nanoseconds », do
a. If 𝔽(v) is not finite, return false.
...
features: [Temporal]
---*/
var inf = "9".repeat(1000);
assert.throws(RangeError, () => Temporal.Duration.from(`P${inf}Y`));
assert.throws(RangeError, () => Temporal.Duration.from(`P${inf}M`));
assert.throws(RangeError, () => Temporal.Duration.from(`P${inf}W`));
assert.throws(RangeError, () => Temporal.Duration.from(`P${inf}D`));
assert.throws(RangeError, () => Temporal.Duration.from(`PT${inf}H`));
assert.throws(RangeError, () => Temporal.Duration.from(`PT${inf}M`));
assert.throws(RangeError, () => Temporal.Duration.from(`PT${inf}S`));

View File

@ -0,0 +1,72 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.from
description: >
ToNumber conversion throws.
info: |
Temporal.Duration.from ( item )
1. Return ? ToTemporalDuration(item).
ToTemporalDuration ( item )
...
4. Let partial be ? ToTemporalPartialDurationRecord(item).
...
ToTemporalPartialDurationRecord ( temporalDurationLike )
...
4. Let days be ? Get(temporalDurationLike, "days").
...
6. Let hours be ? Get(temporalDurationLike, "hours").
...
8. Let microseconds be ? Get(temporalDurationLike, "microseconds").
...
10. Let milliseconds be ? Get(temporalDurationLike, "milliseconds").
11....
12. Let minutes be ? Get(temporalDurationLike, "minutes").
...
14. Let months be ? Get(temporalDurationLike, "months").
...
16. Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds").
...
18. Let seconds be ? Get(temporalDurationLike, "seconds").
...
20. Let weeks be ? Get(temporalDurationLike, "weeks").
...
22. Let years be ? Get(temporalDurationLike, "years").
...
ToIntegerIfIntegral ( argument )
1. Let number be ? ToNumber(argument).
...
features: [Temporal]
---*/
for (var name of [
"years",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
"milliseconds",
"microseconds",
"nanoseconds",
]) {
var item = {
get [name]() {
throw new Test262Error();
}
};
assert.throws(
Test262Error,
() => Temporal.Duration.from(item),
`name = ${name}`
);
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.from
description: >
ToNumber conversion throws.
info: |
Temporal.Duration.from ( item )
1. Return ? ToTemporalDuration(item).
ToTemporalDuration ( item )
...
4. Let partial be ? ToTemporalPartialDurationRecord(item).
...
ToTemporalPartialDurationRecord ( temporalDurationLike )
...
5. If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days).
...
7. If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours).
...
9. If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds).
...
11. If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds).
...
13. If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes).
...
15. If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months).
...
17. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds).
...
19. If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds).
...
21. If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks).
...
23. If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years).
...
ToIntegerIfIntegral ( argument )
1. Let number be ? ToNumber(argument).
...
features: [Temporal]
---*/
for (var invalid of [Symbol(), 0n]) {
for (var name of [
"years",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
"milliseconds",
"microseconds",
"nanoseconds",
]) {
var item = {[name]: invalid};
assert.throws(
TypeError,
() => Temporal.Duration.from(item),
`name = ${name}, value = ${String(invalid)}`
);
}
}

View File

@ -0,0 +1,41 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.instant
description: >
OrdinaryCreateFromConstructor returns with an abrupt completion.
info: |
CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds,
milliseconds, microseconds, nanoseconds [ , newTarget ] )
...
3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Duration.prototype%",
« [[InitializedTemporalDuration]], [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]],
[[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »).
...
OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )
...
2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto).
...
GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
...
2. Let proto be ? Get(constructor, "prototype").
...
features: [Temporal]
---*/
var newTarget = Object.defineProperty(function(){}.bind(), "prototype", {
get() {
throw new Test262Error();
}
});
assert.throws(Test262Error, function() {
Reflect.construct(Temporal.Duration, [], newTarget)
});

View File

@ -0,0 +1,44 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration
description: >
ToNumber conversion throws.
info: |
Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ ,
minutes [ , seconds [ , milliseconds [ , microseconds [ ,
nanoseconds ] ] ] ] ] ] ] ] ] ] )
...
2. If years is undefined, let y be 0; else let y be ? ToIntegerIfIntegral(years).
3. If months is undefined, let mo be 0; else let mo be ? ToIntegerIfIntegral(months).
4. If weeks is undefined, let w be 0; else let w be ? ToIntegerIfIntegral(weeks).
5. If days is undefined, let d be 0; else let d be ? ToIntegerIfIntegral(days).
6. If hours is undefined, let h be 0; else let h be ? ToIntegerIfIntegral(hours).
7. If minutes is undefined, let m be 0; else let m be ? ToIntegerIfIntegral(minutes).
8. If seconds is undefined, let s be 0; else let s be ? ToIntegerIfIntegral(seconds).
9. If milliseconds is undefined, let ms be 0; else let ms be ? ToIntegerIfIntegral(milliseconds).
10. If microseconds is undefined, let mis be 0; else let mis be ? ToIntegerIfIntegral(microseconds).
11. If nanoseconds is undefined, let ns be 0; else let ns be ? ToIntegerIfIntegral(nanoseconds).
...
ToIntegerIfIntegral ( argument )
1. Let number be ? ToNumber(argument).
...
features: [Temporal]
---*/
for (var invalid of [Symbol(), 0n]) {
assert.throws(TypeError, () => new Temporal.Duration(invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, 0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, invalid));
assert.throws(TypeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, invalid));
}

View File

@ -0,0 +1,31 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration
description: >
Throws RangeError when any duration component is a too large finite number.
features: [Temporal]
---*/
assert.throws(RangeError, () => new Temporal.Duration(Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(-Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -Number.MAX_VALUE));
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -Number.MAX_VALUE));

View File

@ -0,0 +1,31 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.add
description: >
TemporalDurationFromInternal throws a RangeError when the result is too large.
info: |
TemporalDurationFromInternal ( internalDuration, largestUnit )
...
9. Else if largestUnit is microsecond, then
a. Set microseconds to floor(nanoseconds / 1000).
b. Set nanoseconds to nanoseconds modulo 1000.
...
12. Return ? CreateTemporalDuration(internalDuration.[[Date]].[[Years]],
internalDuration.[[Date]].[[Months]], internalDuration.[[Date]].[[Weeks]],
internalDuration.[[Date]].[[Days]] + days × sign, hours × sign, minutes × sign,
seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).
features: [Temporal]
---*/
var one = Temporal.Duration.from({nanoseconds: 9.007199254740991e+24});
var two = Temporal.Duration.from({microseconds: 1_000_000});
// TemporalDurationFromInternal is called with:
// internalDuration.[[Time]] = 9,007,199,254,740,991,926,258,176.
//
// |microseconds| is 9,007,199,254,740,991,926,258, which rounds up to
// 9,007,199,254,740,992,000,000. This exceeds the maximum allowed duration.
assert.throws(RangeError, () => one.add(two));

View File

@ -0,0 +1,31 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.subtract
description: >
TemporalDurationFromInternal throws a RangeError when the result is too large.
info: |
TemporalDurationFromInternal ( internalDuration, largestUnit )
...
9. Else if largestUnit is microsecond, then
a. Set microseconds to floor(nanoseconds / 1000).
b. Set nanoseconds to nanoseconds modulo 1000.
...
12. Return ? CreateTemporalDuration(internalDuration.[[Date]].[[Years]],
internalDuration.[[Date]].[[Months]], internalDuration.[[Date]].[[Weeks]],
internalDuration.[[Date]].[[Days]] + days × sign, hours × sign, minutes × sign,
seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).
features: [Temporal]
---*/
var one = Temporal.Duration.from({nanoseconds: -9.007199254740991e+24});
var two = Temporal.Duration.from({microseconds: 1_000_000});
// TemporalDurationFromInternal is called with:
// internalDuration.[[Time]] = -9,007,199,254,740,991,926,258,176.
//
// |microseconds| is -9,007,199,254,740,991,926,258, which rounds up to
// -9,007,199,254,740,992,000,000. This exceeds the maximum allowed duration.
assert.throws(RangeError, () => one.subtract(two));

View File

@ -0,0 +1,13 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.tolocalestring
description: >
toLocaleString return a string.
features: [Temporal]
---*/
var duration = new Temporal.Duration();
assert.sameValue(typeof duration.toLocaleString(), "string");

View File

@ -0,0 +1,49 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.total
description: >
relativeTo is a Temporal.PlainDateTime object.
info: |
Temporal.Duration.prototype.total ( totalOf )
...
7. Let relativeToRecord be ? GetTemporalRelativeToOption(totalOf).
...
GetTemporalRelativeToOption ( options )
1. Let value be ? Get(options, "relativeTo").
...
5. If value is an Object, then
...
c. If value has an [[InitializedTemporalDateTime]] internal slot, then
i. Let plainDate be ! CreateTemporalDate(value.[[ISODateTime]].[[ISODate]], value.[[Calendar]]).
ii. Return the Record { [[PlainRelativeTo]]: plainDate, [[ZonedRelativeTo]]: undefined }.
...
features: [Temporal]
---*/
var duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
var relativeToDate = new Temporal.PlainDate(1970, 1, 1);
var relativeToDateTime = new Temporal.PlainDateTime(1970, 1, 1);
for (var unit of [
"years",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
"milliseconds",
"microseconds",
"nanoseconds",
]) {
var expected = duration.total({unit, relativeTo: relativeToDate});
var actual = duration.total({unit, relativeTo: relativeToDateTime});
assert.sameValue(actual, expected, `unit = ${unit}`);
}

View File

@ -0,0 +1,50 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.total
description: >
Throws RangeError when date-time is outside the valid limits.
info: |
Temporal.Duration.prototype.total ( totalOf )
...
12. Else if plainRelativeTo is not undefined, then
...
h. Let total be ? DifferencePlainDateTimeWithTotal(isoDateTime, targetDateTime,
calendar, unit).
...
DifferencePlainDateTimeWithTotal ( isoDateTime1, isoDateTime2, calendar, unit )
...
5. Return ? TotalRelativeDuration(diff, destEpochNs, isoDateTime1, unset, calendar, unit).
TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, calendar, unit )
1. If IsCalendarUnit(unit) is true, or timeZone is not unset and unit is day, then
a. Let sign be InternalDurationSign(duration).
b. Let record be ? NudgeToCalendarUnit(sign, duration, destEpochNs, isoDateTime,
timeZone, calendar, 1, unit, trunc).
...
NudgeToCalendarUnit ( sign, duration, destEpochNs, isoDateTime, timeZone, calendar,
increment, unit, roundingMode )
...
8. Let end be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], endDuration, constrain).
...
features: [Temporal]
---*/
var duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
var relativeTo = new Temporal.PlainDate(275760, 9, 13);
var totalOf = {
unit: "years",
relativeTo,
};
assert.throws(RangeError, () => duration.total(totalOf));

View File

@ -0,0 +1,50 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.total
description: >
Throws RangeError when date-time is outside the valid limits.
info: |
Temporal.Duration.prototype.total ( totalOf )
...
11. If zonedRelativeTo is not undefined, then
...
f. Let total be ? DifferenceZonedDateTimeWithTotal(relativeEpochNs,
targetEpochNs, timeZone, calendar, unit).
...
DifferenceZonedDateTimeWithTotal ( ns1, ns2, timeZone, calendar, unit )
...
4. Return ? TotalRelativeDuration(difference, ns2, dateTime, timeZone, calendar, unit).
TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, calendar, unit )
1. If IsCalendarUnit(unit) is true, or timeZone is not unset and unit is day, then
a. Let sign be InternalDurationSign(duration).
b. Let record be ? NudgeToCalendarUnit(sign, duration, destEpochNs, isoDateTime,
timeZone, calendar, 1, unit, trunc).
...
NudgeToCalendarUnit ( sign, duration, destEpochNs, isoDateTime, timeZone, calendar,
increment, unit, roundingMode )
...
8. Let end be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], endDuration, constrain).
...
features: [Temporal]
---*/
var duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
var relativeTo = new Temporal.ZonedDateTime(864n * 10n**19n - 1n, "UTC");
var totalOf = {
unit: "years",
relativeTo,
};
assert.throws(RangeError, () => duration.total(totalOf));

View File

@ -0,0 +1,35 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.total
description: >
Throws RangeError when targetEpochNs is not a valid epoch nanoseconds value.
info: |
Temporal.Duration.prototype.total ( totalOf )
...
11. If zonedRelativeTo is not undefined, then
...
e. Let targetEpochNs be ? AddZonedDateTime(relativeEpochNs, timeZone, calendar,
internalDuration, constrain).
...
AddZonedDateTime ( epochNanoseconds, timeZone, calendar, duration, overflow )
1. If DateDurationSign(duration.[[Date]]) = 0, then
a. Return ? AddInstant(epochNanoseconds, duration.[[Time]]).
...
features: [Temporal]
---*/
var duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
var relativeTo = new Temporal.ZonedDateTime(864n * 10n**19n, "UTC");
var totalOf = {
unit: "nanoseconds",
relativeTo,
};
assert.throws(RangeError, () => duration.total(totalOf));