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 , RoundingOptions , Unit } ;
6+
57use crate :: {
68 ecmascript:: {
7- Agent , ArgumentsList , BUILTIN_STRING_MEMORY , Behaviour , Builtin , BuiltinGetter , JsResult ,
8- PropertyKey , Realm , String , Value ,
9+ Agent , ArgumentsList , BUILTIN_STRING_MEMORY , Behaviour , Builtin , BuiltinGetter ,
10+ ExceptionType , JsResult , PropertyKey , Realm , String , StringOptionType , Value ,
911 builders:: OrdinaryObjectBuilder ,
1012 builtins:: temporal:: plain_time:: {
1113 add_duration_to_time, require_internal_slot_temporal_plain_time,
1214 } ,
15+ create_temporal_plain_time, get_options_object, get_rounding_increment_option,
16+ get_rounding_mode_option, get_temporal_unit_valued_option, temporal_err_to_js_err,
1317 } ,
14- engine:: { Bindable , GcScope , NoGcScope } ,
18+ engine:: { Bindable , GcScope , NoGcScope , Scopable } ,
1519 heap:: WellKnownSymbols ,
1620} ;
1721
@@ -90,6 +94,12 @@ impl Builtin for TemporalPlainTimePrototypeSubtract {
9094 const BEHAVIOUR : Behaviour = Behaviour :: Regular ( TemporalPlainTimePrototype :: subtract) ;
9195}
9296
97+ struct TemporalPlainTimePrototypeRound ;
98+ impl Builtin for TemporalPlainTimePrototypeRound {
99+ const NAME : String < ' static > = BUILTIN_STRING_MEMORY . round ;
100+ const LENGTH : u8 = 1 ;
101+ const BEHAVIOUR : Behaviour = Behaviour :: Regular ( TemporalPlainTimePrototype :: round) ;
102+ }
93103impl TemporalPlainTimePrototype {
94104 /// ### [4.3.4 get Temporal.PlainTime.prototype.minute](https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.minute)
95105 pub ( crate ) fn get_minute < ' gc > (
@@ -228,6 +238,96 @@ impl TemporalPlainTimePrototype {
228238 . map ( Value :: from)
229239 }
230240
241+ /// ### [5.3.14 Temporal.PlainTime.prototype.round ( roundTo )](https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.round)
242+ fn round < ' gc > (
243+ agent : & mut Agent ,
244+ this_value : Value ,
245+ args : ArgumentsList ,
246+ mut gc : GcScope < ' gc , ' _ > ,
247+ ) -> JsResult < ' gc , Value < ' gc > > {
248+ let this_value = this_value. bind ( gc. nogc ( ) ) ;
249+ let round_to = args. get ( 0 ) . bind ( gc. nogc ( ) ) ;
250+ // 1. Let plainTime be the this value.
251+ // 2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
252+ let plain_time = require_internal_slot_temporal_plain_time ( agent, this_value, gc. nogc ( ) )
253+ . unbind ( ) ?;
254+ let inner_time = plain_time. inner_plain_time ( agent) ;
255+ // 3. If roundTo is undefined, throw a TypeError exception.
256+ if round_to. is_undefined ( ) {
257+ return Err ( agent. throw_exception_with_static_message (
258+ ExceptionType :: TypeError ,
259+ "rountTo cannot be undefined" ,
260+ gc. into_nogc ( ) ,
261+ ) ) ;
262+ }
263+
264+ // 4. If roundTo is a String, then
265+ let options = if let Ok ( round_to) = String :: try_from ( round_to) {
266+ // a. Let paramString be roundTo.
267+ // b. Set roundTo to OrdinaryObjectCreate(null).
268+ // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
269+ let mut options = RoundingOptions :: default ( ) ;
270+ options. smallest_unit =
271+ Some ( Unit :: from_string ( agent, round_to. unbind ( ) , gc. nogc ( ) ) . unbind ( ) ?) ;
272+ options
273+ } else {
274+ // 5. Else,
275+ // a. Set roundTo to ? GetOptionsObject(roundTo).
276+ let round_to = get_options_object ( agent, round_to, gc. nogc ( ) )
277+ . unbind ( ) ?
278+ . map ( |r| r. scope ( agent, gc. nogc ( ) ) ) ;
279+ // 6. NOTE: The following steps read options and perform independent validation in alphabetical
280+ // order (GetRoundingIncrementOption reads "roundingIncrement" and GetRoundingModeOption reads "roundingMode").
281+ let mut options = RoundingOptions :: default ( ) ;
282+
283+ let ( rounding_increment, rounding_mode, smallest_unit) =
284+ if let Some ( round_to) = round_to {
285+ // 7. Let roundingIncrement be ? GetRoundingIncrementOption(roundTo).
286+ let rounding_increment =
287+ get_rounding_increment_option ( agent, round_to. get ( agent) , gc. reborrow ( ) )
288+ . unbind ( ) ?;
289+ // 8. Let roundingMode be ? GetRoundingModeOption(roundTo, half-expand).
290+ let rounding_mode = get_rounding_mode_option (
291+ agent,
292+ round_to. get ( agent) ,
293+ RoundingMode :: default ( ) ,
294+ gc. reborrow ( ) ,
295+ )
296+ . unbind ( ) ?;
297+ // 9. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
298+ let smallest_unit = get_temporal_unit_valued_option (
299+ agent,
300+ round_to. get ( agent) ,
301+ BUILTIN_STRING_MEMORY . smallestUnit . into ( ) ,
302+ gc. reborrow ( ) ,
303+ )
304+ . unbind ( ) ?;
305+ ( rounding_increment, rounding_mode, smallest_unit)
306+ } else {
307+ Default :: default ( )
308+ } ;
309+
310+ options. increment = Some ( rounding_increment) ;
311+ options. rounding_mode = Some ( rounding_mode) ;
312+ options. smallest_unit = smallest_unit;
313+ options
314+ } ;
315+
316+ // 10. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
317+ // 11. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
318+ // 12. Assert: maximum is not unset.
319+ // 13. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
320+ // 14. Let result be RoundTime(plainTime.[[Time]], roundingIncrement, smallestUnit, roundingMode).
321+ let result = inner_time
322+ . round ( options)
323+ . map_err ( |e| temporal_err_to_js_err ( agent, e, gc. nogc ( ) ) )
324+ . unbind ( ) ?;
325+ // 15. Return ! CreateTemporalTime(result).
326+ Ok ( create_temporal_plain_time ( agent, result, None , gc)
327+ . unwrap ( )
328+ . into ( ) )
329+ }
330+
231331 pub ( crate ) fn create_intrinsic ( agent : & mut Agent , realm : Realm < ' static > , _: NoGcScope ) {
232332 let intrinsics = agent. get_realm_record_by_id ( realm) . intrinsics ( ) ;
233333 let this = intrinsics. temporal_plain_time_prototype ( ) ;
@@ -246,6 +346,7 @@ impl TemporalPlainTimePrototype {
246346 . with_builtin_function_getter_property :: < TemporalPlainTimePrototypeGetMillisecond > ( )
247347 . with_builtin_function_property :: < TemporalPlainTimePrototypeAdd > ( )
248348 . with_builtin_function_property :: < TemporalPlainTimePrototypeSubtract > ( )
349+ . with_builtin_function_property :: < TemporalPlainTimePrototypeRound > ( )
249350 . with_property ( |builder| {
250351 builder
251352 . with_key ( WellKnownSymbols :: ToStringTag . into ( ) )
0 commit comments