Browse Source

LibJS: Implement Date.prototype.setUTCMinutes

Timothy Flynn 3 years ago
parent
commit
2f202e8ef4

+ 38 - 1
Userland/Libraries/LibJS/Runtime/DatePrototype.cpp

@@ -76,7 +76,7 @@ void DatePrototype::initialize(GlobalObject& global_object)
     define_native_function(vm.names.setUTCFullYear, set_full_year, 3, attr);        // FIXME: see above
     define_native_function(vm.names.setUTCHours, set_hours, 4, attr);               // FIXME: see above
     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.setUTCMinutes, set_utc_minutes, 3, attr);
     define_native_function(vm.names.setUTCMonth, set_utc_month, 2, attr);
     define_native_function(vm.names.setUTCSeconds, set_utc_seconds, 2, attr);
     define_native_function(vm.names.toDateString, to_date_string, 0, attr);
@@ -619,6 +619,43 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_time)
     return time;
 }
 
+// 21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcminutes
+JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_minutes)
+{
+    // 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 m be ? ToNumber(min).
+    auto minute = TRY(vm.argument(0).to_number(global_object));
+
+    // 3. If sec is not present, let s be SecFromTime(t).
+    // 4. Else,
+    //     a. Let s be ? ToNumber(sec).
+    auto second = TRY(argument_or_value(global_object, 1, sec_from_time(time)));
+
+    // 5. If ms is not present, let milli be msFromTime(t).
+    // 6. Else,
+    //     a. Let milli be ? ToNumber(ms).
+    auto millisecond = TRY(argument_or_value(global_object, 2, ms_from_time(time)));
+
+    // 7. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)).
+    auto hour = Value(hour_from_time(time));
+
+    auto new_time = make_time(global_object, hour, minute, second, millisecond);
+    auto date = make_date(Value(day(time)), new_time);
+
+    // 8. Let v be TimeClip(date).
+    date = time_clip(global_object, date);
+
+    // 9. 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(date.as_double());
+
+    // 10. Return v.
+    return date;
+}
+
 // 21.4.4.33 Date.prototype.setUTCMonth ( month [ , date ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcmonth
 JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_month)
 {

+ 1 - 0
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_minutes);
     JS_DECLARE_NATIVE_FUNCTION(set_utc_month);
     JS_DECLARE_NATIVE_FUNCTION(set_utc_seconds);
     JS_DECLARE_NATIVE_FUNCTION(to_date_string);

+ 51 - 0
Userland/Libraries/LibJS/Tests/builtins/Date/Date.prototype.setUTCMinutes.js

@@ -0,0 +1,51 @@
+describe("errors", () => {
+    test("called on non-Date object", () => {
+        expect(() => {
+            Date.prototype.setUTCMinutes();
+        }).toThrowWithMessage(TypeError, "Not an object of type Date");
+    });
+
+    test("called with non-numeric parameters", () => {
+        expect(() => {
+            new Date().setUTCMinutes(Symbol.hasInstance);
+        }).toThrowWithMessage(TypeError, "Cannot convert symbol to number");
+
+        expect(() => {
+            new Date().setUTCMinutes(1989, Symbol.hasInstance);
+        }).toThrowWithMessage(TypeError, "Cannot convert symbol to number");
+    });
+});
+
+describe("correct behavior", () => {
+    const d = new Date(2000, 2, 1);
+
+    test("basic functionality", () => {
+        d.setUTCMinutes(8);
+        expect(d.getUTCMinutes()).toBe(8);
+
+        d.setUTCMinutes(9, 15);
+        expect(d.getUTCMinutes()).toBe(9);
+        expect(d.getUTCSeconds()).toBe(15);
+
+        d.setUTCMinutes(55, 44, 456);
+        expect(d.getUTCMinutes()).toBe(55);
+        expect(d.getUTCSeconds()).toBe(44);
+        expect(d.getUTCMilliseconds()).toBe(456);
+
+        d.setUTCMinutes("");
+        expect(d.getUTCMinutes()).toBe(0);
+
+        d.setUTCMinutes("a");
+        expect(d.getUTCMinutes()).toBe(NaN);
+    });
+
+    test("NaN", () => {
+        d.setUTCMinutes(NaN);
+        expect(d.getUTCMinutes()).toBeNaN();
+    });
+
+    test("time clip", () => {
+        d.setUTCMinutes(8.65e15);
+        expect(d.getUTCMinutes()).toBeNaN();
+    });
+});