Bug 1874684 - Part 10: Replace BigInt with Int128 in RoundNumberToIncrement. r=mgaudet
[gecko.git] / js / src / builtin / temporal / Temporal.h
blob5000859c198e2be9b090d7a6a1725ed82b5057b8
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_Temporal_h
8 #define builtin_temporal_Temporal_h
10 #include "mozilla/Assertions.h"
12 #include <stdint.h>
14 #include "jstypes.h"
16 #include "builtin/temporal/Int128.h"
17 #include "builtin/temporal/TemporalRoundingMode.h"
18 #include "builtin/temporal/TemporalUnit.h"
19 #include "js/RootingAPI.h"
20 #include "js/TypeDecls.h"
21 #include "vm/NativeObject.h"
23 namespace js {
24 struct ClassSpec;
25 class PlainObject;
26 class PropertyName;
27 } // namespace js
29 namespace js::temporal {
31 class TemporalObject : public NativeObject {
32 public:
33 static const JSClass class_;
35 private:
36 static const ClassSpec classSpec_;
39 /**
40 * Rounding increment, which is an integer in the range [1, 1'000'000'000].
42 * Temporal units are rounded to a multiple of the specified increment value.
44 class Increment final {
45 uint32_t value_;
47 public:
48 constexpr explicit Increment(uint32_t value) : value_(value) {
49 MOZ_ASSERT(1 <= value && value <= 1'000'000'000);
52 /**
53 * Minimum allowed rounding increment.
55 static constexpr auto min() { return Increment{1}; }
57 /**
58 * Maximum allowed rounding increment.
60 static constexpr auto max() { return Increment{1'000'000'000}; }
62 /**
63 * The rounding increment's value.
65 uint32_t value() const { return value_; }
67 bool operator==(const Increment& other) const {
68 return value_ == other.value_;
71 bool operator<(const Increment& other) const { return value_ < other.value_; }
73 // Other operators are implemented in terms of operator== and operator<.
74 bool operator!=(const Increment& other) const { return !(*this == other); }
75 bool operator>(const Increment& other) const { return other < *this; }
76 bool operator<=(const Increment& other) const { return !(other < *this); }
77 bool operator>=(const Increment& other) const { return !(*this < other); }
80 /**
81 * ToTemporalRoundingIncrement ( normalizedOptions, dividend, inclusive )
83 bool ToTemporalRoundingIncrement(JSContext* cx, JS::Handle<JSObject*> options,
84 Increment* increment);
86 /**
87 * ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )
89 bool ValidateTemporalRoundingIncrement(JSContext* cx, Increment increment,
90 int64_t dividend, bool inclusive);
92 /**
93 * ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )
95 inline bool ValidateTemporalRoundingIncrement(JSContext* cx,
96 Increment increment,
97 Increment dividend,
98 bool inclusive) {
99 return ValidateTemporalRoundingIncrement(cx, increment, dividend.value(),
100 inclusive);
104 * MaximumTemporalDurationRoundingIncrement ( unit )
106 constexpr Increment MaximumTemporalDurationRoundingIncrement(
107 TemporalUnit unit) {
108 // Step 1. (Not applicable in our implementation.)
109 MOZ_ASSERT(unit > TemporalUnit::Day);
111 // Step 2.
112 if (unit == TemporalUnit::Hour) {
113 return Increment{24};
116 // Step 3.
117 if (unit <= TemporalUnit::Second) {
118 return Increment{60};
121 // Steps 4-5.
122 return Increment{1000};
125 PropertyName* TemporalUnitToString(JSContext* cx, TemporalUnit unit);
127 enum class TemporalUnitGroup {
128 // Allow date units: "year", "month", "week", "day".
129 Date,
131 // Allow time units: "hour", "minute", "second", "milli-/micro-/nanoseconds".
132 Time,
134 // Allow date and time units.
135 DateTime,
137 // Allow "day" and time units.
138 DayTime,
141 enum class TemporalUnitKey {
142 SmallestUnit,
143 LargestUnit,
144 Unit,
148 * GetTemporalUnit ( normalizedOptions, key, unitGroup, default [ , extraValues
149 * ] )
151 bool GetTemporalUnit(JSContext* cx, JS::Handle<JSObject*> options,
152 TemporalUnitKey key, TemporalUnitGroup unitGroup,
153 TemporalUnit* unit);
156 * GetTemporalUnit ( normalizedOptions, key, unitGroup, default [ , extraValues
157 * ] )
159 bool GetTemporalUnit(JSContext* cx, JS::Handle<JSString*> value,
160 TemporalUnitKey key, TemporalUnitGroup unitGroup,
161 TemporalUnit* unit);
164 * ToTemporalRoundingMode ( normalizedOptions, fallback )
166 bool ToTemporalRoundingMode(JSContext* cx, JS::Handle<JSObject*> options,
167 TemporalRoundingMode* mode);
170 * RoundNumberToIncrement ( x, increment, roundingMode )
172 Int128 RoundNumberToIncrement(int64_t numerator, int64_t denominator,
173 Increment increment,
174 TemporalRoundingMode roundingMode);
177 * RoundNumberToIncrement ( x, increment, roundingMode )
179 Int128 RoundNumberToIncrement(const Int128& numerator,
180 const Int128& denominator, Increment increment,
181 TemporalRoundingMode roundingMode);
184 * RoundNumberToIncrement ( x, increment, roundingMode )
186 Int128 RoundNumberToIncrement(const Int128& x, const Int128& increment,
187 TemporalRoundingMode roundingMode);
189 enum class CalendarOption { Auto, Always, Never, Critical };
192 * ToCalendarNameOption ( normalizedOptions )
194 bool ToCalendarNameOption(JSContext* cx, JS::Handle<JSObject*> options,
195 CalendarOption* result);
198 * Precision when displaying fractional seconds.
200 class Precision final {
201 int8_t value_;
203 enum class Tag {};
204 constexpr Precision(int8_t value, Tag) : value_(value) {}
206 public:
207 constexpr explicit Precision(uint8_t value) : value_(value) {
208 MOZ_ASSERT(value < 10);
211 bool operator==(const Precision& other) const {
212 return value_ == other.value_;
215 bool operator!=(const Precision& other) const { return !(*this == other); }
218 * Return the number of fractional second digits.
220 uint8_t value() const {
221 MOZ_ASSERT(value_ >= 0, "auto and minute precision don't have a value");
222 return uint8_t(value_);
226 * Limit the precision to trim off any trailing zeros.
228 static constexpr Precision Auto() { return {-1, Tag{}}; }
231 * Limit the precision to minutes, i.e. don't display seconds and sub-seconds.
233 static constexpr Precision Minute() { return {-2, Tag{}}; }
237 * ToFractionalSecondDigits ( normalizedOptions )
239 bool ToFractionalSecondDigits(JSContext* cx, JS::Handle<JSObject*> options,
240 Precision* precision);
242 struct SecondsStringPrecision final {
243 Precision precision = Precision{0};
244 TemporalUnit unit = TemporalUnit::Auto;
245 Increment increment = Increment{1};
249 * ToSecondsStringPrecisionRecord ( smallestUnit, fractionalDigitCount )
251 SecondsStringPrecision ToSecondsStringPrecision(TemporalUnit smallestUnit,
252 Precision fractionalDigitCount);
254 enum class TemporalOverflow { Constrain, Reject };
257 * ToTemporalOverflow ( normalizedOptions )
259 bool ToTemporalOverflow(JSContext* cx, JS::Handle<JSObject*> options,
260 TemporalOverflow* result);
262 enum class TemporalDisambiguation { Compatible, Earlier, Later, Reject };
265 * ToTemporalDisambiguation ( options )
267 bool ToTemporalDisambiguation(JSContext* cx, JS::Handle<JSObject*> options,
268 TemporalDisambiguation* disambiguation);
270 enum class TemporalOffset { Prefer, Use, Ignore, Reject };
273 * ToTemporalOffset ( options, fallback )
275 bool ToTemporalOffset(JSContext* cx, JS::Handle<JSObject*> options,
276 TemporalOffset* offset);
278 enum class TimeZoneNameOption { Auto, Never, Critical };
280 bool ToTimeZoneNameOption(JSContext* cx, JS::Handle<JSObject*> options,
281 TimeZoneNameOption* result);
283 enum class ShowOffsetOption { Auto, Never };
286 * ToShowOffsetOption ( normalizedOptions )
288 bool ToShowOffsetOption(JSContext* cx, JS::Handle<JSObject*> options,
289 ShowOffsetOption* result);
292 * RejectTemporalLikeObject ( object )
294 bool RejectTemporalLikeObject(JSContext* cx, JS::Handle<JSObject*> object);
297 * ToPositiveIntegerWithTruncation ( argument )
299 bool ToPositiveIntegerWithTruncation(JSContext* cx, JS::Handle<JS::Value> value,
300 const char* name, double* result);
303 * ToIntegerWithTruncation ( argument )
305 bool ToIntegerWithTruncation(JSContext* cx, JS::Handle<JS::Value> value,
306 const char* name, double* result);
309 * GetMethod ( V, P )
311 JSObject* GetMethod(JSContext* cx, JS::Handle<JSObject*> object,
312 JS::Handle<PropertyName*> name);
315 * SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ]
318 PlainObject* SnapshotOwnProperties(JSContext* cx, JS::Handle<JSObject*> source);
321 * SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ]
324 PlainObject* SnapshotOwnPropertiesIgnoreUndefined(JSContext* cx,
325 JS::Handle<JSObject*> source);
328 * CopyDataProperties ( target, source, excludedKeys [ , excludedValues ] )
330 bool CopyDataProperties(JSContext* cx, JS::Handle<PlainObject*> target,
331 JS::Handle<JSObject*> source);
333 enum class TemporalDifference { Since, Until };
335 inline const char* ToName(TemporalDifference difference) {
336 return difference == TemporalDifference::Since ? "since" : "until";
339 struct DifferenceSettings final {
340 TemporalUnit smallestUnit = TemporalUnit::Auto;
341 TemporalUnit largestUnit = TemporalUnit::Auto;
342 TemporalRoundingMode roundingMode = TemporalRoundingMode::Trunc;
343 Increment roundingIncrement = Increment{1};
347 * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits,
348 * fallbackSmallestUnit, smallestLargestDefaultUnit )
350 bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation,
351 JS::Handle<PlainObject*> options,
352 TemporalUnitGroup unitGroup,
353 TemporalUnit smallestAllowedUnit,
354 TemporalUnit fallbackSmallestUnit,
355 TemporalUnit smallestLargestDefaultUnit,
356 DifferenceSettings* result);
359 * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits,
360 * fallbackSmallestUnit, smallestLargestDefaultUnit )
362 inline bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation,
363 JS::Handle<PlainObject*> options,
364 TemporalUnitGroup unitGroup,
365 TemporalUnit fallbackSmallestUnit,
366 TemporalUnit smallestLargestDefaultUnit,
367 DifferenceSettings* result) {
368 return GetDifferenceSettings(cx, operation, options, unitGroup,
369 TemporalUnit::Nanosecond, fallbackSmallestUnit,
370 smallestLargestDefaultUnit, result);
374 * Sets |result| to `true` when array iteration is still in its initial state.
376 bool IsArrayIterationSane(JSContext* cx, bool* result);
378 } /* namespace js::temporal */
380 #endif /* builtin_temporal_Temporal_h */