Bug 1874684 - Part 31: Correctly reject invalid durations in some RoundDuration calls...
[gecko.git] / js / src / builtin / temporal / PlainDate.h
blob69c09f42465e70e2af47b703f189f5f63e281a99
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"
11 #include "mozilla/Attributes.h"
13 #include <initializer_list>
14 #include <stdint.h>
16 #include "builtin/temporal/Calendar.h"
17 #include "builtin/temporal/PlainDateTime.h"
18 #include "builtin/temporal/TemporalTypes.h"
19 #include "builtin/temporal/Wrapped.h"
20 #include "js/RootingAPI.h"
21 #include "js/TypeDecls.h"
22 #include "js/Value.h"
23 #include "vm/NativeObject.h"
25 class JS_PUBLIC_API JSTracer;
27 namespace js {
28 struct ClassSpec;
29 class PlainObject;
30 } // namespace js
32 namespace js::temporal {
34 class PlainDateObject : public NativeObject {
35 public:
36 static const JSClass class_;
37 static const JSClass& protoClass_;
39 // TODO: Consider compacting fields to reduce object size.
41 // ceil(log2(271821)) + ceil(log2(12)) + ceil(log2(31)) = 28 bits are
42 // needed to store a date value in a single int32.
44 static constexpr uint32_t ISO_YEAR_SLOT = 0;
45 static constexpr uint32_t ISO_MONTH_SLOT = 1;
46 static constexpr uint32_t ISO_DAY_SLOT = 2;
47 static constexpr uint32_t CALENDAR_SLOT = 3;
48 static constexpr uint32_t SLOT_COUNT = 4;
50 int32_t isoYear() const { return getFixedSlot(ISO_YEAR_SLOT).toInt32(); }
52 int32_t isoMonth() const { return getFixedSlot(ISO_MONTH_SLOT).toInt32(); }
54 int32_t isoDay() const { return getFixedSlot(ISO_DAY_SLOT).toInt32(); }
56 CalendarValue calendar() const {
57 return CalendarValue(getFixedSlot(CALENDAR_SLOT));
60 private:
61 static const ClassSpec classSpec_;
64 class MOZ_STACK_CLASS PlainDateWithCalendar final {
65 PlainDate date_;
66 CalendarValue calendar_;
68 public:
69 PlainDateWithCalendar() = default;
71 PlainDateWithCalendar(const PlainDate& date, const CalendarValue& calendar)
72 : date_(date), calendar_(calendar) {
73 MOZ_ASSERT(ISODateTimeWithinLimits(date));
76 const auto& date() const { return date_; }
77 const auto& calendar() const { return calendar_; }
79 // Allow implicit conversion to a calendar-less PlainDate.
80 operator const PlainDate&() const { return date(); }
82 void trace(JSTracer* trc) { calendar_.trace(trc); }
84 const auto* calendarDoNotUse() const { return &calendar_; }
87 /**
88 * Extract the date fields from the PlainDate object.
90 inline PlainDate ToPlainDate(const PlainDateObject* date) {
91 return {date->isoYear(), date->isoMonth(), date->isoDay()};
94 enum class TemporalOverflow;
95 enum class TemporalUnit;
96 class DurationObject;
97 class ZonedDateTimeObject;
99 #ifdef DEBUG
101 * IsValidISODate ( year, month, day )
103 bool IsValidISODate(const PlainDate& date);
106 * IsValidISODate ( year, month, day )
108 bool IsValidISODate(double year, double month, double day);
109 #endif
112 * IsValidISODate ( year, month, day )
114 bool ThrowIfInvalidISODate(JSContext* cx, const PlainDate& date);
117 * IsValidISODate ( year, month, day )
119 bool ThrowIfInvalidISODate(JSContext* cx, double year, double month,
120 double day);
123 * ToTemporalDate ( item [ , options ] )
125 bool ToTemporalDate(JSContext* cx, JS::Handle<JS::Value> item,
126 PlainDate* result);
129 * ToTemporalDate ( item [ , options ] )
131 bool ToTemporalDate(JSContext* cx, JS::Handle<JS::Value> item,
132 JS::MutableHandle<PlainDateWithCalendar> result);
135 * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
137 PlainDateObject* CreateTemporalDate(JSContext* cx, const PlainDate& date,
138 JS::Handle<CalendarValue> calendar);
141 * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )
143 bool CreateTemporalDate(JSContext* cx, const PlainDate& date,
144 JS::Handle<CalendarValue> calendar,
145 JS::MutableHandle<PlainDateWithCalendar> result);
148 * RegulateISODate ( year, month, day, overflow )
150 bool RegulateISODate(JSContext* cx, const PlainDate& date,
151 TemporalOverflow overflow, PlainDate* result);
153 struct RegulatedISODate final {
154 double year = 0;
155 int32_t month = 0;
156 int32_t day = 0;
160 * RegulateISODate ( year, month, day, overflow )
162 bool RegulateISODate(JSContext* cx, double year, double month, double day,
163 TemporalOverflow overflow, RegulatedISODate* result);
166 * AddISODate ( year, month, day, years, months, weeks, days, overflow )
168 bool AddISODate(JSContext* cx, const PlainDate& date,
169 const DateDuration& duration, TemporalOverflow overflow,
170 PlainDate* result);
173 * AddDate ( calendarRec, plainDate, duration [ , options ] )
175 Wrapped<PlainDateObject*> AddDate(JSContext* cx,
176 JS::Handle<CalendarRecord> calendar,
177 JS::Handle<Wrapped<PlainDateObject*>> date,
178 const Duration& duration,
179 JS::Handle<JSObject*> options);
182 * AddDate ( calendarRec, plainDate, duration [ , options ] )
184 Wrapped<PlainDateObject*> AddDate(JSContext* cx,
185 JS::Handle<CalendarRecord> calendar,
186 JS::Handle<Wrapped<PlainDateObject*>> date,
187 const DateDuration& duration);
190 * AddDate ( calendarRec, plainDate, duration [ , options ] )
192 bool AddDate(JSContext* cx, JS::Handle<CalendarRecord> calendar,
193 const PlainDate& date, const DateDuration& duration,
194 JS::Handle<JSObject*> options, PlainDate* result);
197 * AddDate ( calendarRec, plainDate, duration [ , options ] )
199 bool AddDate(JSContext* cx, JS::Handle<CalendarRecord> calendar,
200 JS::Handle<Wrapped<PlainDateObject*>> date,
201 const DateDuration& duration, PlainDate* result);
204 * DifferenceISODate ( y1, m1, d1, y2, m2, d2, largestUnit )
206 DateDuration DifferenceISODate(const PlainDate& start, const PlainDate& end,
207 TemporalUnit largestUnit);
210 * DifferenceDate ( calendarRec, one, two, options )
212 bool DifferenceDate(JSContext* cx, JS::Handle<CalendarRecord> calendar,
213 JS::Handle<Wrapped<PlainDateObject*>> one,
214 JS::Handle<Wrapped<PlainDateObject*>> two,
215 JS::Handle<PlainObject*> options, DateDuration* result);
218 * DifferenceDate ( calendarRec, one, two, options )
220 bool DifferenceDate(JSContext* cx, JS::Handle<CalendarRecord> calendar,
221 JS::Handle<Wrapped<PlainDateObject*>> one,
222 JS::Handle<Wrapped<PlainDateObject*>> two,
223 TemporalUnit largestUnit, DateDuration* result);
226 * CompareISODate ( y1, m1, d1, y2, m2, d2 )
228 int32_t CompareISODate(const PlainDate& one, const PlainDate& two);
231 * BalanceISODate ( year, month, day )
233 bool BalanceISODate(JSContext* cx, int32_t year, int32_t month, int64_t day,
234 PlainDate* result);
237 * BalanceISODate ( year, month, day )
239 PlainDate BalanceISODate(int32_t year, int32_t month, int32_t day);
242 * BalanceISODate ( year, month, day )
244 PlainDate BalanceISODateNew(int32_t year, int32_t month, int32_t day);
247 * Return true when accessing the calendar fields |fieldNames| can be optimized.
248 * Otherwise returns false.
250 bool IsBuiltinAccess(JSContext* cx, JS::Handle<PlainDateObject*> date,
251 std::initializer_list<CalendarField> fieldNames);
253 } /* namespace js::temporal */
255 namespace js {
257 template <typename Wrapper>
258 class WrappedPtrOperations<temporal::PlainDateWithCalendar, Wrapper> {
259 const auto& container() const {
260 return static_cast<const Wrapper*>(this)->get();
263 public:
264 const auto& date() const { return container().date(); }
266 JS::Handle<temporal::CalendarValue> calendar() const {
267 return JS::Handle<temporal::CalendarValue>::fromMarkedLocation(
268 container().calendarDoNotUse());
271 // Allow implicit conversion to a calendar-less PlainDate.
272 operator const temporal::PlainDate&() const { return date(); }
275 } // namespace js
277 #endif /* builtin_temporal_PlainDate_h */