diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp index c09bb580cd..0ae4f4f970 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp @@ -312,6 +312,30 @@ Value calendar_era(GlobalObject& global_object, Object& calendar, Object& date_l return result; } +// 15.6.1.3 CalendarEraYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarerayear +Value calendar_era_year(GlobalObject& global_object, Object& calendar, Object& date_like) +{ + auto& vm = global_object.vm(); + + // 1. Assert: Type(calendar) is Object. + + // 2. Let result be ? Invoke(calendar, "eraYear", « dateLike »). + auto result = Value(&calendar).invoke(global_object, vm.names.eraYear, &date_like); + if (vm.exception()) + return {}; + + // 3. If result is not undefined, set result to ? ToIntegerOrInfinity(result). + if (!result.is_undefined()) { + auto result_number = result.to_integer_or_infinity(global_object); + if (vm.exception()) + return {}; + result = Value(result_number); + } + + // 4. Return result. + return result; +} + // 12.1.21 ToTemporalCalendar ( temporalCalendarLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalcalendar Object* to_temporal_calendar(GlobalObject& global_object, Value temporal_calendar_like) { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h index bc650c5050..4ccf1a05b3 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h @@ -47,6 +47,7 @@ Value calendar_days_in_year(GlobalObject&, Object& calendar, Object& date_like); Value calendar_months_in_year(GlobalObject&, Object& calendar, Object& date_like); Value calendar_in_leap_year(GlobalObject&, Object& calendar, Object& date_like); Value calendar_era(GlobalObject&, Object& calendar, Object& date_like); +Value calendar_era_year(GlobalObject&, Object& calendar, Object& date_like); Object* to_temporal_calendar(GlobalObject&, Value); Object* to_temporal_calendar_with_iso_default(GlobalObject&, Value); Object* get_temporal_calendar_with_iso_default(GlobalObject&, Object&); diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp index bb34a836f0..258cd26112 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp @@ -47,6 +47,7 @@ void PlainDatePrototype::initialize(GlobalObject& global_object) define_native_accessor(vm.names.monthsInYear, months_in_year_getter, {}, Attribute::Configurable); define_native_accessor(vm.names.inLeapYear, in_leap_year_getter, {}, Attribute::Configurable); define_native_accessor(vm.names.era, era_getter, {}, Attribute::Configurable); + define_native_accessor(vm.names.eraYear, era_year_getter, {}, Attribute::Configurable); u8 attr = Attribute::Writable | Attribute::Configurable; define_native_function(vm.names.toPlainYearMonth, to_plain_year_month, 0, attr); @@ -295,6 +296,22 @@ JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::era_getter) return calendar_era(global_object, calendar, *plain_date); } +// 15.6.5.3 get Temporal.PlainDate.prototype.eraYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.erayear +JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::era_year_getter) +{ + // 1. Let plainDate be the this value. + // 2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]). + auto* plain_date = typed_this(global_object); + if (vm.exception()) + return {}; + + // 3. Let calendar be plainDate.[[Calendar]]. + auto& calendar = plain_date->calendar(); + + // 4. Return ? CalendarEraYear(calendar, plainDate). + return calendar_era_year(global_object, calendar, *plain_date); +} + // 3.3.16 Temporal.PlainDate.prototype.toPlainYearMonth ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.toplainyearmonth JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_plain_year_month) { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h index 761cac41b6..196199d3de 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h @@ -33,6 +33,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(months_in_year_getter); JS_DECLARE_NATIVE_FUNCTION(in_leap_year_getter); JS_DECLARE_NATIVE_FUNCTION(era_getter); + JS_DECLARE_NATIVE_FUNCTION(era_year_getter); JS_DECLARE_NATIVE_FUNCTION(to_plain_year_month); JS_DECLARE_NATIVE_FUNCTION(to_plain_month_day); JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.eraYear.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.eraYear.js new file mode 100644 index 0000000000..d3d98f6b36 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.eraYear.js @@ -0,0 +1,24 @@ +describe("correct behavior", () => { + test("basic functionality", () => { + const plainDate = new Temporal.PlainDate(2021, 7, 6); + expect(plainDate.eraYear).toBeUndefined(); + }); + + test("calendar with custom eraYear function", () => { + const calendar = { + eraYear() { + return 123; + }, + }; + const plainDate = new Temporal.PlainDate(2021, 7, 6, calendar); + expect(plainDate.eraYear).toBe(123); + }); +}); + +describe("errors", () => { + test("this value must be a Temporal.PlainDate object", () => { + expect(() => { + Reflect.get(Temporal.PlainDate.prototype, "eraYear", "foo"); + }).toThrowWithMessage(TypeError, "Not a Temporal.PlainDate"); + }); +});