fix: Date.prototype.setYear 无参/NaN 不再越界 panic,按 spec 设为 NaN
This commit is contained in:
@@ -734,6 +734,14 @@ pub fn date_get_year<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_year<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
// A missing year argument coerces to NaN; per B.2.4.2 a NaN year sets the date value to
|
||||
// NaN and returns NaN.
|
||||
let arg = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let y_num = oxide_runtime_api::to_number(arg);
|
||||
if y_num.is_nan() {
|
||||
set_timestamp(obj, f64::NAN);
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
if !ms.is_finite() {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
@@ -741,7 +749,7 @@ pub fn date_set_year<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
Some(d) => d,
|
||||
None => return NativeResult::Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let y = oxide_runtime_api::to_number(vm.reg(args[1])).trunc() as i32;
|
||||
let y = y_num.trunc() as i32;
|
||||
let full_year = if (0..=99).contains(&y) { y + 1900 } else { y };
|
||||
let nd = dt.with_year(full_year).unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
|
||||
@@ -345,3 +345,40 @@ fn date_set_utc_invalid_returns_nan() {
|
||||
let r = eval(&mut vm, "new Date(NaN).setUTCFullYear(2025)").unwrap();
|
||||
assert!(r.as_double().is_nan());
|
||||
}
|
||||
|
||||
// setYear with no argument must not index a missing argument register (previously panicked);
|
||||
// a missing / NaN year sets the date value to NaN and returns NaN (B.2.4.2).
|
||||
#[test]
|
||||
fn date_set_year_no_arg_returns_nan() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(&mut vm, "var d = new Date(0); d.setYear()").unwrap();
|
||||
assert!(r.as_double().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_set_year_no_arg_sets_value_nan() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(&mut vm, "var d = new Date(0); d.setYear(); d.valueOf()").unwrap();
|
||||
assert!(r.as_double().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_set_year_nan_from_string() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(&mut vm, "var d = new Date(0); d.setYear('not a number')").unwrap();
|
||||
assert!(r.as_double().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_set_year_two_digit_maps_to_1900s() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(&mut vm, "var d = new Date(0); d.setYear(95); d.getFullYear()").unwrap();
|
||||
assert_eq!(r.as_double() as i64, 1995);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_set_year_four_digit_kept() {
|
||||
let mut vm = Vm::new();
|
||||
let r = eval(&mut vm, "var d = new Date(0); d.setYear(2020); d.getFullYear()").unwrap();
|
||||
assert_eq!(r.as_double() as i64, 2020);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user