From c71877b0a6b6e1ec2a605d7edaea2888a568cb4f Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 15 Jan 2022 15:32:27 -0500 Subject: [PATCH] LibJS: Implement Date.prototype.setUTCSeconds --- .../Libraries/LibJS/Runtime/DatePrototype.cpp | 35 +++++++++++++- .../Libraries/LibJS/Runtime/DatePrototype.h | 1 + .../Date/Date.prototype.setUTCSeconds.js | 46 +++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 Userland/Libraries/LibJS/Tests/builtins/Date/Date.prototype.setUTCSeconds.js diff --git a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp index b43a3a14e60..f1cfcbbfebf 100644 --- a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -78,7 +78,7 @@ void DatePrototype::initialize(GlobalObject& global_object) define_native_function(vm.names.setUTCMilliseconds, set_milliseconds, 1, attr); // FIXME: see above define_native_function(vm.names.setUTCMinutes, set_minutes, 3, attr); // FIXME: see above define_native_function(vm.names.setUTCMonth, set_month, 2, attr); // FIXME: see above - define_native_function(vm.names.setUTCSeconds, set_seconds, 2, attr); // FIXME: see above + define_native_function(vm.names.setUTCSeconds, set_utc_seconds, 2, attr); define_native_function(vm.names.toDateString, to_date_string, 0, attr); define_native_function(vm.names.toISOString, to_iso_string, 0, attr); define_native_function(vm.names.toJSON, to_json, 1, attr); @@ -619,6 +619,39 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_time) return time; } +// 21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcseconds +JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_seconds) +{ + // 1. Let t be ? thisTimeValue(this value). + auto this_time = TRY(this_time_value(global_object, vm.this_value(global_object))); + auto time = local_time(this_time.as_double()); + + // 2. Let s be ? ToNumber(sec). + auto second = TRY(vm.argument(0).to_number(global_object)); + + // 3. If ms is not present, let milli be msFromTime(t). + // 4. Else, + // a. Let milli be ? ToNumber(ms). + auto millisecond = TRY(argument_or_value(global_object, 1, ms_from_time(time))); + + // 5. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)). + auto hour = Value(hour_from_time(time)); + auto minute = Value(min_from_time(time)); + + auto new_time = make_time(global_object, hour, minute, second, millisecond); + auto new_date = make_date(Value(day(time)), new_time); + + // 6. Let v be TimeClip(date). + new_date = time_clip(global_object, new_date); + + // 7. Set the [[DateValue]] internal slot of this Date object to v. + auto* this_object = MUST(typed_this_object(global_object)); + this_object->set_date_value(new_date.as_double()); + + // 8. Return v. + return new_date; +} + // 21.4.4.35 Date.prototype.toDateString ( ), https://tc39.es/ecma262/#sec-date.prototype.todatestring JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_date_string) { diff --git a/Userland/Libraries/LibJS/Runtime/DatePrototype.h b/Userland/Libraries/LibJS/Runtime/DatePrototype.h index 1d2ab58b36b..21cc4001086 100644 --- a/Userland/Libraries/LibJS/Runtime/DatePrototype.h +++ b/Userland/Libraries/LibJS/Runtime/DatePrototype.h @@ -46,6 +46,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(set_month); JS_DECLARE_NATIVE_FUNCTION(set_seconds); JS_DECLARE_NATIVE_FUNCTION(set_time); + JS_DECLARE_NATIVE_FUNCTION(set_utc_seconds); JS_DECLARE_NATIVE_FUNCTION(to_date_string); JS_DECLARE_NATIVE_FUNCTION(to_iso_string); JS_DECLARE_NATIVE_FUNCTION(to_json); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Date/Date.prototype.setUTCSeconds.js b/Userland/Libraries/LibJS/Tests/builtins/Date/Date.prototype.setUTCSeconds.js new file mode 100644 index 00000000000..16b049bcdf3 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Date/Date.prototype.setUTCSeconds.js @@ -0,0 +1,46 @@ +describe("errors", () => { + test("called on non-Date object", () => { + expect(() => { + Date.prototype.setUTCSeconds(); + }).toThrowWithMessage(TypeError, "Not an object of type Date"); + }); + + test("called with non-numeric parameters", () => { + expect(() => { + new Date().setUTCSeconds(Symbol.hasInstance); + }).toThrowWithMessage(TypeError, "Cannot convert symbol to number"); + + expect(() => { + new Date().setUTCSeconds(1989, Symbol.hasInstance); + }).toThrowWithMessage(TypeError, "Cannot convert symbol to number"); + }); +}); + +describe("correct behavior", () => { + const d = new Date(2000, 2, 1); + + test("basic functionality", () => { + d.setUTCSeconds(50); + expect(d.getUTCSeconds()).toBe(50); + + d.setUTCSeconds(50, 600); + expect(d.getUTCSeconds()).toBe(50); + expect(d.getUTCMilliseconds()).toBe(600); + + d.setUTCSeconds(""); + expect(d.getUTCSeconds()).toBe(0); + + d.setUTCSeconds("a"); + expect(d.getUTCSeconds()).toBe(NaN); + }); + + test("NaN", () => { + d.setUTCSeconds(NaN); + expect(d.getUTCSeconds()).toBeNaN(); + }); + + test("time clip", () => { + d.setUTCSeconds(8.65e15); + expect(d.getUTCSeconds()).toBeNaN(); + }); +});