Skip to content

Commit

Permalink
Bug 1868962 - Part 17: Add PlainDateWithCalendar. r=allstarschh
Browse files Browse the repository at this point in the history
Similar to parts 2 and 13, add a class to replace `PlainDateObject` when no
allocations are necessary.

Differential Revision: https://phabricator.services.mozilla.com/D195880
  • Loading branch information
anba committed Dec 15, 2023
1 parent 4d83366 commit 88ce2b7
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 57 deletions.
14 changes: 14 additions & 0 deletions js/src/builtin/temporal/Calendar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,20 @@ bool js::temporal::CalendarDay(JSContext* cx, Handle<CalendarValue> calendar,
return CalendarDay(cx, calendar, dateLike, ToPlainDate(dateLike), result);
}

/**
* CalendarDay ( calendar, dateLike )
*/
bool js::temporal::CalendarDay(JSContext* cx, Handle<CalendarValue> calendar,
const PlainDate& date,
MutableHandle<Value> result) {
Rooted<PlainDateObject*> dateLike(cx, CreateTemporalDate(cx, date, calendar));
if (!dateLike) {
return false;
}

return ::CalendarDay(cx, calendar, dateLike, date, result);
}

/**
* CalendarDay ( calendar, dateLike )
*/
Expand Down
6 changes: 6 additions & 0 deletions js/src/builtin/temporal/Calendar.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@ bool CalendarDay(JSContext* cx, JS::Handle<CalendarValue> calendar,
JS::Handle<PlainMonthDayObject*> dateLike,
JS::MutableHandle<JS::Value> result);

/**
* CalendarDay ( calendar, dateLike )
*/
bool CalendarDay(JSContext* cx, JS::Handle<CalendarValue> calendar,
const PlainDate& date, JS::MutableHandle<JS::Value> result);

/**
* CalendarDay ( calendar, dateLike )
*/
Expand Down
51 changes: 37 additions & 14 deletions js/src/builtin/temporal/PlainDate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,29 @@ PlainDateObject* js::temporal::CreateTemporalDate(
return object;
}

/**
* CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
*/
bool js::temporal::CreateTemporalDate(
JSContext* cx, const PlainDate& date, Handle<CalendarValue> calendar,
MutableHandle<PlainDateWithCalendar> result) {
// Step 1.
if (!ThrowIfInvalidISODate(cx, date)) {
return false;
}

// Step 2.
if (!ISODateTimeWithinLimits(date)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TEMPORAL_PLAIN_DATE_INVALID);
return false;
}

// Steps 3-9.
result.set(PlainDateWithCalendar{date, calendar});
return true;
}

