feat: implement Temporal Instant zoned conversion

This commit is contained in:
爱特每羊队
2026-08-11 20:54:25 +08:00
parent a9e194f2c6
commit 5ec0dc2b7d
12 changed files with 333 additions and 43 deletions
@@ -70,6 +70,10 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
"asyncIterator",
JsValue::from_js_object(session.builtin_world().sym_async_iterator.as_ptr() as *mut JsObject),
),
(
"toStringTag",
JsValue::from_js_object(session.builtin_world().sym_to_string_tag.as_ptr() as *mut JsObject),
),
] {
bind_well_known_symbol(core, ctor, name, val);
}
+63 -2
View File
@@ -1,8 +1,11 @@
use std::sync::Arc;
use crate::bindings::{apply_binding_table, bind_accessor_getter, bind_global_value, configure_native_constructor};
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_global_value, bind_well_known_data_property,
configure_native_constructor,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// 把 Temporal 命名空间及其子对象绑定到 global。
@@ -98,10 +101,67 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
0,
),
("toString", oxide_builtins::temporal::instant_to_string::<crate::vm::Vm> as *const (), 0),
(
"toZonedDateTimeISO",
oxide_builtins::temporal::instant_to_zoned_date_time_iso::<crate::vm::Vm> as *const (),
1,
),
("until", oxide_builtins::temporal::instant_until::<crate::vm::Vm> as *const (), 1),
("valueOf", oxide_builtins::temporal::instant_value_of::<crate::vm::Vm> as *const (), 0),
],
);
bind_well_known_data_property(
core,
instant_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.Instant").0),
),
PropAttributes::new(false, false, true),
);
// Temporal.ZonedDateTime:最小构造器与三个稳定内部槽 getter。
let zoned_date_time_ctor_ptr = world.zoned_date_time_constructor.as_ptr() as *mut JsObject;
let zoned_date_time_ctor = unsafe { &mut *zoned_date_time_ctor_ptr };
configure_native_constructor(
zoned_date_time_ctor,
oxide_builtins::temporal::zoned_date_time_constructor::<crate::vm::Vm> as *const (),
2,
);
let zoned_date_time_proto_ptr = world.zoned_date_time_proto.as_ptr() as *mut JsObject;
let zoned_date_time_proto = unsafe { &mut *zoned_date_time_proto_ptr };
bind_accessor_getter(
core,
session,
zoned_date_time_proto,
"epochNanoseconds",
oxide_builtins::temporal::zoned_date_time_epoch_nanoseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
zoned_date_time_proto,
"timeZoneId",
oxide_builtins::temporal::zoned_date_time_time_zone_id::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
zoned_date_time_proto,
"calendarId",
oxide_builtins::temporal::zoned_date_time_calendar_id::<crate::vm::Vm> as *const (),
);
bind_well_known_data_property(
core,
zoned_date_time_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.ZonedDateTime").0),
),
PropAttributes::new(false, false, true),
);
// Temporal.PlainDate:构造器 + from 静态方法 + year/month/day getter 与 toString。
let plain_date_ctor_ptr = world.plain_date_constructor.as_ptr() as *mut JsObject;
@@ -376,5 +436,6 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
bind_global_value(core, temporal, "PlainDate", JsValue::from_js_object(plain_date_ctor_ptr));
bind_global_value(core, temporal, "PlainTime", JsValue::from_js_object(plain_time_ctor_ptr));
bind_global_value(core, temporal, "Duration", JsValue::from_js_object(duration_ctor_ptr));
bind_global_value(core, temporal, "ZonedDateTime", JsValue::from_js_object(zoned_date_time_ctor_ptr));
bind_global_value(core, global, "Temporal", JsValue::from_js_object(temporal_ptr));
}
+12
View File
@@ -222,6 +222,18 @@ pub(crate) fn bind_well_known_method_alias(
proto.bump_generation();
}
/// 在对象上按 well-known symbol 键绑定数据属性。
pub(crate) fn bind_well_known_data_property(
core: &Arc<KernelCore>, target: &mut JsObject, well_known_id: u32, value: JsValue, attributes: PropAttributes,
) {
let key = oxide_types::private_key::make_well_known_symbol_key(well_known_id);
let new_shape = core.shape_forge().make_shape(target.shape_id(), key);
target.set_shape_id(new_shape);
let pos = target.push_prop(value);
target.set_data_meta(pos, attributes);
target.bump_generation();
}
pub(crate) fn bind_global_value(core: &Arc<KernelCore>, global: &mut JsObject, name: &str, value: JsValue) {
let si = core.perm_interner().intern(name).0;
let shape = core.shape_forge().make_shape(global.shape_id(), si);
+3 -1
View File
@@ -905,6 +905,8 @@ impl Vm {
Some(7)
} else if std::ptr::eq(ptr, world.sym_async_iterator.as_ptr()) {
Some(8)
} else if std::ptr::eq(ptr, world.sym_to_string_tag.as_ptr()) {
Some(9)
} else {
None
};
@@ -985,7 +987,7 @@ impl Vm {
// 数组属性存储索引 = array_prop_count + shape 槽位(与元素区分)。
let idx = obj.array_prop_count as usize + pos as usize;
let val = obj.get_prop_at(idx);
if !val.is_undefined() {
if !val.is_undefined() || obj.prop_vec_len() > idx {
Some(idx as u32)
} else {
None