diff --git a/crates/oxide_builtins/src/temporal.rs b/crates/oxide_builtins/src/temporal.rs index e8b4b2e0..5152bd74 100644 --- a/crates/oxide_builtins/src/temporal.rs +++ b/crates/oxide_builtins/src/temporal.rs @@ -7862,6 +7862,17 @@ pub fn plain_month_day_to_json(vm: &mut H, args: &[u8]) -> NativeResu plain_month_day_default_string(vm, args) } +/// `Temporal.PlainMonthDay.prototype.toLocaleString()`:locale/options 无引擎行为, +/// 恒输出默认形串。 +pub fn plain_month_day_to_locale_string(vm: &mut H, args: &[u8]) -> NativeResult { + plain_month_day_default_string(vm, args) +} + +/// `Temporal.PlainMonthDay.prototype.valueOf()`:Temporal 对象无值表示,恒 TypeError。 +pub fn plain_month_day_value_of(vm: &mut H, _args: &[u8]) -> NativeResult { + NativeResult::Err(crate::error::create_type_error(vm, "Temporal.PlainMonthDay has no valueOf")) +} + /// PlainYearMonth 默认形串(`±YYYY-MM`),含 receiver 校验,不读 options。 fn plain_year_month_default_string(vm: &mut H, args: &[u8]) -> NativeResult { let ptr = native_try!(receiver_obj(vm, args)); @@ -7900,6 +7911,17 @@ pub fn plain_year_month_to_json(vm: &mut H, args: &[u8]) -> NativeRes plain_year_month_default_string(vm, args) } +/// `Temporal.PlainYearMonth.prototype.toLocaleString()`:locale/options 无引擎行为, +/// 恒输出默认形串。 +pub fn plain_year_month_to_locale_string(vm: &mut H, args: &[u8]) -> NativeResult { + plain_year_month_default_string(vm, args) +} + +/// `Temporal.PlainYearMonth.prototype.valueOf()`:Temporal 对象无值表示,恒 TypeError。 +pub fn plain_year_month_value_of(vm: &mut H, _args: &[u8]) -> NativeResult { + NativeResult::Err(crate::error::create_type_error(vm, "Temporal.PlainYearMonth has no valueOf")) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/oxide_vm/src/bindings/bind_temporal.rs b/crates/oxide_vm/src/bindings/bind_temporal.rs index 2636ec37..4eecd1b3 100644 --- a/crates/oxide_vm/src/bindings/bind_temporal.rs +++ b/crates/oxide_vm/src/bindings/bind_temporal.rs @@ -1005,6 +1005,16 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m oxide_builtins::temporal::plain_month_day_to_json:: as *const (), 0, ), + ( + "toLocaleString", + oxide_builtins::temporal::plain_month_day_to_locale_string:: as *const (), + 0, + ), + ( + "valueOf", + oxide_builtins::temporal::plain_month_day_value_of:: as *const (), + 0, + ), ], ); bind_well_known_data_property( @@ -1088,6 +1098,16 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m oxide_builtins::temporal::plain_year_month_to_json:: as *const (), 0, ), + ( + "toLocaleString", + oxide_builtins::temporal::plain_year_month_to_locale_string:: as *const (), + 0, + ), + ( + "valueOf", + oxide_builtins::temporal::plain_year_month_value_of:: as *const (), + 0, + ), ], ); bind_well_known_data_property( diff --git a/crates/oxide_vm/tests/builtins_temporal_tests.rs b/crates/oxide_vm/tests/builtins_temporal_tests.rs index 9651db1d..450346fc 100644 --- a/crates/oxide_vm/tests/builtins_temporal_tests.rs +++ b/crates/oxide_vm/tests/builtins_temporal_tests.rs @@ -2797,3 +2797,32 @@ fn plain_month_day_and_year_month_branding() { .unwrap(); assert_eq!(str_val(&vm, r), "TypeError|TypeError|TypeError|TypeError"); } + +#[test] +fn plain_month_day_and_year_month_to_locale_string_value_of_to_string_tag() { + let mut vm = Vm::new(); + // toLocaleString 忽略 locale/options,恒默认形串;valueOf 恒 TypeError + // (`<` 走 ToPrimitive→valueOf 同抛);toStringTag 经 Object.prototype.toString 读回。 + let r = eval( + &mut vm, + "(() => { + const pmd = new Temporal.PlainMonthDay(5, 2); + const pym = new Temporal.PlainYearMonth(2021, 2); + const kind = (fn) => { try { fn(); return 'no'; } catch (e) { return e.constructor.name; } }; + return [ + pmd.toLocaleString('en-US', {calendar: 'iso8601'}), + pym.toLocaleString(), + kind(() => pmd.valueOf()), + kind(() => pym.valueOf()), + kind(() => pmd < pym), + Object.prototype.toString.call(pmd), + Object.prototype.toString.call(pym), + ].join('|'); + })()", + ) + .unwrap(); + assert_eq!( + str_val(&vm, r), + "05-02|2021-02|TypeError|TypeError|TypeError|[object Temporal.PlainMonthDay]|[object Temporal.PlainYearMonth]" + ); +}