Bug 1874684 - Part 31: Correctly reject invalid durations in some RoundDuration calls...
[gecko.git] / js / src / builtin / temporal / Duration.h
blob80bdb1074d471e6537ed096f8b87d47b6218f570
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_Duration_h
8 #define builtin_temporal_Duration_h
10 #include <stdint.h>
12 #include "builtin/temporal/TemporalTypes.h"
13 #include "builtin/temporal/Wrapped.h"
14 #include "js/RootingAPI.h"
15 #include "js/TypeDecls.h"
16 #include "js/Value.h"
17 #include "vm/NativeObject.h"
19 namespace js {
20 struct ClassSpec;
23 namespace js::temporal {
25 class DurationObject : public NativeObject {
26 public:
27 static const JSClass class_;
28 static const JSClass& protoClass_;
30 static constexpr uint32_t YEARS_SLOT = 0;
31 static constexpr uint32_t MONTHS_SLOT = 1;
32 static constexpr uint32_t WEEKS_SLOT = 2;
33 static constexpr uint32_t DAYS_SLOT = 3;
34 static constexpr uint32_t HOURS_SLOT = 4;
35 static constexpr uint32_t MINUTES_SLOT = 5;
36 static constexpr uint32_t SECONDS_SLOT = 6;
37 static constexpr uint32_t MILLISECONDS_SLOT = 7;
38 static constexpr uint32_t MICROSECONDS_SLOT = 8;
39 static constexpr uint32_t NANOSECONDS_SLOT = 9;
40 static constexpr uint32_t SLOT_COUNT = 10;
42 double years() const { return getFixedSlot(YEARS_SLOT).toNumber(); }
43 double months() const { return getFixedSlot(MONTHS_SLOT).toNumber(); }
44 double weeks() const { return getFixedSlot(WEEKS_SLOT).toNumber(); }
45 double days() const { return getFixedSlot(DAYS_SLOT).toNumber(); }
46 double hours() const { return getFixedSlot(HOURS_SLOT).toNumber(); }
47 double minutes() const { return getFixedSlot(MINUTES_SLOT).toNumber(); }
48 double seconds() const { return getFixedSlot(SECONDS_SLOT).toNumber(); }
49 double milliseconds() const {
50 return getFixedSlot(MILLISECONDS_SLOT).toNumber();
52 double microseconds() const {
53 return getFixedSlot(MICROSECONDS_SLOT).toNumber();
55 double nanoseconds() const {
56 return getFixedSlot(NANOSECONDS_SLOT).toNumber();
59 private:
60 static const ClassSpec classSpec_;
63 /**
64 * Extract the duration fields from the Duration object.
66 inline Duration ToDuration(const DurationObject* duration) {
67 return {
68 duration->years(), duration->months(),
69 duration->weeks(), duration->days(),
70 duration->hours(), duration->minutes(),
71 duration->seconds(), duration->milliseconds(),
72 duration->microseconds(), duration->nanoseconds(),
76 class Increment;
77 class CalendarRecord;
78 class PlainDateObject;
79 class TimeZoneRecord;
80 class ZonedDateTime;
81 class ZonedDateTimeObject;
82 enum class TemporalRoundingMode;
83 enum class TemporalUnit;
85 /**
86 * DurationSign ( years, months, weeks, days, hours, minutes, seconds,
87 * milliseconds, microseconds, nanoseconds )
89 int32_t DurationSign(const Duration& duration);
91 /**
92 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds,
93 * milliseconds, microseconds, nanoseconds )
95 bool IsValidDuration(const Duration& duration);
97 #ifdef DEBUG
98 /**
99 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds,
100 * milliseconds, microseconds, nanoseconds )
102 bool IsValidDuration(const DateDuration& duration);
105 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds,
106 * milliseconds, microseconds, nanoseconds )
108 bool IsValidDuration(const NormalizedDuration& duration);
109 #endif
112 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds,
113 * milliseconds, microseconds, nanoseconds )
115 bool ThrowIfInvalidDuration(JSContext* cx, const Duration& duration);
118 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds,
119 * milliseconds, microseconds, nanoseconds )
121 bool ThrowIfInvalidDuration(JSContext* cx, const DateDuration& duration);
124 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds,
125 * milliseconds, microseconds, nanoseconds )
127 inline bool IsValidNormalizedTimeDuration(
128 const NormalizedTimeDuration& duration) {
129 MOZ_ASSERT(0 <= duration.nanoseconds && duration.nanoseconds <= 999'999'999);
131 // Step 4.
133 // The absolute value of the seconds part of normalized time duration must be
134 // less-or-equal to `2**53 - 1` and the nanoseconds part must be less or equal
135 // to `999'999'999`.
136 return NormalizedTimeDuration::min() <= duration &&
137 duration <= NormalizedTimeDuration::max();
141 * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds,
142 * nanoseconds )
144 NormalizedTimeDuration NormalizeTimeDuration(int32_t hours, int32_t minutes,
145 int32_t seconds,
146 int32_t milliseconds,
147 int32_t microseconds,
148 int32_t nanoseconds);
151 * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds,
152 * nanoseconds )
154 NormalizedTimeDuration NormalizeTimeDuration(const Duration& duration);
157 * CompareNormalizedTimeDuration ( one, two )
159 inline int32_t CompareNormalizedTimeDuration(
160 const NormalizedTimeDuration& one, const NormalizedTimeDuration& two) {
161 MOZ_ASSERT(IsValidNormalizedTimeDuration(one));
162 MOZ_ASSERT(IsValidNormalizedTimeDuration(two));
164 // Step 1.
165 if (one > two) {
166 return 1;
169 // Step 2.
170 if (one < two) {
171 return -1;
174 // Step 3.
175 return 0;
179 * NormalizedTimeDurationSign ( d )
181 inline int32_t NormalizedTimeDurationSign(const NormalizedTimeDuration& d) {
182 MOZ_ASSERT(IsValidNormalizedTimeDuration(d));
184 // Steps 1-3.
185 return CompareNormalizedTimeDuration(d, NormalizedTimeDuration{});
189 * Add24HourDaysToNormalizedTimeDuration ( d, days )
191 bool Add24HourDaysToNormalizedTimeDuration(JSContext* cx,
192 const NormalizedTimeDuration& d,
193 int64_t days,
194 NormalizedTimeDuration* result);
197 * CreateNormalizedDurationRecord ( years, months, weeks, days, norm )
199 inline NormalizedDuration CreateNormalizedDurationRecord(
200 const DateDuration& date, const NormalizedTimeDuration& time) {
201 MOZ_ASSERT(IsValidDuration(date));
202 MOZ_ASSERT(IsValidNormalizedTimeDuration(time));
203 #ifdef DEBUG
204 int64_t dateValues = date.years | date.months | date.weeks | date.days;
205 int32_t dateSign = dateValues ? dateValues < 0 ? -1 : 1 : 0;
206 int32_t timeSign = NormalizedTimeDurationSign(time);
207 MOZ_ASSERT((dateSign * timeSign) >= 0);
208 #endif
210 return {date, time};
214 * CreateNormalizedDurationRecord ( years, months, weeks, days, norm )
216 inline NormalizedDuration CreateNormalizedDurationRecord(
217 const Duration& duration) {
218 return CreateNormalizedDurationRecord(duration.toDateDuration(),
219 NormalizeTimeDuration(duration));
223 * CombineDateAndNormalizedTimeDuration ( dateDurationRecord, norm )
225 bool CombineDateAndNormalizedTimeDuration(JSContext* cx,
226 const DateDuration& date,
227 const NormalizedTimeDuration& time,
228 NormalizedDuration* result);
231 * CreateNormalizedDurationRecord ( years, months, weeks, days, norm )
233 inline bool CreateNormalizedDurationRecord(JSContext* cx,
234 const DateDuration& date,
235 const NormalizedTimeDuration& time,
236 NormalizedDuration* result) {
237 return CombineDateAndNormalizedTimeDuration(cx, date, time, result);
241 * NormalizedTimeDurationFromEpochNanosecondsDifference ( one, two )
243 NormalizedTimeDuration NormalizedTimeDurationFromEpochNanosecondsDifference(
244 const Instant& one, const Instant& two);
247 * CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds,
248 * milliseconds, microseconds, nanoseconds [ , newTarget ] )
250 DurationObject* CreateTemporalDuration(JSContext* cx, const Duration& duration);
253 * ToTemporalDuration ( item )
255 Wrapped<DurationObject*> ToTemporalDuration(JSContext* cx,
256 JS::Handle<JS::Value> item);
259 * ToTemporalDuration ( item )
261 bool ToTemporalDuration(JSContext* cx, JS::Handle<JS::Value> item,
262 Duration* result);
265 * ToTemporalDurationRecord ( temporalDurationLike )
267 bool ToTemporalDurationRecord(JSContext* cx,
268 JS::Handle<JS::Value> temporalDurationLike,
269 Duration* result);
272 * BalanceTimeDuration ( norm, largestUnit )
274 TimeDuration BalanceTimeDuration(const NormalizedTimeDuration& duration,
275 TemporalUnit largestUnit);
278 * BalanceTimeDuration ( norm, largestUnit )
280 bool BalanceTimeDuration(JSContext* cx, const NormalizedTimeDuration& duration,
281 TemporalUnit largestUnit, TimeDuration* result);
284 * BalanceDateDurationRelative ( years, months, weeks, days, largestUnit,
285 * smallestUnit, plainRelativeTo, calendarRec )
287 bool BalanceDateDurationRelative(
288 JSContext* cx, const DateDuration& duration, TemporalUnit largestUnit,
289 TemporalUnit smallestUnit,
290 JS::Handle<Wrapped<PlainDateObject*>> plainRelativeTo,
291 JS::Handle<CalendarRecord> calendar, DateDuration* result);
294 * AdjustRoundedDurationDays ( years, months, weeks, days, norm, increment,
295 * unit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec,
296 * precalculatedPlainDateTime )
298 bool AdjustRoundedDurationDays(JSContext* cx,
299 const NormalizedDuration& duration,
300 Increment increment, TemporalUnit unit,
301 TemporalRoundingMode roundingMode,
302 JS::Handle<ZonedDateTime> relativeTo,
303 JS::Handle<CalendarRecord> calendar,
304 JS::Handle<TimeZoneRecord> timeZone,
305 const PlainDateTime& precalculatedPlainDateTime,
306 NormalizedDuration* result);
309 * RoundDuration ( years, months, weeks, days, norm, increment, unit,
310 * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ ,
311 * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] )
313 NormalizedTimeDuration RoundDuration(const NormalizedTimeDuration& duration,
314 Increment increment, TemporalUnit unit,
315 TemporalRoundingMode roundingMode);
318 * RoundDuration ( years, months, weeks, days, norm, increment, unit,
319 * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ ,
320 * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] )
322 bool RoundDuration(JSContext* cx, const NormalizedTimeDuration& duration,
323 Increment increment, TemporalUnit unit,
324 TemporalRoundingMode roundingMode,
325 NormalizedTimeDuration* result);
328 * RoundDuration ( years, months, weeks, days, norm, increment, unit,
329 * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ ,
330 * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] )
332 bool RoundDuration(JSContext* cx, const NormalizedDuration& duration,
333 Increment increment, TemporalUnit unit,
334 TemporalRoundingMode roundingMode,
335 JS::Handle<Wrapped<PlainDateObject*>> plainRelativeTo,
336 JS::Handle<CalendarRecord> calendar,
337 NormalizedDuration* result);
340 * RoundDuration ( years, months, weeks, days, norm, increment, unit,
341 * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ ,
342 * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] )
344 bool RoundDuration(JSContext* cx, const NormalizedDuration& duration,
345 Increment increment, TemporalUnit unit,
346 TemporalRoundingMode roundingMode,
347 JS::Handle<PlainDateObject*> plainRelativeTo,
348 JS::Handle<CalendarRecord> calendar,
349 JS::Handle<ZonedDateTime> zonedRelativeTo,
350 JS::Handle<TimeZoneRecord> timeZone,
351 const PlainDateTime& precalculatedPlainDateTime,
352 NormalizedDuration* result);
355 * DaysUntil ( earlier, later )
357 int32_t DaysUntil(const PlainDate& earlier, const PlainDate& later);
359 } /* namespace js::temporal */
361 #endif /* builtin_temporal_Duration_h */