Skip to content

Commit 273d87e

Browse files
merge temporal_intrinsic into duration-and-durationproto
2 parents 70cd26e + 1996577 commit 273d87e

File tree

4 files changed

+154
-9
lines changed

4 files changed

+154
-9
lines changed

nova_vm/src/builtin_strings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ any
3939
apply
4040
arguments
4141
Array
42+
#[cfg(feature="temporal")]auto
4243
Array Iterator
4344
#[cfg(feature = "array-buffer")]ArrayBuffer
4445
#[cfg(feature = "math")]asin
@@ -138,6 +139,7 @@ find
138139
findIndex
139140
findLast
140141
findLastIndex
142+
#[cfg(feature = "temporal")]fractionalSecondDigits
141143
#[cfg(feature = "annex-b-string")]fixed
142144
#[cfg(feature = "regexp")]flags
143145
flat
@@ -452,6 +454,7 @@ SyntaxError
452454
#[cfg(feature = "regexp")]test
453455
then
454456
throw
457+
#[cfg(feature = "temporal")]timeZone
455458
toArray
456459
#[cfg(feature = "date")]toDateString
457460
toExponential

nova_vm/src/ecmascript/builtins/temporal.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ use temporal_rs::options::{DifferenceSettings, RoundingIncrement, RoundingMode,
1212

1313
use crate::{
1414
ecmascript::{
15+
abstract_operations::operations_on_objects::get,
1516
builders::ordinary_object_builder::OrdinaryObjectBuilder,
1617
builtins::temporal::{
1718
instant::instant_prototype::get_temporal_unit_valued_option,
1819
options::{get_rounding_increment_option, get_rounding_mode_option},
1920
},
20-
execution::{Agent, JsResult, Realm},
21-
types::{BUILTIN_STRING_MEMORY, IntoValue, Object},
21+
execution::{Agent, JsResult, Realm, agent::ExceptionType},
22+
types::{BUILTIN_STRING_MEMORY, IntoValue, Number, Object, Value},
2223
},
2324
engine::{
2425
context::{Bindable, GcScope, NoGcScope, trivially_bindable},
@@ -93,6 +94,78 @@ trivially_bindable!(Unit);
9394
trivially_bindable!(RoundingMode);
9495
trivially_bindable!(RoundingIncrement);
9596

97+
/// [13.15 GetTemporalFractionalSecondDigitsOption ( options )](https://tc39.es/proposal-temporal/#sec-temporal-gettemporalfractionalseconddigitsoption)
98+
/// The abstract operation GetTemporalFractionalSecondDigitsOption takes argument
99+
/// options (an Object) and returns either a normal completion containing
100+
/// either auto or an integer in the inclusive interval from 0 to 9,
101+
/// or a throw completion. It fetches and validates the "fractionalSecondDigits"
102+
/// property from options, returning a default if absent.
103+
pub(crate) fn get_temporal_fractional_second_digits_option<'gc>(
104+
agent: &mut Agent,
105+
options: Object<'gc>,
106+
mut gc: GcScope<'gc, '_>,
107+
) -> JsResult<'gc, Value<'gc>> {
108+
let options = options.bind(gc.nogc());
109+
// 1. Let digitsValue be ? Get(options, "fractionalSecondDigits").
110+
let digits_value = get(
111+
agent,
112+
options.unbind(),
113+
BUILTIN_STRING_MEMORY
114+
.fractionalSecondDigits
115+
.to_property_key(),
116+
gc.reborrow(),
117+
)
118+
.unbind()?
119+
.bind(gc.nogc());
120+
// 2. If digitsValue is undefined, return auto.
121+
if digits_value.unbind().is_undefined().bind(gc.nogc()) {
122+
return Ok(BUILTIN_STRING_MEMORY.auto.into_value());
123+
}
124+
let digits_value = digits_value.unbind();
125+
// 3. If digitsValue is not a Number, then
126+
if !digits_value.is_number() {
127+
// a. If ? ToString(digitsValue) is not "auto", throw a RangeError exception.
128+
if digits_value
129+
.to_string(agent, gc.reborrow())
130+
.unbind()?
131+
.as_bytes(agent)
132+
!= b"auto"
133+
{
134+
// b. Return auto.
135+
return Ok(BUILTIN_STRING_MEMORY.auto.into_value());
136+
}
137+
}
138+
let digits_value = digits_value.bind(gc.nogc());
139+
// 4. If digitsValue is NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception.
140+
if digits_value.unbind().is_nan(agent)
141+
|| digits_value.is_pos_infinity(agent)
142+
|| digits_value.is_neg_infinity(agent)
143+
{
144+
return Err(agent.throw_exception_with_static_message(
145+
ExceptionType::RangeError,
146+
"fractionalSecondDigits must be a finite number or \"auto\"",
147+
gc.into_nogc(),
148+
));
149+
}
150+
// 5. Let digitCount be floor(ℝ(digitsValue)).
151+
let digit_count = digits_value
152+
.unbind()
153+
.to_number(agent, gc.reborrow())
154+
.unbind()?
155+
.bind(gc.nogc());
156+
let digit_count = digit_count.into_f64(agent).floor() as i32;
157+
// 6. If digitCount < 0 or digitCount > 9, throw a RangeError exception.
158+
if digit_count < 0 || digit_count > 9 {
159+
return Err(agent.throw_exception_with_static_message(
160+
ExceptionType::RangeError,
161+
"fractionalSecondDigits must be between 0 and 9",
162+
gc.into_nogc(),
163+
));
164+
}
165+
// 7. Return digitCount.
166+
Ok(Number::from_i64(agent, digit_count.into(), gc.into_nogc()).into_value())
167+
}
168+
96169
/// [13.42 GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, fallbackSmallestUnit, smallestLargestDefaultUnit )](https://tc39.es/proposal-temporal/#sec-temporal-getdifferencesettings)
97170
/// The abstract operation GetDifferenceSettings takes arguments operation (since or until),
98171
/// options (an Object), unitGroup (date, time, or datetime), disallowedUnits (a List of Temporal units),

nova_vm/src/ecmascript/builtins/temporal/duration.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,11 +450,13 @@ pub(crate) fn to_temporal_partial_duration_record<'gc>(
450450
/// It returns a new Temporal.Duration instance that is the
451451
/// negation of duration.
452452
pub(crate) fn create_negated_temporal_duration<'gc>(
453-
_agent: &mut Agent,
454-
_item: temporal_rs::Duration,
453+
agent: &mut Agent,
454+
item: temporal_rs::Duration,
455455
mut _gc: GcScope<'gc, '_>,
456456
) -> JsResult<'gc, temporal_rs::Duration> {
457457
// 1. Return ! CreateTemporalDuration(-duration.[[Years]], -duration.[[Months]], -duration.[[Weeks]], -duration.[[Days]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]]).
458+
let _duration = temporal_rs::Duration::negated(&item);
459+
//TODO: IMPL create_temporal_duration()
458460
unimplemented!()
459461
}
460462

