Skip to content

Commit

Permalink
Temporal: Coverage for Temporal.Duration
Browse files Browse the repository at this point in the history
  • Loading branch information
anba committed Dec 12, 2024
1 parent feeddb5 commit 94cf340
Show file tree
Hide file tree
Showing 14 changed files with 603 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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));
Original file line number Diff line number Diff line change
@@ -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`));
72 changes: 72 additions & 0 deletions test/built-ins/Temporal/Duration/from/get-property-throws.js
Original file line number Diff line number Diff line change
@@ -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}`
);
}
70 changes: 70 additions & 0 deletions test/built-ins/Temporal/Duration/from/invalid-type.js
Original file line number Diff line number Diff line change
@@ -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)}`
);
}
}
Original file line number Diff line number Diff line change
@@ -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)
});
44 changes: 44 additions & 0 deletions test/built-ins/Temporal/Duration/invalid-type.js
Original file line number Diff line number Diff line change
@@ -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));
}
31 changes: 31 additions & 0 deletions test/built-ins/Temporal/Duration/large-number.js
Original file line number Diff line number Diff line change
@@ -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));
Original file line number Diff line number Diff line change
@@ -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));
Loading

0 comments on commit 94cf340

Please sign in to comment.