diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h index 485968ccb6..95be6f7be9 100644 --- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -246,6 +246,7 @@ namespace JS { P(multiline) \ P(name) \ P(nanoseconds) \ + P(negated) \ P(next) \ P(now) \ P(of) \ diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp index cff8eb430a..1e8aa8942b 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp @@ -40,6 +40,7 @@ void DurationPrototype::initialize(GlobalObject& global_object) u8 attr = Attribute::Writable | Attribute::Configurable; define_native_function(vm.names.with, with, 1, attr); + define_native_function(vm.names.negated, negated, 0, attr); define_native_function(vm.names.valueOf, value_of, 0, attr); } @@ -297,6 +298,19 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::with) return create_temporal_duration(global_object, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } +// 7.3.16 Temporal.Duration.prototype.negated ( ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.negated +JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::negated) +{ + // 1. Let duration be the this value. + // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + auto* duration = typed_this(global_object); + if (vm.exception()) + return {}; + + // 3. Return ? CreateTemporalDuration(−duration.[[Years]], −duration.[[Months]], −duration.[[Weeks]], −duration.[[Days]], −duration.[[Hours]], −duration.[[Minutes]], −duration.[[Seconds]], −duration.[[Milliseconds]], −duration.[[Microseconds]], −duration.[[Nanoseconds]]). + return create_temporal_duration(global_object, -duration->years(), -duration->months(), -duration->weeks(), -duration->days(), -duration->hours(), -duration->minutes(), -duration->seconds(), -duration->milliseconds(), -duration->microseconds(), -duration->nanoseconds()); +} + // 7.3.25 Temporal.Duration.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.valueof JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::value_of) { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h index 507b5c9c83..7d57107905 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h @@ -32,6 +32,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(sign_getter); JS_DECLARE_NATIVE_FUNCTION(blank_getter); JS_DECLARE_NATIVE_FUNCTION(with); + JS_DECLARE_NATIVE_FUNCTION(negated); JS_DECLARE_NATIVE_FUNCTION(value_of); }; diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.negated.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.negated.js new file mode 100644 index 0000000000..f62a07c368 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.negated.js @@ -0,0 +1,42 @@ +const DURATION_PROPERTIES = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; + +describe("correct behavior", () => { + test("length is 0", () => { + expect(Temporal.Duration.prototype.negated).toHaveLength(0); + }); + + test("basic functionality", () => { + const negativeDuration = new Temporal.Duration(123).negated(); + expect(negativeDuration.years).toBe(-123); + + const positiveDuration = new Temporal.Duration(-123).negated(); + expect(positiveDuration.years).toBe(123); + }); + + test("each property is negated", () => { + const values = Array(DURATION_PROPERTIES.length).fill(1); + const duration = new Temporal.Duration(...values).negated(); + for (const property of DURATION_PROPERTIES) { + expect(duration[property]).toBe(-1); + } + }); +}); + +test("errors", () => { + test("this value must be a Temporal.Duration object", () => { + expect(() => { + Temporal.Duration.prototype.negated.call("foo"); + }).toThrowWithMessage(TypeError, "Not a Temporal.Duration"); + }); +});