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"
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"
29 namespace js::temporal
{
31 class TemporalObject
: public NativeObject
{
33 static const JSClass class_
;
36 static const ClassSpec classSpec_
;
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
{
48 constexpr explicit Increment(uint32_t value
) : value_(value
) {
49 MOZ_ASSERT(1 <= value
&& value
<= 1'000'000'000);
53 * Minimum allowed rounding increment.
55 static constexpr auto min() { return Increment
{1}; }
58 * Maximum allowed rounding increment.
60 static constexpr auto max() { return Increment
{1'000'000'000}; }
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
); }
81 * GetRoundingIncrementOption ( normalizedOptions, dividend, inclusive )
83 bool GetRoundingIncrementOption(JSContext
* cx
, JS::Handle
<JSObject
*> options
,
84 Increment
* increment
);
87 * ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )
89 bool ValidateTemporalRoundingIncrement(JSContext
* cx
, Increment increment
,
90 int64_t dividend
, bool inclusive
);
93 * ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )
95 inline bool ValidateTemporalRoundingIncrement(JSContext
* cx
,
99 return ValidateTemporalRoundingIncrement(cx
, increment
, dividend
.value(),
104 * MaximumTemporalDurationRoundingIncrement ( unit )
106 constexpr Increment
MaximumTemporalDurationRoundingIncrement(
108 // Step 1. (Not applicable in our implementation.)
109 MOZ_ASSERT(unit
> TemporalUnit::Day
);
112 if (unit
== TemporalUnit::Hour
) {
113 return Increment
{24};
117 if (unit
<= TemporalUnit::Second
) {
118 return Increment
{60};
122 return Increment
{1000};
125 PropertyName
* TemporalUnitToString(JSContext
* cx
, TemporalUnit unit
);
127 enum class TemporalUnitGroup
{
128 // Allow date units: "year", "month", "week", "day".
131 // Allow time units: "hour", "minute", "second", "milli-/micro-/nanoseconds".
134 // Allow date and time units.
137 // Allow "day" and time units.
141 enum class TemporalUnitKey
{
148 * GetTemporalUnitValuedOption ( normalizedOptions, key, unitGroup, default [ ,
151 bool GetTemporalUnitValuedOption(JSContext
* cx
, JS::Handle
<JSObject
*> options
,
153 TemporalUnitGroup unitGroup
,
157 * GetTemporalUnitValuedOption ( normalizedOptions, key, unitGroup, default [ ,
160 bool GetTemporalUnitValuedOption(JSContext
* cx
, JS::Handle
<JSString
*> value
,
162 TemporalUnitGroup unitGroup
,
166 * GetRoundingModeOption ( normalizedOptions, fallback )
168 bool GetRoundingModeOption(JSContext
* cx
, JS::Handle
<JSObject
*> options
,
169 TemporalRoundingMode
* mode
);
172 * RoundNumberToIncrement ( x, increment, roundingMode )
174 Int128
RoundNumberToIncrement(int64_t numerator
, int64_t denominator
,
176 TemporalRoundingMode roundingMode
);
179 * RoundNumberToIncrement ( x, increment, roundingMode )
181 Int128
RoundNumberToIncrement(const Int128
& numerator
,
182 const Int128
& denominator
, Increment increment
,
183 TemporalRoundingMode roundingMode
);
186 * RoundNumberToIncrement ( x, increment, roundingMode )
188 int64_t RoundNumberToIncrement(int64_t x
, int64_t increment
,
189 TemporalRoundingMode roundingMode
);
192 * RoundNumberToIncrement ( x, increment, roundingMode )
194 inline int64_t RoundNumberToIncrement(int64_t x
, Increment increment
,
195 TemporalRoundingMode roundingMode
) {
196 return RoundNumberToIncrement(x
, int64_t(increment
.value()), roundingMode
);
200 * RoundNumberToIncrement ( x, increment, roundingMode )
202 Int128
RoundNumberToIncrement(const Int128
& x
, const Int128
& increment
,
203 TemporalRoundingMode roundingMode
);
206 * Return the double value of the fractional number `numerator / denominator`.
208 double FractionToDouble(int64_t numerator
, int64_t denominator
);
211 * Return the double value of the fractional number `numerator / denominator`.
213 double FractionToDouble(const Int128
& numerator
, const Int128
& denominator
);
215 enum class ShowCalendar
{ Auto
, Always
, Never
, Critical
};
218 * GetTemporalShowCalendarNameOption ( normalizedOptions )
220 bool GetTemporalShowCalendarNameOption(JSContext
* cx
,
221 JS::Handle
<JSObject
*> options
,
222 ShowCalendar
* result
);
225 * Precision when displaying fractional seconds.
227 class Precision final
{
231 constexpr Precision(int8_t value
, Tag
) : value_(value
) {}
234 constexpr explicit Precision(uint8_t value
) : value_(int8_t(value
)) {
235 MOZ_ASSERT(value
< 10);
238 bool operator==(const Precision
& other
) const {
239 return value_
== other
.value_
;
242 bool operator!=(const Precision
& other
) const { return !(*this == other
); }
245 * Return the number of fractional second digits.
247 uint8_t value() const {
248 MOZ_ASSERT(value_
>= 0, "auto and minute precision don't have a value");
249 return uint8_t(value_
);
253 * Limit the precision to trim off any trailing zeros.
255 static constexpr Precision
Auto() { return {-1, Tag
{}}; }
258 * Limit the precision to minutes, i.e. don't display seconds and sub-seconds.
260 static constexpr Precision
Minute() { return {-2, Tag
{}}; }
264 * GetTemporalFractionalSecondDigitsOption ( normalizedOptions )
266 bool GetTemporalFractionalSecondDigitsOption(JSContext
* cx
,
267 JS::Handle
<JSObject
*> options
,
268 Precision
* precision
);
270 struct SecondsStringPrecision final
{
271 Precision precision
= Precision
{0};
272 TemporalUnit unit
= TemporalUnit::Auto
;
273 Increment increment
= Increment
{1};
277 * ToSecondsStringPrecisionRecord ( smallestUnit, fractionalDigitCount )
279 SecondsStringPrecision
ToSecondsStringPrecision(TemporalUnit smallestUnit
,
280 Precision fractionalDigitCount
);
282 enum class TemporalOverflow
{ Constrain
, Reject
};
285 * GetTemporalOverflowOption ( normalizedOptions )
287 bool GetTemporalOverflowOption(JSContext
* cx
, JS::Handle
<JSObject
*> options
,
288 TemporalOverflow
* result
);
290 enum class TemporalDisambiguation
{ Compatible
, Earlier
, Later
, Reject
};
293 * GetTemporalDisambiguationOption ( options )
295 bool GetTemporalDisambiguationOption(JSContext
* cx
,
296 JS::Handle
<JSObject
*> options
,
297 TemporalDisambiguation
* disambiguation
);
299 enum class TemporalOffset
{ Prefer
, Use
, Ignore
, Reject
};
302 * GetTemporalOffsetOption ( options, fallback )
304 bool GetTemporalOffsetOption(JSContext
* cx
, JS::Handle
<JSObject
*> options
,
305 TemporalOffset
* offset
);
307 enum class ShowTimeZoneName
{ Auto
, Never
, Critical
};
309 bool GetTemporalShowTimeZoneNameOption(JSContext
* cx
,
310 JS::Handle
<JSObject
*> options
,
311 ShowTimeZoneName
* result
);
313 enum class ShowOffset
{ Auto
, Never
};
316 * GetTemporalShowOffsetOption ( normalizedOptions )
318 bool GetTemporalShowOffsetOption(JSContext
* cx
, JS::Handle
<JSObject
*> options
,
322 * IsPartialTemporalObject ( object )
324 * Our implementation performs error reporting in this function instead of in
325 * the caller to provide better error messages.
327 bool ThrowIfTemporalLikeObject(JSContext
* cx
, JS::Handle
<JSObject
*> object
);
330 * ToPositiveIntegerWithTruncation ( argument )
332 bool ToPositiveIntegerWithTruncation(JSContext
* cx
, JS::Handle
<JS::Value
> value
,
333 const char* name
, double* result
);
336 * ToIntegerWithTruncation ( argument )
338 bool ToIntegerWithTruncation(JSContext
* cx
, JS::Handle
<JS::Value
> value
,
339 const char* name
, double* result
);
344 JSObject
* GetMethod(JSContext
* cx
, JS::Handle
<JSObject
*> object
,
345 JS::Handle
<PropertyName
*> name
);
348 * SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ]
351 PlainObject
* SnapshotOwnProperties(JSContext
* cx
, JS::Handle
<JSObject
*> source
);
354 * SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ]
357 PlainObject
* SnapshotOwnPropertiesIgnoreUndefined(JSContext
* cx
,
358 JS::Handle
<JSObject
*> source
);
361 * CopyDataProperties ( target, source, excludedKeys [ , excludedValues ] )
363 bool CopyDataProperties(JSContext
* cx
, JS::Handle
<PlainObject
*> target
,
364 JS::Handle
<JSObject
*> source
);
366 enum class TemporalDifference
{ Since
, Until
};
368 inline const char* ToName(TemporalDifference difference
) {
369 return difference
== TemporalDifference::Since
? "since" : "until";
372 struct DifferenceSettings final
{
373 TemporalUnit smallestUnit
= TemporalUnit::Auto
;
374 TemporalUnit largestUnit
= TemporalUnit::Auto
;
375 TemporalRoundingMode roundingMode
= TemporalRoundingMode::Trunc
;
376 Increment roundingIncrement
= Increment
{1};
380 * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits,
381 * fallbackSmallestUnit, smallestLargestDefaultUnit )
383 bool GetDifferenceSettings(JSContext
* cx
, TemporalDifference operation
,
384 JS::Handle
<PlainObject
*> options
,
385 TemporalUnitGroup unitGroup
,
386 TemporalUnit smallestAllowedUnit
,
387 TemporalUnit fallbackSmallestUnit
,
388 TemporalUnit smallestLargestDefaultUnit
,
389 DifferenceSettings
* result
);
392 * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits,
393 * fallbackSmallestUnit, smallestLargestDefaultUnit )
395 inline bool GetDifferenceSettings(JSContext
* cx
, TemporalDifference operation
,
396 JS::Handle
<PlainObject
*> options
,
397 TemporalUnitGroup unitGroup
,
398 TemporalUnit fallbackSmallestUnit
,
399 TemporalUnit smallestLargestDefaultUnit
,
400 DifferenceSettings
* result
) {
401 return GetDifferenceSettings(cx
, operation
, options
, unitGroup
,
402 TemporalUnit::Nanosecond
, fallbackSmallestUnit
,
403 smallestLargestDefaultUnit
, result
);
407 * Sets |result| to `true` when array iteration is still in its initial state.
409 bool IsArrayIterationSane(JSContext
* cx
, bool* result
);
411 } /* namespace js::temporal */
413 #endif /* builtin_temporal_Temporal_h */