Skip to content

Commit 9bf44d2

Browse files
authored
feat(ecmascript): PlainTime.prototype.toString (#985)
1 parent 807c367 commit 9bf44d2

3 files changed

Lines changed: 85 additions & 11 deletions

File tree

nova_vm/src/ecmascript/builtins/temporal/plain_time/plain_time_prototype.rs

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
use temporal_rs::options::ToStringRoundingOptions;
5+
use temporal_rs::options::{RoundingMode, ToStringRoundingOptions};
66

77
use crate::{
88
ecmascript::{
@@ -12,9 +12,10 @@ use crate::{
1212
builtins::temporal::plain_time::{
1313
add_duration_to_time, require_internal_slot_temporal_plain_time,
1414
},
15-
temporal_err_to_js_err,
15+
get_options_object, get_rounding_mode_option, get_temporal_fractional_second_digits_option,
16+
get_temporal_unit_valued_option, temporal_err_to_js_err,
1617
},
17-
engine::{Bindable, GcScope, NoGcScope},
18+
engine::{Bindable, GcScope, NoGcScope, Scopable},
1819
heap::WellKnownSymbols,
1920
};
2021

@@ -100,6 +101,13 @@ impl Builtin for TemporalPlainTimePrototypeToJSON {
100101
const BEHAVIOUR: Behaviour = Behaviour::Regular(TemporalPlainTimePrototype::to_json);
101102
}
102103

104+
struct TemporalPlainTimePrototypeToString;
105+
impl Builtin for TemporalPlainTimePrototypeToString {
106+
const NAME: String<'static> = BUILTIN_STRING_MEMORY.toString;
107+
const LENGTH: u8 = 0;
108+
const BEHAVIOUR: Behaviour = Behaviour::Regular(TemporalPlainTimePrototype::to_string);
109+
}
110+
103111
struct TemporalPlainTimePrototypeValueOf;
104112
impl Builtin for TemporalPlainTimePrototypeValueOf {
105113
const NAME: String<'static> = BUILTIN_STRING_MEMORY.valueOf;
@@ -265,6 +273,76 @@ impl TemporalPlainTimePrototype {
265273
}
266274
}
267275

276+
/// ### [4.3.16 Temporal.PlainTime.prototype.toString ( [ options ] )](https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tostring)
277+
fn to_string<'gc>(
278+
agent: &mut Agent,
279+
this_value: Value,
280+
args: ArgumentsList,
281+
mut gc: GcScope<'gc, '_>,
282+
) -> JsResult<'gc, Value<'gc>> {
283+
let options = args.get(0).bind(gc.nogc());
284+
// 1. Let plainTime be the this value.
285+
let plain_time = this_value.bind(gc.nogc());
286+
// 2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
287+
let plain_time =
288+
require_internal_slot_temporal_plain_time(agent, plain_time.unbind(), gc.nogc())
289+
.unbind()?
290+
.scope(agent, gc.nogc());
291+
// 3. Let resolvedOptions be ? GetOptionsObject(options).
292+
let resolved_options = get_options_object(agent, options, gc.nogc())
293+
.unbind()?
294+
.map(|r| r.scope(agent, gc.nogc()));
295+
296+
let (digits, rounding_mode, smallest_unit) =
297+
if let Some(resolved_options) = resolved_options {
298+
// 4. NOTE: The following steps read options and perform independent validation
299+
// in alphabetical order (GetTemporalFractionalSecondDigitsOption reads
300+
// "fractionalSecondDigits" and GetRoundingModeOption reads "roundingMode").
301+
// 5. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
302+
let digits = get_temporal_fractional_second_digits_option(
303+
agent,
304+
resolved_options.get(agent),
305+
gc.reborrow(),
306+
)
307+
.unbind()?;
308+
// 6. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, trunc).
309+
let rounding_mode = get_rounding_mode_option(
310+
agent,
311+
resolved_options.get(agent),
312+
RoundingMode::Trunc,
313+
gc.reborrow(),
314+
)
315+
.unbind()?;
316+
// 7. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", unset).
317+
let smallest_unit = get_temporal_unit_valued_option(
318+
agent,
319+
resolved_options.get(agent),
320+
BUILTIN_STRING_MEMORY.smallestUnit.to_property_key(),
321+
gc.reborrow(),
322+
)
323+
.unbind()?;
324+
(digits, rounding_mode, smallest_unit)
325+
} else {
326+
Default::default()
327+
};
328+
329+
// 8. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
330+
// 9. If smallestUnit is hour, throw a RangeError exception.
331+
// 10. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
332+
// 11. Let roundResult be RoundTime(plainTime.[[Time]], precision.[[Increment]], precision.[[Unit]], roundingMode).
333+
let options = ToStringRoundingOptions {
334+
precision: digits,
335+
smallest_unit,
336+
rounding_mode: Some(rounding_mode),
337+
};
338+
// 12. Return TimeRecordToString(roundResult, precision.[[Precision]]).
339+
let plain_time = unsafe { plain_time.take(agent) };
340+
match plain_time.inner_plain_time(agent).to_ixdtf_string(options) {
341+
Ok(string) => Ok(Value::from_string(agent, string, gc.into_nogc())),
342+
Err(err) => Err(temporal_err_to_js_err(agent, err, gc.into_nogc())),
343+
}
344+
}
345+
268346
/// ### [4.3.19 Temporal.PlainTime.prototype.valueOf](https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.valueof)
269347
fn value_of<'gc>(
270348
agent: &mut Agent,
@@ -287,7 +365,7 @@ impl TemporalPlainTimePrototype {
287365
let plain_time_constructor = intrinsics.temporal_plain_time();
288366

289367
OrdinaryObjectBuilder::new_intrinsic_object(agent, realm, this)
290-
.with_property_capacity(12)
368+
.with_property_capacity(13)
291369
.with_prototype(object_prototype)
292370
.with_constructor_property(plain_time_constructor)
293371
.with_builtin_function_getter_property::<TemporalPlainTimePrototypeGetHour>()
@@ -299,6 +377,7 @@ impl TemporalPlainTimePrototype {
299377
.with_builtin_function_property::<TemporalPlainTimePrototypeAdd>()
300378
.with_builtin_function_property::<TemporalPlainTimePrototypeSubtract>()
301379
.with_builtin_function_property::<TemporalPlainTimePrototypeToJSON>()
380+
.with_builtin_function_property::<TemporalPlainTimePrototypeToString>()
302381
.with_builtin_function_property::<TemporalPlainTimePrototypeValueOf>()
303382
.with_property(|builder| {
304383
builder

tests/expectations.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4081,7 +4081,6 @@
40814081
"built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js": "FAIL",
40824082
"built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js": "FAIL",
40834083
"built-ins/Temporal/PlainTime/prototype/toString/basic.js": "FAIL",
4084-
"built-ins/Temporal/PlainTime/prototype/toString/branding.js": "FAIL",
40854084
"built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js": "FAIL",
40864085
"built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js": "FAIL",
40874086
"built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js": "FAIL",
@@ -4091,12 +4090,8 @@
40914090
"built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js": "FAIL",
40924091
"built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js": "FAIL",
40934092
"built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js": "FAIL",
4094-
"built-ins/Temporal/PlainTime/prototype/toString/options-object.js": "FAIL",
4095-
"built-ins/Temporal/PlainTime/prototype/toString/options-read-before-algorithmic-validation.js": "FAIL",
40964093
"built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js": "FAIL",
4097-
"built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js": "FAIL",
40984094
"built-ins/Temporal/PlainTime/prototype/toString/order-of-operations.js": "FAIL",
4099-
"built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js": "FAIL",
41004095
"built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js": "FAIL",
41014096
"built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js": "FAIL",
41024097
"built-ins/Temporal/PlainTime/prototype/toString/roundingmode-expand.js": "FAIL",

tests/metrics.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"results": {
33
"crash": 52,
4-
"fail": 6888,
5-
"pass": 40412,
4+
"fail": 6883,
5+
"pass": 40417,
66
"skip": 3326,
77
"timeout": 18,
88
"unresolved": 37

0 commit comments

Comments
 (0)