/**
* ToTemporalDate ( item [ , options ] )
*/
Expand Down Expand Up @@ -546,16 +569,20 @@ bool js::temporal::ToTemporalDate(JSContext* cx, Handle<Value> item,
* ToTemporalDate ( item [ , options ] )
*/
bool js::temporal::ToTemporalDate(JSContext* cx, Handle<Value> item,
PlainDate* result,
MutableHandle<CalendarValue> calendar) {
MutableHandle<PlainDateWithCalendar> result) {
auto* obj = ::ToTemporalDate(cx, item, nullptr).unwrapOrNull();
if (!obj) {
return false;
}

*result = ToPlainDate(obj);
calendar.set(obj->calendar());
return calendar.wrap(cx);
auto date = ToPlainDate(obj);
Rooted<CalendarValue> calendar(cx, obj->calendar());
if (!calendar.wrap(cx)) {
return false;
}

result.set(PlainDateWithCalendar{date, calendar});
return true;
}

/**
Expand Down Expand Up @@ -2529,19 +2556,15 @@ static bool PlainDate_equals(JSContext* cx, const CallArgs& args) {
Rooted<CalendarValue> calendar(cx, temporalDate->calendar());

// Step 3.
PlainDate other;
Rooted<CalendarValue> otherCalendar(cx);
if (!ToTemporalDate(cx, args.get(0), &other, &otherCalendar)) {
Rooted<PlainDateWithCalendar> other(cx);
if (!ToTemporalDate(cx, args.get(0), &other)) {
return false;
}

// Steps 4-7.
bool equals = false;
if (date.year == other.year && date.month == other.month &&
date.day == other.day) {
if (!CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}
bool equals = date == other.date();
if (equals && !CalendarEquals(cx, calendar, other.calendar(), &equals)) {
return false;
}

args.rval().setBoolean(equals);
Expand Down
50 changes: 48 additions & 2 deletions js/src/builtin/temporal/PlainDate.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <stdint.h>

#include "builtin/temporal/Calendar.h"
#include "builtin/temporal/PlainDateTime.h"
#include "builtin/temporal/TemporalTypes.h"
#include "builtin/temporal/Wrapped.h"
#include "js/TypeDecls.h"
Expand Down Expand Up @@ -53,6 +54,26 @@ class PlainDateObject : public NativeObject {
static const ClassSpec classSpec_;
};

class PlainDateWithCalendar {
PlainDate date_;
CalendarValue calendar_;

public:
PlainDateWithCalendar() = default;

PlainDateWithCalendar(const PlainDate& date, const CalendarValue& calendar)
: date_(date), calendar_(calendar) {
MOZ_ASSERT(ISODateTimeWithinLimits(date));
}

const auto& date() const { return date_; }
const auto& calendar() const { return calendar_; }

void trace(JSTracer* trc) { calendar_.trace(trc); }

const auto* calendarDoNotUse() const { return &calendar_; }
};

/**
* Extract the date fields from the PlainDate object.
*/
Expand Down Expand Up @@ -98,15 +119,21 @@ bool ToTemporalDate(JSContext* cx, JS::Handle<JS::Value> item,
* ToTemporalDate ( item [ , options ] )
*/
bool ToTemporalDate(JSContext* cx, JS::Handle<JS::Value> item,
PlainDate* result,
JS::MutableHandle<CalendarValue> calendar);
JS::MutableHandle<PlainDateWithCalendar> result);

/**
* CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
*/
PlainDateObject* CreateTemporalDate(JSContext* cx, const PlainDate& date,
JS::Handle<CalendarValue> calendar);

/**
* CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
*/
bool CreateTemporalDate(JSContext* cx, const PlainDate& date,
JS::Handle<CalendarValue> calendar,
JS::MutableHandle<PlainDateWithCalendar> result);

/**
* RegulateISODate ( year, month, day, overflow )
*/
Expand Down Expand Up @@ -244,4 +271,23 @@ bool IsBuiltinAccess(JSContext* cx, JS::Handle<PlainDateObject*> date,

} /* namespace js::temporal */

namespace js {

template <typename Wrapper>
class WrappedPtrOperations<temporal::PlainDateWithCalendar, Wrapper> {
const auto& container() const {
return static_cast<const Wrapper*>(this)->get();
}

public:
const auto& date() const { return container().date(); }

JS::Handle<temporal::CalendarValue> calendar() const {
return JS::Handle<temporal::CalendarValue>::fromMarkedLocation(
container().calendarDoNotUse());
}
};

} // namespace js

#endif /* builtin_temporal_PlainDate_h */
16 changes: 7 additions & 9 deletions js/src/builtin/temporal/PlainDateTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1930,14 +1930,14 @@ static bool PlainDateTime_withPlainDate(JSContext* cx, const CallArgs& args) {
Rooted<CalendarValue> calendar(cx, temporalDateTime->calendar());

// Step 3.
PlainDate date;
Rooted<CalendarValue> dateCalendar(cx);
if (!ToTemporalDate(cx, args.get(0), &date, &dateCalendar)) {
Rooted<PlainDateWithCalendar> plainDate(cx);
if (!ToTemporalDate(cx, args.get(0), &plainDate)) {
return false;
}
auto date = plainDate.date();

// Step 4.
if (!ConsolidateCalendars(cx, calendar, dateCalendar, &calendar)) {
if (!ConsolidateCalendars(cx, calendar, plainDate.calendar(), &calendar)) {
return false;
}

Expand Down Expand Up @@ -2194,11 +2194,9 @@ static bool PlainDateTime_equals(JSContext* cx, const CallArgs& args) {
}

// Steps 4-13.
bool equals = false;
if (CompareISODateTime(dateTime, other) == 0) {
if (!CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}
bool equals = dateTime == other;
if (equals && !CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}

args.rval().setBoolean(equals);
Expand Down
8 changes: 3 additions & 5 deletions js/src/builtin/temporal/PlainMonthDay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,11 +631,9 @@ static bool PlainMonthDay_equals(JSContext* cx, const CallArgs& args) {
}

// Steps 4-7.
bool equals = false;
if (date == other) {
if (!CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}
bool equals = date == other;
if (equals && !CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}

args.rval().setBoolean(equals);
Expand Down
14 changes: 8 additions & 6 deletions js/src/builtin/temporal/PlainTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2270,11 +2270,12 @@ static bool PlainTime_toPlainDateTime(JSContext* cx, const CallArgs& args) {
auto time = ToPlainTime(temporalTime);

// Step 3.
PlainDate date;
Rooted<CalendarValue> calendar(cx);
if (!ToTemporalDate(cx, args.get(0), &date, &calendar)) {
Rooted<PlainDateWithCalendar> plainDate(cx);
if (!ToTemporalDate(cx, args.get(0), &plainDate)) {
return false;
}
auto date = plainDate.date();
auto calendar = plainDate.calendar();

// Step 4.
auto* result = CreateTemporalDateTime(cx, {date, time}, calendar);
Expand Down Expand Up @@ -2326,11 +2327,12 @@ static bool PlainTime_toZonedDateTime(JSContext* cx, const CallArgs& args) {
}

// Step 6.
PlainDate date;
Rooted<CalendarValue> calendar(cx);
if (!ToTemporalDate(cx, temporalDateLike, &date, &calendar)) {
Rooted<PlainDateWithCalendar> plainDate(cx);
if (!ToTemporalDate(cx, temporalDateLike, &plainDate)) {
return false;
}
auto date = plainDate.date();
auto calendar = plainDate.calendar();

// Step 7.
Rooted<Value> temporalTimeZoneLike(cx);
Expand Down
15 changes: 6 additions & 9 deletions js/src/builtin/temporal/PlainYearMonth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,15 +625,14 @@ static bool AddDurationToOrSubtractDurationFromPlainYearMonth(
// FIXME: spec bug - CreateTemporalDate is fallible

// Step 12.d.
Rooted<PlainDateObject*> endOfMonth(
cx, CreateTemporalDate(cx, endOfMonthISO, calendar));
if (!endOfMonth) {
Rooted<PlainDateWithCalendar> endOfMonth(cx);
if (!CreateTemporalDate(cx, endOfMonthISO, calendar, &endOfMonth)) {
return false;
}

// Step 12.e.
Rooted<Value> day(cx);
if (!CalendarDay(cx, calendar, endOfMonth, &day)) {
if (!CalendarDay(cx, calendar, endOfMonth.date(), &day)) {
return false;
}

Expand Down Expand Up @@ -1206,11 +1205,9 @@ static bool PlainYearMonth_equals(JSContext* cx, const CallArgs& args) {
}

// Steps 4-7.
bool equals = false;
if (date == other) {
if (!CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}
bool equals = date == other;
if (equals && !CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}

args.rval().setBoolean(equals);
Expand Down
20 changes: 8 additions & 12 deletions js/src/builtin/temporal/ZonedDateTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2896,11 +2896,11 @@ static bool ZonedDateTime_withPlainDate(JSContext* cx, const CallArgs& args) {
Rooted<TimeZoneValue> timeZone(cx, zonedDateTime->timeZone());

// Step 3.
PlainDate date;
Rooted<CalendarValue> plainDateCalendar(cx);
if (!ToTemporalDate(cx, args.get(0), &date, &plainDateCalendar)) {
Rooted<PlainDateWithCalendar> plainDate(cx);
if (!ToTemporalDate(cx, args.get(0), &plainDate)) {
return false;
}
auto date = plainDate.date();

// Steps 5-6.
PlainDateTime plainDateTime;
Expand All @@ -2909,7 +2909,7 @@ static bool ZonedDateTime_withPlainDate(JSContext* cx, const CallArgs& args) {
}

// Step 7.
if (!ConsolidateCalendars(cx, calendar, plainDateCalendar, &calendar)) {
if (!ConsolidateCalendars(cx, calendar, plainDate.calendar(), &calendar)) {
return false;
}

Expand Down Expand Up @@ -3283,15 +3283,11 @@ static bool ZonedDateTime_equals(JSContext* cx, const CallArgs& args) {

// Steps 4-6.
bool equals = epochNanoseconds == otherEpochNanoseconds;
if (equals) {
if (!TimeZoneEquals(cx, timeZone, otherTimeZone, &equals)) {
return false;
}
if (equals && !TimeZoneEquals(cx, timeZone, otherTimeZone, &equals)) {
return false;
}
if (equals) {
if (!CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}
if (equals && !CalendarEquals(cx, calendar, otherCalendar, &equals)) {
return false;
}

args.rval().setBoolean(equals);
Expand Down

0 comments on commit 88ce2b7

Please sign in to comment.