From a171d3755d1a9dcef6ba55c3ff9b8194cfa8449b Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sun, 16 Aug 2026 18:50:55 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20PlainDate=20=E5=91=A8/=E6=9C=88/?= =?UTF-8?q?=E6=97=B6=E4=BB=A3=20getter=20=E8=A1=A5=20ensure=20branding=20?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/temporal.rs | 20 +++----------- .../oxide_vm/tests/builtins_temporal_tests.rs | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/crates/oxide_builtins/src/temporal.rs b/crates/oxide_builtins/src/temporal.rs index 8af31dc..6da5f0c 100644 --- a/crates/oxide_builtins/src/temporal.rs +++ b/crates/oxide_builtins/src/temporal.rs @@ -4590,10 +4590,7 @@ pub fn plain_date_days_in_month(vm: &mut H, args: &[u8]) -> NativeRes /// `Temporal.PlainDate.prototype.daysInWeek` getter:恒 7。 pub fn plain_date_days_in_week(vm: &mut H, args: &[u8]) -> NativeResult { - let _ = match receiver_obj(vm, args) { - Ok(p) => p, - Err(e) => return NativeResult::Err(e), - }; + let _ = native_try!(plain_date_ymd(vm, args)); NativeResult::Ok(JsValue::float(7.0)) } @@ -4612,10 +4609,7 @@ pub fn plain_date_days_in_year(vm: &mut H, args: &[u8]) -> NativeResu /// `Temporal.PlainDate.prototype.monthsInYear` getter:恒 12(ISO 日历)。 pub fn plain_date_months_in_year(vm: &mut H, args: &[u8]) -> NativeResult { - let _ = match receiver_obj(vm, args) { - Ok(p) => p, - Err(e) => return NativeResult::Err(e), - }; + let _ = native_try!(plain_date_ymd(vm, args)); NativeResult::Ok(JsValue::float(12.0)) } @@ -4657,19 +4651,13 @@ pub fn plain_date_month_code(vm: &mut H, args: &[u8]) -> NativeResult /// `Temporal.PlainDate.prototype.era` getter:ISO 日历无纪元,恒 undefined。 pub fn plain_date_era(vm: &mut H, args: &[u8]) -> NativeResult { - let _ = match receiver_obj(vm, args) { - Ok(p) => p, - Err(e) => return NativeResult::Err(e), - }; + let _ = native_try!(plain_date_ymd(vm, args)); NativeResult::Ok(JsValue::undefined()) } /// `Temporal.PlainDate.prototype.eraYear` getter:ISO 日历无纪元,恒 undefined。 pub fn plain_date_era_year(vm: &mut H, args: &[u8]) -> NativeResult { - let _ = match receiver_obj(vm, args) { - Ok(p) => p, - Err(e) => return NativeResult::Err(e), - }; + let _ = native_try!(plain_date_ymd(vm, args)); NativeResult::Ok(JsValue::undefined()) } diff --git a/crates/oxide_vm/tests/builtins_temporal_tests.rs b/crates/oxide_vm/tests/builtins_temporal_tests.rs index 9b88fcc..4e058b3 100644 --- a/crates/oxide_vm/tests/builtins_temporal_tests.rs +++ b/crates/oxide_vm/tests/builtins_temporal_tests.rs @@ -965,3 +965,30 @@ fn plain_date_from_instance_preserves_calendar() { .unwrap(); assert_eq!(str_val(&vm, r), "gregory,gregory,hebrew,hebrew,gregory,gregory,hebrew"); } + +#[test] +fn plain_date_brand_only_getters_require_plain_date_receiver() { + let mut vm = Vm::new(); + // 4 个品牌-only getter 对普通对象 receiver 必须抛 TypeError。 + // 经 property descriptor 取真实 getter 函数(原型上的 `.get` 访问不可靠, + // 会拿到 undefined),修复前只查 is_object 不查品牌 → 返回常量不抛,断言失败。 + for getter in ["daysInWeek", "monthsInYear", "era", "eraYear"] { + let r = eval( + &mut vm, + &format!( + "var g = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, '{getter}').get; \ + try {{ g.call({{}}); 'no-throw' }} catch (e) {{ e.constructor.name }}" + ), + ) + .unwrap(); + assert_eq!(str_val(&vm, r), "TypeError", "{getter} on plain object must throw"); + } + // 正常 PlainDate receiver 不回归。 + let r = eval( + &mut vm, + "var p = new Temporal.PlainDate(2000, 5, 2); \ + [p.daysInWeek, p.monthsInYear, p.era === undefined, p.eraYear === undefined].join(',')", + ) + .unwrap(); + assert_eq!(str_val(&vm, r), "7,12,true,true"); +}