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:: { RoundingMode , ToStringRoundingOptions } ;
5+ use temporal_rs:: options:: { RoundingMode , RoundingOptions , ToStringRoundingOptions , Unit } ;
66
77use crate :: {
88 ecmascript:: {
99 Agent , ArgumentsList , BUILTIN_STRING_MEMORY , Behaviour , Builtin , BuiltinGetter ,
10- ExceptionType , JsResult , PropertyKey , Realm , String , Value ,
10+ ExceptionType , JsResult , PropertyKey , Realm , String , StringOptionType , Value ,
1111 builders:: OrdinaryObjectBuilder ,
1212 builtins:: temporal:: plain_time:: {
1313 add_duration_to_time, require_internal_slot_temporal_plain_time,
1414 } ,
15- get_options_object, get_rounding_mode_option, get_temporal_fractional_second_digits_option,
15+ create_temporal_plain_time, get_options_object, get_rounding_increment_option,
16+ get_rounding_mode_option, get_temporal_fractional_second_digits_option,
1617 get_temporal_unit_valued_option, temporal_err_to_js_err,
1718 } ,
1819 engine:: { Bindable , GcScope , NoGcScope , Scopable } ,
@@ -87,6 +88,13 @@ impl Builtin for TemporalPlainTimePrototypeAdd {
8788 const BEHAVIOUR : Behaviour = Behaviour :: Regular ( TemporalPlainTimePrototype :: add) ;
8889}
8990
91+ struct TemporalPlainTimePrototypeRound ;
92+ impl Builtin for TemporalPlainTimePrototypeRound {
93+ const NAME : String < ' static > = BUILTIN_STRING_MEMORY . round ;
94+ const LENGTH : u8 = 1 ;
95+ const BEHAVIOUR : Behaviour = Behaviour :: Regular ( TemporalPlainTimePrototype :: round) ;
96+ }
97+
9098struct TemporalPlainTimePrototypeSubtract ;
9199impl Builtin for TemporalPlainTimePrototypeSubtract {
92100 const NAME : String < ' static > = BUILTIN_STRING_MEMORY . subtract ;
@@ -239,6 +247,98 @@ impl TemporalPlainTimePrototype {
239247 . map ( Value :: from)
240248 }
241249
250+ /// ### [5.3.14 Temporal.PlainTime.prototype.round ( roundTo )](https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.round)
251+ fn round < ' gc > (
252+ agent : & mut Agent ,
253+ this_value : Value ,
254+ args : ArgumentsList ,
255+ mut gc : GcScope < ' gc , ' _ > ,
256+ ) -> JsResult < ' gc , Value < ' gc > > {
257+ let nogc = gc. nogc ( ) ;
258+ let this_value = this_value. bind ( nogc) ;
259+ let round_to = args. get ( 0 ) . bind ( nogc) ;
260+ // 1. Let plainTime be the this value.
261+ // 2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
262+ let plain_time = require_internal_slot_temporal_plain_time ( agent, this_value, nogc)
263+ . unbind ( ) ?
264+ . bind ( nogc) ;
265+ let inner_time = * plain_time. inner_plain_time ( agent) ;
266+ // 3. If roundTo is undefined, throw a TypeError exception.
267+ if round_to. is_undefined ( ) {
268+ return Err ( agent. throw_exception_with_static_message (
269+ ExceptionType :: TypeError ,
270+ "rountTo cannot be undefined" ,
271+ gc. into_nogc ( ) ,
272+ ) ) ;
273+ }
274+
275+ // 4. If roundTo is a String, then
276+ let options = if let Ok ( round_to) = String :: try_from ( round_to) {
277+ // a. Let paramString be roundTo.
278+ // b. Set roundTo to OrdinaryObjectCreate(null).
279+ // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
280+ let mut options = RoundingOptions :: default ( ) ;
281+ options. smallest_unit =
282+ Some ( Unit :: from_string ( agent, round_to. unbind ( ) , nogc) . unbind ( ) ?) ;
283+ options
284+ } else {
285+ // 5. Else,
286+ // a. Set roundTo to ? GetOptionsObject(roundTo).
287+ let round_to = get_options_object ( agent, round_to, nogc)
288+ . unbind ( ) ?
289+ . map ( |r| r. scope ( agent, nogc) ) ;
290+ // 6. NOTE: The following steps read options and perform independent validation in alphabetical
291+ // order (GetRoundingIncrementOption reads "roundingIncrement" and GetRoundingModeOption reads "roundingMode").
292+ let mut options = RoundingOptions :: default ( ) ;
293+
294+ let ( rounding_increment, rounding_mode, smallest_unit) =
295+ if let Some ( round_to) = round_to {
296+ // 7. Let roundingIncrement be ? GetRoundingIncrementOption(roundTo).
297+ let rounding_increment =
298+ get_rounding_increment_option ( agent, round_to. get ( agent) , gc. reborrow ( ) )
299+ . unbind ( ) ?;
300+ // 8. Let roundingMode be ? GetRoundingModeOption(roundTo, half-expand).
301+ let rounding_mode = get_rounding_mode_option (
302+ agent,
303+ round_to. get ( agent) ,
304+ RoundingMode :: default ( ) ,
305+ gc. reborrow ( ) ,
306+ )
307+ . unbind ( ) ?;
308+ // 9. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
309+ let smallest_unit = get_temporal_unit_valued_option (
310+ agent,
311+ round_to. get ( agent) ,
312+ BUILTIN_STRING_MEMORY . smallestUnit . into ( ) ,
313+ gc. reborrow ( ) ,
314+ )
315+ . unbind ( ) ?;
316+ ( rounding_increment, rounding_mode, smallest_unit)
317+ } else {
318+ Default :: default ( )
319+ } ;
320+
321+ options. increment = Some ( rounding_increment) ;
322+ options. rounding_mode = Some ( rounding_mode) ;
323+ options. smallest_unit = smallest_unit;
324+ options
325+ } ;
326+
327+ // 10. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
328+ // 11. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
329+ // 12. Assert: maximum is not unset.
330+ // 13. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
331+ // 14. Let result be RoundTime(plainTime.[[Time]], roundingIncrement, smallestUnit, roundingMode).
332+ let result = inner_time
333+ . round ( options)
334+ . map_err ( |e| temporal_err_to_js_err ( agent, e, gc. nogc ( ) ) )
335+ . unbind ( ) ?;
336+ // 15. Return ! CreateTemporalTime(result).
337+ Ok ( create_temporal_plain_time ( agent, result, None , gc)
338+ . unwrap ( )
339+ . into ( ) )
340+ }
341+
242342 /// ### [4.3.10 Temporal.PlainTime.prototype.subtract ( temporalDurationLike )](https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.subtract)
243343 fn subtract < ' gc > (
244344 agent : & mut Agent ,
@@ -395,7 +495,7 @@ impl TemporalPlainTimePrototype {
395495 let plain_time_constructor = intrinsics. temporal_plain_time ( ) ;
396496
397497 OrdinaryObjectBuilder :: new_intrinsic_object ( agent, realm, this)
398- . with_property_capacity ( 14 )
498+ . with_property_capacity ( 15 )
399499 . with_prototype ( object_prototype)
400500 . with_constructor_property ( plain_time_constructor)
401501 . with_builtin_function_getter_property :: < TemporalPlainTimePrototypeGetHour > ( )
@@ -405,6 +505,7 @@ impl TemporalPlainTimePrototype {
405505 . with_builtin_function_getter_property :: < TemporalPlainTimePrototypeGetNanosecond > ( )
406506 . with_builtin_function_getter_property :: < TemporalPlainTimePrototypeGetMillisecond > ( )
407507 . with_builtin_function_property :: < TemporalPlainTimePrototypeAdd > ( )
508+ . with_builtin_function_property :: < TemporalPlainTimePrototypeRound > ( )
408509 . with_builtin_function_property :: < TemporalPlainTimePrototypeSubtract > ( )
409510 . with_builtin_function_property :: < TemporalPlainTimePrototypeToJSON > ( )
410511 . with_builtin_function_property :: < TemporalPlainTimePrototypeToLocaleString > ( )
0 commit comments