1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef builtin_temporal_PlainDate_h
8 #define builtin_temporal_PlainDate_h
10 #include "mozilla/Assertions.h"
12 #include <initializer_list>
15 #include "builtin/temporal/Calendar.h"
16 #include "builtin/temporal/PlainDateTime.h"
17 #include "builtin/temporal/TemporalTypes.h"
18 #include "builtin/temporal/Wrapped.h"
19 #include "js/RootingAPI.h"
20 #include "js/TypeDecls.h"
22 #include "vm/NativeObject.h"
24 class JS_PUBLIC_API JSTracer
;
31 namespace js::temporal
{
33 class PlainDateObject
: public NativeObject
{
35 static const JSClass class_
;
36 static const JSClass
& protoClass_
;
38 // TODO: Consider compacting fields to reduce object size.
40 // ceil(log2(271821)) + ceil(log2(12)) + ceil(log2(31)) = 28 bits are
41 // needed to store a date value in a single int32.
43 static constexpr uint32_t ISO_YEAR_SLOT
= 0;
44 static constexpr uint32_t ISO_MONTH_SLOT
= 1;
45 static constexpr uint32_t ISO_DAY_SLOT
= 2;
46 static constexpr uint32_t CALENDAR_SLOT
= 3;
47 static constexpr uint32_t SLOT_COUNT
= 4;
49 int32_t isoYear() const { return getFixedSlot(ISO_YEAR_SLOT
).toInt32(); }
51 int32_t isoMonth() const { return getFixedSlot(ISO_MONTH_SLOT
).toInt32(); }
53 int32_t isoDay() const { return getFixedSlot(ISO_DAY_SLOT
).toInt32(); }
55 CalendarValue
calendar() const {
56 return CalendarValue(getFixedSlot(CALENDAR_SLOT
));
60 static const ClassSpec classSpec_
;
63 class PlainDateWithCalendar
{
65 CalendarValue calendar_
;
68 PlainDateWithCalendar() = default;
70 PlainDateWithCalendar(const PlainDate
& date
, const CalendarValue
& calendar
)
71 : date_(date
), calendar_(calendar
) {
72 MOZ_ASSERT(ISODateTimeWithinLimits(date
));
75 const auto& date() const { return date_
; }
76 const auto& calendar() const { return calendar_
; }
78 // Allow implicit conversion to a calendar-less PlainDate.
79 operator const PlainDate
&() const { return date(); }
81 void trace(JSTracer
* trc
) { calendar_
.trace(trc
); }
83 const auto* calendarDoNotUse() const { return &calendar_
; }
87 * Extract the date fields from the PlainDate object.
89 inline PlainDate
ToPlainDate(const PlainDateObject
* date
) {
90 return {date
->isoYear(), date
->isoMonth(), date
->isoDay()};
93 enum class TemporalOverflow
;
94 enum class TemporalUnit
;
96 class ZonedDateTimeObject
;
100 * IsValidISODate ( year, month, day )
102 bool IsValidISODate(const PlainDate
& date
);
105 * IsValidISODate ( year, month, day )
107 bool IsValidISODate(double year
, double month
, double day
);
111 * IsValidISODate ( year, month, day )
113 bool ThrowIfInvalidISODate(JSContext
* cx
, const PlainDate
& date
);
116 * IsValidISODate ( year, month, day )
118 bool ThrowIfInvalidISODate(JSContext
* cx
, double year
, double month
,
122 * ToTemporalDate ( item [ , options ] )
124 bool ToTemporalDate(JSContext
* cx
, JS::Handle
<JS::Value
> item
,
128 * ToTemporalDate ( item [ , options ] )
130 bool ToTemporalDate(JSContext
* cx
, JS::Handle
<JS::Value
> item
,
131 JS::MutableHandle
<PlainDateWithCalendar
> result
);
134 * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
136 PlainDateObject
* CreateTemporalDate(JSContext
* cx
, const PlainDate
& date
,
137 JS::Handle
<CalendarValue
> calendar
);
140 * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
142 bool CreateTemporalDate(JSContext
* cx
, const PlainDate
& date
,
143 JS::Handle
<CalendarValue
> calendar
,
144 JS::MutableHandle
<PlainDateWithCalendar
> result
);
147 * RegulateISODate ( year, month, day, overflow )
149 bool RegulateISODate(JSContext
* cx
, const PlainDate
& date
,
150 TemporalOverflow overflow
, PlainDate
* result
);
152 struct RegulatedISODate final
{
159 * RegulateISODate ( year, month, day, overflow )
161 bool RegulateISODate(JSContext
* cx
, double year
, double month
, double day
,
162 TemporalOverflow overflow
, RegulatedISODate
* result
);
165 * AddISODate ( year, month, day, years, months, weeks, days, overflow )
167 bool AddISODate(JSContext
* cx
, const PlainDate
& date
,
168 const DateDuration
& duration
, TemporalOverflow overflow
,
172 * AddDate ( calendarRec, plainDate, duration [ , options ] )
174 Wrapped
<PlainDateObject
*> AddDate(JSContext
* cx
,
175 JS::Handle
<CalendarRecord
> calendar
,
176 JS::Handle
<Wrapped
<PlainDateObject
*>> date
,
177 const Duration
& duration
,
178 JS::Handle
<JSObject
*> options
);
181 * AddDate ( calendarRec, plainDate, duration [ , options ] )
183 Wrapped
<PlainDateObject
*> AddDate(JSContext
* cx
,
184 JS::Handle
<CalendarRecord
> calendar
,
185 JS::Handle
<Wrapped
<PlainDateObject
*>> date
,
186 const Duration
& duration
);
189 * AddDate ( calendarRec, plainDate, duration [ , options ] )
191 Wrapped
<PlainDateObject
*> AddDate(
192 JSContext
* cx
, JS::Handle
<CalendarRecord
> calendar
,
193 JS::Handle
<Wrapped
<PlainDateObject
*>> date
,
194 JS::Handle
<Wrapped
<DurationObject
*>> durationObj
,
195 JS::Handle
<JSObject
*> options
);
198 * AddDate ( calendarRec, plainDate, duration [ , options ] )
200 Wrapped
<PlainDateObject
*> AddDate(
201 JSContext
* cx
, JS::Handle
<CalendarRecord
> calendar
,
202 JS::Handle
<Wrapped
<PlainDateObject
*>> date
,
203 JS::Handle
<Wrapped
<DurationObject
*>> durationObj
);
206 * AddDate ( calendarRec, plainDate, duration [ , options ] )
208 bool AddDate(JSContext
* cx
, JS::Handle
<CalendarRecord
> calendar
,
209 const PlainDate
& date
, const Duration
& duration
,
210 JS::Handle
<JSObject
*> options
, PlainDate
* result
);
213 * AddDate ( calendarRec, plainDate, duration [ , options ] )
215 bool AddDate(JSContext
* cx
, JS::Handle
<CalendarRecord
> calendar
,
216 JS::Handle
<Wrapped
<PlainDateObject
*>> date
,
217 const Duration
& duration
, PlainDate
* result
);
220 * DifferenceISODate ( y1, m1, d1, y2, m2, d2, largestUnit )
222 DateDuration
DifferenceISODate(const PlainDate
& start
, const PlainDate
& end
,
223 TemporalUnit largestUnit
);
226 * DifferenceDate ( calendarRec, one, two, options )
228 bool DifferenceDate(JSContext
* cx
, JS::Handle
<CalendarRecord
> calendar
,
229 JS::Handle
<Wrapped
<PlainDateObject
*>> one
,
230 JS::Handle
<Wrapped
<PlainDateObject
*>> two
,
231 JS::Handle
<PlainObject
*> options
, Duration
* result
);
234 * DifferenceDate ( calendarRec, one, two, options )
236 bool DifferenceDate(JSContext
* cx
, JS::Handle
<CalendarRecord
> calendar
,
237 JS::Handle
<Wrapped
<PlainDateObject
*>> one
,
238 JS::Handle
<Wrapped
<PlainDateObject
*>> two
,
239 TemporalUnit largestUnit
, Duration
* result
);
242 * CompareISODate ( y1, m1, d1, y2, m2, d2 )
244 int32_t CompareISODate(const PlainDate
& one
, const PlainDate
& two
);
247 * BalanceISODate ( year, month, day )
249 bool BalanceISODate(JSContext
* cx
, int32_t year
, int32_t month
, int64_t day
,
253 * BalanceISODate ( year, month, day )
255 PlainDate
BalanceISODate(int32_t year
, int32_t month
, int32_t day
);
258 * BalanceISODate ( year, month, day )
260 PlainDate
BalanceISODateNew(int32_t year
, int32_t month
, int32_t day
);
263 * Return true when accessing the calendar fields |fieldNames| can be optimized.
264 * Otherwise returns false.
266 bool IsBuiltinAccess(JSContext
* cx
, JS::Handle
<PlainDateObject
*> date
,
267 std::initializer_list
<CalendarField
> fieldNames
);
269 } /* namespace js::temporal */
273 template <typename Wrapper
>
274 class WrappedPtrOperations
<temporal::PlainDateWithCalendar
, Wrapper
> {
275 const auto& container() const {
276 return static_cast<const Wrapper
*>(this)->get();
280 const auto& date() const { return container().date(); }
282 JS::Handle
<temporal::CalendarValue
> calendar() const {
283 return JS::Handle
<temporal::CalendarValue
>::fromMarkedLocation(
284 container().calendarDoNotUse());
287 // Allow implicit conversion to a calendar-less PlainDate.
288 operator const temporal::PlainDate
&() const { return date(); }
293 #endif /* builtin_temporal_PlainDate_h */