nova_vm/src/ecmascript/builtins/temporal/instant/instant_prototype.rs

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ use temporal_rs::options::{RoundingMode, RoundingOptions, Unit};
33
use crate::{
44
ecmascript::{
55
abstract_operations::{
6-
operations_on_objects::try_create_data_property_or_throw, type_conversion::to_number,
6+
operations_on_objects::{get, try_create_data_property_or_throw},
7+
type_conversion::to_number,
78
},
89
builders::ordinary_object_builder::OrdinaryObjectBuilder,
910
builtins::{
1011
ArgumentsList, Behaviour, Builtin, BuiltinGetter,
1112
ordinary::ordinary_object_create_with_intrinsics,
1213
temporal::{
1314
error::temporal_err_to_js_err,
15+
get_temporal_fractional_second_digits_option,
1416
instant::{
1517
add_duration_to_instant, create_temporal_instant, difference_temporal_instant,
1618
require_internal_slot_temporal_instant, to_temporal_instant,
@@ -408,11 +410,76 @@ impl TemporalInstantPrototype {
408410

409411
/// ### [8.3.11 Temporal.Instant.prototype.toString ( [ options ] )](https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tostring)
410412
fn to_string<'gc>(
411-
_agent: &mut Agent,
412-
_this_value: Value,
413-
_args: ArgumentsList,
414-
mut _gc: GcScope<'gc, '_>,
413+
agent: &mut Agent,
414+
this_value: Value,
415+
args: ArgumentsList,
416+
mut gc: GcScope<'gc, '_>,
415417
) -> JsResult<'gc, Value<'gc>> {
418+
// 1. Let instant be the this value.
419+
let options = args.get(0).bind(gc.nogc());
420+
let instant = this_value.bind(gc.nogc());
421+
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
422+
let instant = require_internal_slot_temporal_instant(agent, instant.unbind(), gc.nogc())
423+
.unbind()?
424+
.bind(gc.nogc());
425+
// 3. Let resolvedOptions be ? GetOptionsObject(options).
426+
let resolved_options = get_options_object(agent, options.unbind(), gc.nogc())
427+
.unbind()?
428+
.scope(agent, gc.nogc());
429+
// 4. NOTE: The following steps read options and perform independent validation in alphabetical order (GetTemporalFractionalSecondDigitsOption reads "fractionalSecondDigits" and GetRoundingModeOption reads "roundingMode").
430+
// 5. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
431+
let digits = get_temporal_fractional_second_digits_option(
432+
agent,
433+
resolved_options.get(agent),
434+
gc.reborrow(),
435+
)
436+
.unbind()?
437+
.bind(gc.nogc());
438+
// 6. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, trunc).
439+
let rounding_mode = get_rounding_mode_option(
440+
agent,
441+
resolved_options.get(agent),
442+
RoundingMode::Trunc,
443+
gc.reborrow(),
444+
)
445+
.unbind()?
446+
.bind(gc.nogc());
447+
// 7. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", unset).
448+
let smallest_unit = get_temporal_unit_valued_option(
449+
agent,
450+
resolved_options.get(agent),
451+
BUILTIN_STRING_MEMORY.smallestUnit.to_property_key(),
452+
gc.reborrow(),
453+
)
454+
.unbind()?
455+
.bind(gc.nogc());
456+
// 8. Let timeZone be ? Get(resolvedOptions, "timeZone").
457+
let tz = get(
458+
agent,
459+
resolved_options.get(agent),
460+
BUILTIN_STRING_MEMORY.timeZone.to_property_key(),
461+
gc.reborrow(),
462+
)
463+
.unbind()?
464+
.bind(gc.nogc());
465+
// 9. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
466+
// 10. If smallestUnit is hour, throw a RangeError exception.
467+
if smallest_unit.unwrap() == Unit::Hour {
468+
return Err(agent.throw_exception_with_static_message(
469+
ExceptionType::RangeError,
470+
"smallestUnit is hour",
471+
gc.into_nogc(),
472+
));
473+
}
474+
// 11. If timeZone is not undefined, then
475+
let _tz = if !tz.is_undefined() {
476+
// a. Set timeZone to ? ToTemporalTimeZoneIdentifier(timeZone).
477+
todo!()
478+
};
479+
// 12. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
480+
// 13. Let roundedNs be RoundTemporalInstant(instant.[[EpochNanoseconds]], precision.[[Increment]], precision.[[Unit]], roundingMode).
481+
// 14. Let roundedInstant be ! CreateTemporalInstant(roundedNs).
482+
// 15. Return TemporalInstantToString(roundedInstant, timeZone, precision.[[Precision]]).
416483
unimplemented!()
417484
}
418485

0 commit comments

Comments
 (0)