Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit59a7566

Browse files
authored
Throw on negative values when usingOverflow::Reject inTemporal.PlainTime.with (#4490)
This PR fixes the last failing test on the `Temporal.PlainTime` testsuite([`throws-if-time-is-invalid-when-overflow-is-reject.js`](https://github.com/tc39/test262/blob/main/test/built-ins/Temporal/PlainTime/prototype/with/throws-if-time-is-invalid-when-overflow-is-reject.js)).
1 parentbc1f36e commit59a7566

File tree

2 files changed

+128
-31
lines changed

2 files changed

+128
-31
lines changed

‎core/engine/src/builtins/temporal/plain_time/mod.rs‎

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,19 @@ use crate::{
2121
};
2222
usecrate::{builtins::temporal::options::get_digits_option, value::JsVariant};
2323
use boa_gc::{Finalize,Trace};
24+
use num_traits::{AsPrimitive,PrimInt};
2425
use temporal_rs::{
2526
PlainTimeasPlainTimeInner,
2627
options::{
2728
Overflow,RoundingIncrement,RoundingMode,RoundingOptions,ToStringRoundingOptions,Unit,
2829
},
2930
partial::PartialTime,
31+
primitive::FiniteF64,
3032
};
3133

34+
#[cfg(test)]
35+
mod tests;
36+
3237
/// The `Temporal.PlainTime` built-in implementation.
3338
///
3439
/// More information:
@@ -540,13 +545,19 @@ impl PlainTime {
540545
};
541546

542547
// Steps 5-16 equate to the below
543-
let partial =to_partial_time_record(&partial_object, context)?;
548+
let partial =to_js_partial_time_record(&partial_object, context)?;
544549
// 17. Let resolvedOptions be ? GetOptionsObject(options).
545550
// 18. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
546551
let options =get_options_object(args.get_or_undefined(1))?;
547552
let overflow =get_option::<Overflow>(&options,js_string!("overflow"), context)?;
548553

549-
create_temporal_time(time.inner.with(partial, overflow)?,None, context).map(Into::into)
554+
create_temporal_time(
555+
time.inner
556+
.with(partial.as_temporal_partial_time(overflow)?, overflow)?,
557+
None,
558+
context,
559+
)
560+
.map(Into::into)
550561
}
551562

552563
/// 4.3.12 `Temporal.PlainTime.prototype.until ( other [ , options ] )`
@@ -907,12 +918,13 @@ pub(crate) fn to_temporal_time(
907918
// e. Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]],
908919
// result.[[Second]], result.[[Millisecond]], result.[[Microsecond]],
909920
// result.[[Nanosecond]], overflow).
910-
let partial =to_partial_time_record(&object, context)?;
921+
let partial =to_js_partial_time_record(&object, context)?;
911922

912923
let options =get_options_object(options)?;
913924
let overflow =get_option::<Overflow>(&options,js_string!("overflow"), context)?;
914925

915-
PlainTimeInner::from_partial(partial, overflow).map_err(Into::into)
926+
PlainTimeInner::from_partial(partial.as_temporal_partial_time(overflow)?, overflow)
927+
.map_err(Into::into)
916928
}
917929
// 3. Else,
918930
JsVariant::String(str) =>{
@@ -934,59 +946,100 @@ pub(crate) fn to_temporal_time(
934946
// 4. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).
935947
}
936948

937-
pub(crate)fnto_partial_time_record(
949+
/// A `PartialTime` represents partially filled `Time` fields.
950+
#[derive(Debug,Default,Clone,Copy,PartialEq)]
951+
pubstructJsPartialTime{
952+
/// A potentially set `hour` field.
953+
pubhour:Option<FiniteF64>,
954+
/// A potentially set `minute` field.
955+
pubminute:Option<FiniteF64>,
956+
/// A potentially set `second` field.
957+
pubsecond:Option<FiniteF64>,
958+
/// A potentially set `millisecond` field.
959+
pubmillisecond:Option<FiniteF64>,
960+
/// A potentially set `microsecond` field.
961+
pubmicrosecond:Option<FiniteF64>,
962+
/// A potentially set `nanosecond` field.
963+
pubnanosecond:Option<FiniteF64>,
964+
}
965+
966+
implJsPartialTime{
967+
fnas_temporal_partial_time(&self,overflow:Option<Overflow>) ->JsResult<PartialTime>{
968+
fncheck(value:Option<FiniteF64>,typ:&'staticstr,max:u16) ->JsResult<()>{
969+
ifletSome(value) = value
970+
&& value.as_inner().is_sign_negative()
971+
{
972+
returnErr(JsNativeError::range()
973+
.with_message(format!("time value '{typ}' not in 0..{max}: {value}"))
974+
.into());
975+
}
976+
Ok(())
977+
}
978+
979+
fntruncate<T>(value:Option<FiniteF64>) ->Option<T>
980+
where
981+
T:PrimInt +AsPrimitive<f64>,
982+
f64:AsPrimitive<T>,
983+
{
984+
value
985+
.as_ref()
986+
.map(FiniteF64::as_integer_with_truncation::<T>)
987+
}
988+
989+
if overflow ==Some(Overflow::Reject){
990+
check(self.hour,"hour",23)?;
991+
check(self.minute,"minute",59)?;
992+
check(self.second,"second",59)?;
993+
check(self.millisecond,"millisecond",999)?;
994+
check(self.microsecond,"microsecond",999)?;
995+
check(self.nanosecond,"nanosecond",999)?;
996+
}
997+
998+
Ok(PartialTime::new()
999+
.with_hour(truncate(self.hour))
1000+
.with_minute(truncate(self.minute))
1001+
.with_second(truncate(self.second))
1002+
.with_millisecond(truncate(self.millisecond))
1003+
.with_microsecond(truncate(self.microsecond))
1004+
.with_nanosecond(truncate(self.nanosecond)))
1005+
}
1006+
}
1007+
1008+
pub(crate)fnto_js_partial_time_record(
9381009
partial_object:&JsObject,
9391010
context:&mutContext,
940-
) ->JsResult<PartialTime>{
1011+
) ->JsResult<JsPartialTime>{
9411012
let hour = partial_object
9421013
.get(js_string!("hour"), context)?
943-
.map(|v|{
944-
let finite = v.to_finitef64(context)?;
945-
Ok::<u8,JsError>(finite.as_integer_with_truncation::<u8>())
946-
})
1014+
.map(|v| v.to_finitef64(context))
9471015
.transpose()?;
9481016

9491017
let microsecond = partial_object
9501018
.get(js_string!("microsecond"), context)?
951-
.map(|v|{
952-
let finite = v.to_finitef64(context)?;
953-
Ok::<u16,JsError>(finite.as_integer_with_truncation::<u16>())
954-
})
1019+
.map(|v| v.to_finitef64(context))
9551020
.transpose()?;
9561021

9571022
let millisecond = partial_object
9581023
.get(js_string!("millisecond"), context)?
959-
.map(|v|{
960-
let finite = v.to_finitef64(context)?;
961-
Ok::<u16,JsError>(finite.as_integer_with_truncation::<u16>())
962-
})
1024+
.map(|v| v.to_finitef64(context))
9631025
.transpose()?;
9641026

9651027
let minute = partial_object
9661028
.get(js_string!("minute"), context)?
967-
.map(|v|{
968-
let finite = v.to_finitef64(context)?;
969-
Ok::<u8,JsError>(finite.as_integer_with_truncation::<u8>())
970-
})
1029+
.map(|v| v.to_finitef64(context))
9711030
.transpose()?;
9721031

9731032
let nanosecond = partial_object
9741033
.get(js_string!("nanosecond"), context)?
975-
.map(|v|{
976-
let finite = v.to_finitef64(context)?;
977-
Ok::<u16,JsError>(finite.as_integer_with_truncation::<u16>())
978-
})
1034+
.map(|v| v.to_finitef64(context))
9791035
.transpose()?;
9801036

9811037
let second = partial_object
9821038
.get(js_string!("second"), context)?
983-
.map(|v|{
984-
let finite = v.to_finitef64(context)?;
985-
Ok::<u8,JsError>(finite.as_integer_with_truncation::<u8>())
986-
})
1039+
.map(|v| v.to_finitef64(context))
9871040
.transpose()?;
9881041

989-
Ok(PartialTime{
1042+
Ok(JsPartialTime{
9901043
hour,
9911044
minute,
9921045
second,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use indoc::indoc;
2+
3+
usecrate::{JsNativeErrorKind,TestAction, run_test_actions};
4+
5+
#[test]
6+
fnwith_overflow_reject_throws_on_negative_components(){
7+
// Temporal Builtin tests.
8+
run_test_actions([
9+
TestAction::run(indoc!{"
10+
let plain = new Temporal.PlainTime();
11+
let options = {overflow: 'reject'};
12+
"}),
13+
TestAction::assert_native_error(
14+
"plain.with({hour: -1}, options)",
15+
JsNativeErrorKind::Range,
16+
"time value 'hour' not in 0..23: -1",
17+
),
18+
TestAction::assert_native_error(
19+
"plain.with({minute: -1}, options)",
20+
JsNativeErrorKind::Range,
21+
"time value 'minute' not in 0..59: -1",
22+
),
23+
TestAction::assert_native_error(
24+
"plain.with({second: -1}, options)",
25+
JsNativeErrorKind::Range,
26+
"time value 'second' not in 0..59: -1",
27+
),
28+
TestAction::assert_native_error(
29+
"plain.with({millisecond: -1}, options)",
30+
JsNativeErrorKind::Range,
31+
"time value 'millisecond' not in 0..999: -1",
32+
),
33+
TestAction::assert_native_error(
34+
"plain.with({microsecond: -1}, options)",
35+
JsNativeErrorKind::Range,
36+
"time value 'microsecond' not in 0..999: -1",
37+
),
38+
TestAction::assert_native_error(
39+
"plain.with({nanosecond: -1}, options)",
40+
JsNativeErrorKind::Range,
41+
"time value 'nanosecond' not in 0..999: -1",
42+
),
43+
]);
44+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp