mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 18:51:13 +08:00
feat: 新增 Intl 特性域骨架实现
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
use crate::bindings::{
|
||||
apply_binding_table, bind_global_value, bind_well_known_data_property, configure_native_constructor, BindEnv,
|
||||
};
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
/// 一组 Intl 构造器/原型对:(构造器槽,原型槽,构造器 native 函数,
|
||||
/// 构造器 length 槽,命名空间槽名,原型标签)。
|
||||
type IntlCtorPair<'a> = (
|
||||
&'a oxide_types::mem::P<JsObject>,
|
||||
&'a oxide_types::mem::P<JsObject>,
|
||||
*const (),
|
||||
u32,
|
||||
&'a str,
|
||||
&'a str,
|
||||
);
|
||||
|
||||
/// 把 Intl 命名空间对象与十组构造器/原型对绑定到 global。
|
||||
///
|
||||
/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号,
|
||||
/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
|
||||
///
|
||||
/// 构造器/原型对与 `prototype`/`constructor` 互指、命名空间与构造器的
|
||||
/// `[[Prototype]]` 链由内核接线(`wire_builtin_world_links`)预置,本函数
|
||||
/// 只安装 native 函数面、`length` 与 `@@toStringTag`。
|
||||
pub fn bind_intl(env: BindEnv<'_>, global: &mut JsObject) {
|
||||
let world = env.world();
|
||||
let intl_ptr = world.intl_object.as_ptr() as *mut JsObject;
|
||||
let intl = unsafe { &mut *intl_ptr };
|
||||
|
||||
// Intl.getCanonicalLocales 与 Intl.supportedValuesOf:命名空间对象上的
|
||||
// 静态方法(各 length 1,非构造器)。
|
||||
apply_binding_table(
|
||||
env,
|
||||
intl,
|
||||
&[
|
||||
(
|
||||
"getCanonicalLocales",
|
||||
oxide_builtins::intl::get_canonical_locales::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
(
|
||||
"supportedValuesOf",
|
||||
oxide_builtins::intl::supported_values_of::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
],
|
||||
);
|
||||
bind_well_known_data_property(
|
||||
env.core,
|
||||
intl,
|
||||
9,
|
||||
JsValue::perm_string(env.string_forge().string_ptr(env.string_forge().intern("Intl").0)),
|
||||
PropAttributes::new(false, false, true),
|
||||
env.realm_id,
|
||||
);
|
||||
|
||||
// 十组构造器/原型对:构造器(length 0)+ supportedLocalesOf 静态方法 +
|
||||
// 命名空间槽(Intl.NumberFormat 等)+ 原型 @@toStringTag。
|
||||
let pairs: [IntlCtorPair; 10] = [
|
||||
(
|
||||
&world.number_format_constructor,
|
||||
&world.number_format_proto,
|
||||
oxide_builtins::intl::number_format_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"NumberFormat",
|
||||
"Intl.NumberFormat",
|
||||
),
|
||||
(
|
||||
&world.date_time_format_constructor,
|
||||
&world.date_time_format_proto,
|
||||
oxide_builtins::intl::date_time_format_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"DateTimeFormat",
|
||||
"Intl.DateTimeFormat",
|
||||
),
|
||||
(
|
||||
&world.collator_constructor,
|
||||
&world.collator_proto,
|
||||
oxide_builtins::intl::collator_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"Collator",
|
||||
"Intl.Collator",
|
||||
),
|
||||
(
|
||||
&world.plural_rules_constructor,
|
||||
&world.plural_rules_proto,
|
||||
oxide_builtins::intl::plural_rules_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"PluralRules",
|
||||
"Intl.PluralRules",
|
||||
),
|
||||
(
|
||||
&world.list_format_constructor,
|
||||
&world.list_format_proto,
|
||||
oxide_builtins::intl::list_format_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"ListFormat",
|
||||
"Intl.ListFormat",
|
||||
),
|
||||
(
|
||||
&world.relative_time_format_constructor,
|
||||
&world.relative_time_format_proto,
|
||||
oxide_builtins::intl::relative_time_format_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"RelativeTimeFormat",
|
||||
"Intl.RelativeTimeFormat",
|
||||
),
|
||||
(
|
||||
&world.display_names_constructor,
|
||||
&world.display_names_proto,
|
||||
oxide_builtins::intl::display_names_constructor::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
"DisplayNames",
|
||||
"Intl.DisplayNames",
|
||||
),
|
||||
(
|
||||
&world.segmenter_constructor,
|
||||
&world.segmenter_proto,
|
||||
oxide_builtins::intl::segmenter_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"Segmenter",
|
||||
"Intl.Segmenter",
|
||||
),
|
||||
(
|
||||
&world.locale_constructor,
|
||||
&world.locale_proto,
|
||||
oxide_builtins::intl::locale_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
"Locale",
|
||||
"Intl.Locale",
|
||||
),
|
||||
(
|
||||
&world.duration_format_constructor,
|
||||
&world.duration_format_proto,
|
||||
oxide_builtins::intl::duration_format_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
"DurationFormat",
|
||||
"Intl.DurationFormat",
|
||||
),
|
||||
];
|
||||
for (ctor_p, proto_p, ctor_fn, length, name, tag) in pairs {
|
||||
let ctor = unsafe { &mut *(ctor_p.as_ptr() as *mut JsObject) };
|
||||
let proto = unsafe { &mut *(proto_p.as_ptr() as *mut JsObject) };
|
||||
bind_intl_ctor_pair(env, ctor, proto, ctor_fn, length, tag);
|
||||
// 命名空间对象上的构造器槽(如 Intl.NumberFormat):既有槽原位更新。
|
||||
bind_global_value(env.core, intl, name, JsValue::from_js_object(ctor_p.as_ptr() as *mut JsObject));
|
||||
}
|
||||
|
||||
// 命名空间对象挂到 global(既有槽原位更新,幂等)。
|
||||
bind_global_value(env.core, global, "Intl", JsValue::from_js_object(intl_ptr));
|
||||
}
|
||||
|
||||
/// 安装一组 Intl 构造器/原型对:构造器 native 函数与 `length`、
|
||||
/// `supportedLocalesOf` 静态方法、原型 `@@toStringTag`。
|
||||
fn bind_intl_ctor_pair(
|
||||
env: BindEnv<'_>,
|
||||
ctor: &mut JsObject,
|
||||
proto: &mut JsObject,
|
||||
ctor_fn: *const (),
|
||||
length: u32,
|
||||
tag: &str,
|
||||
) {
|
||||
// 构造器:length 槽的 native 函数;`prototype`/`name` 槽由内核接线
|
||||
// 预置(wire_ctor_proto / make_pair),此处不重复建槽。
|
||||
configure_native_constructor(ctor, ctor_fn, 0);
|
||||
let length_si = env.string_forge().intern("length").0;
|
||||
let length_shape = env.shape_forge().make_shape(ctor.shape_id(), length_si);
|
||||
ctor.set_shape_id(length_shape);
|
||||
ctor.ensure_hash_props().push(JsValue::int(length as i32));
|
||||
let length_pos = ctor.hash_props_vec().map_or(0, |props| props.len() as u32).saturating_sub(1);
|
||||
ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
|
||||
|
||||
// supportedLocalesOf:普通静态方法(非构造器、无 prototype),length 1。
|
||||
apply_binding_table(
|
||||
env,
|
||||
ctor,
|
||||
&[(
|
||||
"supportedLocalesOf",
|
||||
oxide_builtins::intl::supported_locales_of::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
)],
|
||||
);
|
||||
|
||||
// 原型 @@toStringTag:{ writable:false, enumerable:false, configurable:true }。
|
||||
bind_well_known_data_property(
|
||||
env.core,
|
||||
proto,
|
||||
9,
|
||||
JsValue::perm_string(env.string_forge().string_ptr(env.string_forge().intern(tag).0)),
|
||||
PropAttributes::new(false, false, true),
|
||||
env.realm_id,
|
||||
);
|
||||
}
|
||||
@@ -33,6 +33,8 @@ pub mod bind_event;
|
||||
pub mod bind_function;
|
||||
/// global 对象上的普通全局函数(parseInt、isNaN 等)绑定。
|
||||
pub mod bind_global;
|
||||
/// Intl 命名空间对象与十组构造器/原型的 native 绑定(骨架阶段)。
|
||||
pub mod bind_intl;
|
||||
/// Iterator 相关全局辅助对象(%IteratorPrototype% 等)绑定。
|
||||
pub mod bind_iterator;
|
||||
/// JSON 单例对象及其 native 方法绑定。
|
||||
@@ -1118,6 +1120,7 @@ pub fn bind_global_builtin_slots(
|
||||
("JSON", JsValue::from_js_object(world.json_object.as_ptr() as *mut JsObject)),
|
||||
("Temporal", JsValue::from_js_object(world.temporal_object.as_ptr() as *mut JsObject)),
|
||||
("Atomics", JsValue::from_js_object(world.atomics_object.as_ptr() as *mut JsObject)),
|
||||
("Intl", JsValue::from_js_object(world.intl_object.as_ptr() as *mut JsObject)),
|
||||
] {
|
||||
bind_existing_global(core, global, name, value);
|
||||
}
|
||||
@@ -1343,6 +1346,9 @@ pub fn rebind_dirty_builtins(
|
||||
if dirty.map_or(true, |d| d.temporal) {
|
||||
bind_temporal::bind_temporal(env, global);
|
||||
}
|
||||
if dirty.map_or(true, |d| d.intl) {
|
||||
bind_intl::bind_intl(env, global);
|
||||
}
|
||||
// 独占函数(bind_stubs / bind_weak_map)需要 session 的可变借用,与 env
|
||||
// 的共享借用冲突;env 的最后一次使用在上面的 temporal 分支,独占调用
|
||||
// 之后重建 env 供后续分支使用。
|
||||
|
||||
@@ -148,6 +148,26 @@ impl oxide_runtime_api::VmHost for Vm {
|
||||
ProtoKind::MessageEventProto => &world.message_event_proto,
|
||||
ProtoKind::ErrorEventProto => &world.error_event_proto,
|
||||
ProtoKind::CustomEventProto => &world.custom_event_proto,
|
||||
ProtoKind::NumberFormatConstructor => &world.number_format_constructor,
|
||||
ProtoKind::NumberFormatProto => &world.number_format_proto,
|
||||
ProtoKind::DateTimeFormatConstructor => &world.date_time_format_constructor,
|
||||
ProtoKind::DateTimeFormatProto => &world.date_time_format_proto,
|
||||
ProtoKind::CollatorConstructor => &world.collator_constructor,
|
||||
ProtoKind::CollatorProto => &world.collator_proto,
|
||||
ProtoKind::PluralRulesConstructor => &world.plural_rules_constructor,
|
||||
ProtoKind::PluralRulesProto => &world.plural_rules_proto,
|
||||
ProtoKind::ListFormatConstructor => &world.list_format_constructor,
|
||||
ProtoKind::ListFormatProto => &world.list_format_proto,
|
||||
ProtoKind::RelativeTimeFormatConstructor => &world.relative_time_format_constructor,
|
||||
ProtoKind::RelativeTimeFormatProto => &world.relative_time_format_proto,
|
||||
ProtoKind::DisplayNamesConstructor => &world.display_names_constructor,
|
||||
ProtoKind::DisplayNamesProto => &world.display_names_proto,
|
||||
ProtoKind::SegmenterConstructor => &world.segmenter_constructor,
|
||||
ProtoKind::SegmenterProto => &world.segmenter_proto,
|
||||
ProtoKind::LocaleConstructor => &world.locale_constructor,
|
||||
ProtoKind::LocaleProto => &world.locale_proto,
|
||||
ProtoKind::DurationFormatConstructor => &world.duration_format_constructor,
|
||||
ProtoKind::DurationFormatProto => &world.duration_format_proto,
|
||||
};
|
||||
P::as_ptr(p) as *mut JsObject
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user