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
77use 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+
103111struct TemporalPlainTimePrototypeValueOf ;
104112impl 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
0 commit comments