瀏覽代碼

LibJS: Implement Temporal.PlainDate.prototype.equals & Required AO

Idan Horowitz 4 年之前
父節點
當前提交
d804ce830d

+ 25 - 0
Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp

@@ -231,6 +231,31 @@ PlainDate* date_from_fields(GlobalObject& global_object, Object& calendar, Objec
     return static_cast<PlainDate*>(date_object);
     return static_cast<PlainDate*>(date_object);
 }
 }
 
 
+// 12.1.28 CalendarEquals ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal-calendarequals
+bool calendar_equals(GlobalObject& global_object, Object& one, Object& two)
+{
+    auto& vm = global_object.vm();
+
+    // 1. If one and two are the same Object value, return true.
+    if (&one == &two)
+        return true;
+
+    // 2. Let calendarOne be ? ToString(one).
+    auto calendar_one = Value(&one).to_string(global_object);
+    if (vm.exception())
+        return {};
+    // 3. Let calendarTwo be ? ToString(two).
+    auto calendar_two = Value(&two).to_string(global_object);
+    if (vm.exception())
+        return {};
+
+    // 4. If calendarOne is calendarTwo, return true.
+    if (calendar_one == calendar_two)
+        return true;
+    // 5. Return false.
+    return false;
+}
+
 // 12.1.30 IsISOLeapYear ( year ), https://tc39.es/proposal-temporal/#sec-temporal-isisoleapyear
 // 12.1.30 IsISOLeapYear ( year ), https://tc39.es/proposal-temporal/#sec-temporal-isisoleapyear
 bool is_iso_leap_year(i32 year)
 bool is_iso_leap_year(i32 year)
 {
 {

+ 1 - 0
Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h

@@ -38,6 +38,7 @@ Object* to_temporal_calendar(GlobalObject&, Value);
 Object* to_temporal_calendar_with_iso_default(GlobalObject&, Value);
 Object* to_temporal_calendar_with_iso_default(GlobalObject&, Value);
 Object* get_temporal_calendar_with_iso_default(GlobalObject&, Object&);
 Object* get_temporal_calendar_with_iso_default(GlobalObject&, Object&);
 PlainDate* date_from_fields(GlobalObject&, Object& calendar, Object& fields, Object& options);
 PlainDate* date_from_fields(GlobalObject&, Object& calendar, Object& fields, Object& options);
+bool calendar_equals(GlobalObject&, Object& one, Object& two);
 bool is_iso_leap_year(i32 year);
 bool is_iso_leap_year(i32 year);
 i32 iso_days_in_month(i32 year, i32 month);
 i32 iso_days_in_month(i32 year, i32 month);
 String build_iso_month_code(i32 month);
 String build_iso_month_code(i32 month);

+ 29 - 0
Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp

@@ -5,6 +5,7 @@
  */
  */
 
 
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/Temporal/Calendar.h>
 #include <LibJS/Runtime/Temporal/PlainDate.h>
 #include <LibJS/Runtime/Temporal/PlainDate.h>
 #include <LibJS/Runtime/Temporal/PlainDatePrototype.h>
 #include <LibJS/Runtime/Temporal/PlainDatePrototype.h>
 
 
@@ -28,6 +29,7 @@ void PlainDatePrototype::initialize(GlobalObject& global_object)
     define_native_accessor(vm.names.calendar, calendar_getter, {}, Attribute::Configurable);
     define_native_accessor(vm.names.calendar, calendar_getter, {}, Attribute::Configurable);
 
 
     u8 attr = Attribute::Writable | Attribute::Configurable;
     u8 attr = Attribute::Writable | Attribute::Configurable;
+    define_native_function(vm.names.equals, equals, 1, attr);
     define_native_function(vm.names.valueOf, value_of, 0, attr);
     define_native_function(vm.names.valueOf, value_of, 0, attr);
 }
 }
 
 
@@ -57,6 +59,33 @@ JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::calendar_getter)
     return Value(&temporal_date->calendar());
     return Value(&temporal_date->calendar());
 }
 }
 
 
+// 3.3.25 Temporal.PlainDate.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.equals
+JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::equals)
+{
+    // 1. Let temporalDate be the this value.
+    // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
+    auto* temporal_date = typed_this(global_object);
+    if (vm.exception())
+        return {};
+
+    // 3. Set other to ? ToTemporalDate(other).
+    auto* other = to_temporal_date(global_object, vm.argument(0));
+    if (vm.exception())
+        return {};
+
+    // 4. If temporalDate.[[ISOYear]] ≠ other.[[ISOYear]], return false.
+    if (temporal_date->iso_year() != other->iso_year())
+        return Value(false);
+    // 5. If temporalDate.[[ISOMonth]] ≠ other.[[ISOMonth]], return false.
+    if (temporal_date->iso_month() != other->iso_month())
+        return Value(false);
+    // 6. If temporalDate.[[ISODay]] ≠ other.[[ISODay]], return false.
+    if (temporal_date->iso_day() != other->iso_day())
+        return Value(false);
+    // 7. Return ? CalendarEquals(temporalDate.[[Calendar]], other.[[Calendar]]).
+    return Value(calendar_equals(global_object, temporal_date->calendar(), other->calendar()));
+}
+
 // 3.3.31 Temporal.PlainDate.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.valueof
 // 3.3.31 Temporal.PlainDate.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.valueof
 JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::value_of)
 JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::value_of)
 {
 {

+ 1 - 0
Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h

@@ -21,6 +21,7 @@ public:
 private:
 private:
     JS_DECLARE_NATIVE_FUNCTION(calendar_getter);
     JS_DECLARE_NATIVE_FUNCTION(calendar_getter);
 
 
+    JS_DECLARE_NATIVE_FUNCTION(equals);
     JS_DECLARE_NATIVE_FUNCTION(value_of);
     JS_DECLARE_NATIVE_FUNCTION(value_of);
 };
 };
 
 

+ 13 - 0
Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.equals.js

@@ -0,0 +1,13 @@
+describe("correct behavior", () => {
+    test("length is 1", () => {
+        expect(Temporal.PlainDate.prototype.equals).toHaveLength(1);
+    });
+
+    test("basic functionality", () => {
+        const calendar = { hello: "friends" };
+        const first_plain_date = new Temporal.PlainDate(1, 1, 1, calendar);
+        const second_plain_date = new Temporal.PlainDate(0, 1, 1, calendar);
+        expect(first_plain_date.equals(first_plain_date));
+        expect(!first_plain_date.equals(second_plain_date));
+    });
+});