summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-09-06 21:28:06 +0300
committerLinus Groh <mail@linusgroh.de>2021-09-06 22:15:39 +0100
commit470499b2a88b88098f2a1e2252cdada61a236002 (patch)
treedae185a22831b1dad728005c82307bee77fc5cd5 /Userland
parent24b78fff7db473de34473fa980687c5535533d8c (diff)
downloadserenity-470499b2a88b88098f2a1e2252cdada61a236002.zip
LibJS: Implement Temporal.Instant.prototype.until
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp61
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h1
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js20
4 files changed, 83 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
index 6edf4c61bd..ff7a1d11f1 100644
--- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
+++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
@@ -443,6 +443,7 @@ namespace JS {
P(undefined) \
P(unescape) \
P(unicode) \
+ P(until) \
P(unregister) \
P(unshift) \
P(value) \
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
index 278f09d4e6..a56c940df8 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
@@ -38,6 +38,7 @@ void InstantPrototype::initialize(GlobalObject& global_object)
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(vm.names.add, add, 1, attr);
define_native_function(vm.names.subtract, subtract, 1, attr);
+ define_native_function(vm.names.until, until, 1, attr);
define_native_function(vm.names.round, round, 1, attr);
define_native_function(vm.names.equals, equals, 1, attr);
define_native_function(vm.names.toString, to_string, 0, attr);
@@ -182,6 +183,66 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::subtract)
return create_temporal_instant(global_object, *ns);
}
+// 8.3.9 Temporal.Instant.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.until
+JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::until)
+{
+ // 1. Let instant be the this value.
+ // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
+ auto* instant = typed_this(global_object);
+ if (vm.exception())
+ return {};
+
+ // 3. Set other to ? ToTemporalInstant(other).
+ auto* other = to_temporal_instant(global_object, vm.argument(0));
+ if (vm.exception())
+ return {};
+
+ // 4. Set options to ? GetOptionsObject(options).
+ auto* options = get_options_object(global_object, vm.argument(1));
+ if (vm.exception())
+ return {};
+
+ // 5. Let smallestUnit be ? ToSmallestTemporalUnit(options, « "year", "month", "week", "day" », "nanosecond").
+ auto smallest_unit = to_smallest_temporal_unit(global_object, *options, { "year"sv, "month"sv, "week"sv, "day"sv }, "nanosecond"sv);
+ if (vm.exception())
+ return {};
+
+ // 6. Let defaultLargestUnit be ! LargerOfTwoTemporalUnits("second", smallestUnit).
+ auto default_largest_unit = larger_of_two_temporal_units("second"sv, *smallest_unit);
+
+ // 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "year", "month", "week", "day" », "auto", defaultLargestUnit).
+ auto largest_unit = to_largest_temporal_unit(global_object, *options, { "year"sv, "month"sv, "week"sv, "day"sv }, "auto"sv, move(default_largest_unit));
+ if (vm.exception())
+ return {};
+
+ // 8. Perform ? ValidateTemporalUnitRange(largestUnit, smallestUnit).
+ validate_temporal_unit_range(global_object, *largest_unit, *smallest_unit);
+ if (vm.exception())
+ return {};
+
+ // 9. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
+ auto rounding_mode = to_temporal_rounding_mode(global_object, *options, "trunc"sv);
+ if (vm.exception())
+ return {};
+
+ // 10. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit).
+ auto maximum = maximum_temporal_duration_rounding_increment(*smallest_unit);
+
+ // 11. Let roundingIncrement be ? ToTemporalRoundingIncrement(options, maximum, false).
+ auto rounding_increment = to_temporal_rounding_increment(global_object, *options, *maximum, false);
+ if (vm.exception())
+ return {};
+
+ // 12. Let roundedNs be ! DifferenceInstant(instant.[[Nanoseconds]], other.[[Nanoseconds]], roundingIncrement, smallestUnit, roundingMode).
+ auto rounded_ns = difference_instant(global_object, instant->nanoseconds(), other->nanoseconds(), rounding_increment, *smallest_unit, *rounding_mode);
+
+ // 13. Let result be ! BalanceDuration(0, 0, 0, 0, 0, 0, roundedNs, largestUnit).
+ auto result = balance_duration(global_object, 0, 0, 0, 0, 0, 0, *rounded_ns, *largest_unit);
+
+ // 14. Return ? CreateTemporalDuration(0, 0, 0, 0, result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
+ return create_temporal_duration(global_object, 0, 0, 0, 0, result->hours, result->minutes, result->seconds, result->milliseconds, result->microseconds, result->nanoseconds);
+}
+
// 8.3.11 Temporal.Instant.prototype.round ( options ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.round
JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::round)
{
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
index 6149e6a7f6..294df67aa7 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
@@ -25,6 +25,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(epoch_nanoseconds_getter);
JS_DECLARE_NATIVE_FUNCTION(add);
JS_DECLARE_NATIVE_FUNCTION(subtract);
+ JS_DECLARE_NATIVE_FUNCTION(until);
JS_DECLARE_NATIVE_FUNCTION(round);
JS_DECLARE_NATIVE_FUNCTION(equals);
JS_DECLARE_NATIVE_FUNCTION(to_string);
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js
new file mode 100644
index 0000000000..28a9ba7a5b
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js
@@ -0,0 +1,20 @@
+describe("correct behavior", () => {
+ test("length is 1", () => {
+ expect(Temporal.Instant.prototype.until).toHaveLength(1);
+ });
+
+ test("basic functionality", () => {
+ const instant1 = new Temporal.Instant(0n);
+ const instant2 = new Temporal.Instant(1625614920000000000n);
+ expect(instant1.until(instant2).seconds).toBe(1625614920);
+ expect(instant1.until(instant2, { largestUnit: "hour" }).hours).toBe(27093582);
+ });
+});
+
+describe("errors", () => {
+ test("this value must be a Temporal.Instant object", () => {
+ expect(() => {
+ Temporal.Instant.prototype.until.call("foo");
+ }).toThrowWithMessage(TypeError, "Not a Temporal.Instant");
+ });
+});