refactor: 绑定层环境四件套收敛为 BindEnv 单参

This commit is contained in:
2026-10-12 17:54:00 +00:00
parent df599313d4
commit 29ea2fd990
21 changed files with 222 additions and 319 deletions
+4 -7
View File
@@ -1713,11 +1713,10 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
let mut ag_proto = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, async_iterator_proto_val));
// 站点标签:与 Generator 原型的同名方法槽(next/return/throw)区分复用键。
let ag_label = sf.intern("AsyncGeneratorPrototype").0;
oxide_kernel::bind_methods_static!(
let kenv = oxide_kernel::builtin::BindEnv { world, shape_forge: sh, string_forge: sf };
oxide_kernel::bind_methods!(
kenv,
&mut ag_proto,
sf,
sh,
world,
ag_label,
("next", async_generator_next as *const (), 1),
("return", async_generator_return as *const (), 1),
@@ -1735,14 +1734,12 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
// @@asyncIterator:返回自身(异步生成器是异步可迭代对象,供 for-await-of 消费)。
let aiter_key = oxide_types::private_key::encode_symbol_key(vm.realm_id(), 8);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method_key_labeled_static(
kenv,
&mut ag_proto,
sh,
sf,
aiter_key,
"@@asyncIterator",
unsafe { oxide_types::object::NativeFnPtr::from_raw(async_generator_symbol_async_iterator as *const ()) },
0,
world,
ag_label,
);
Vm::swap_intrinsic_proto(&mut vm.realm.async_generator_proto.borrow_mut(), *ag_proto);
+2 -3
View File
@@ -2,7 +2,7 @@ use oxide_kernel::builtin::ArrayMethods;
use oxide_types::object::{JsObject, PropAttributes};
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, BindEnv};
use crate::bindings::{apply_binding_table, kernel_env, BindEnv};
/// 把 Array 构造器与原型方法绑定到 global。
///
@@ -51,8 +51,7 @@ pub fn bind_array(env: BindEnv<'_>, global: &mut JsObject) {
with_method: oxide_builtins::array::array_with::<crate::vm::Vm> as *const (),
};
env.world()
.bind_array_methods(&_array_methods, env.string_forge(), env.shape_forge(), env.realm_id);
oxide_kernel::builtin::BuiltinWorld::bind_array_methods(kernel_env(env), &_array_methods, env.realm_id);
let array_proto_ptr = env.world().array_proto.as_ptr() as *mut JsObject;
let array_proto = unsafe { &mut *array_proto_ptr };
+2 -8
View File
@@ -2,7 +2,7 @@ use oxide_kernel::bind_methods;
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
use crate::bindings::{bind_global_value, BindEnv};
use crate::bindings::{bind_global_value, kernel_env, BindEnv};
/// 把 Atomics 全局纯对象及其 10 个原子方法绑定到 global。
///
@@ -12,15 +12,9 @@ pub fn bind_atomics(env: BindEnv<'_>, global: &mut JsObject) {
let atomics_ptr = env.world().atomics_object.as_ptr() as *mut JsObject;
let atomics = unsafe { &mut *atomics_ptr };
let bw = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
bind_methods!(
bw,
kernel_env(env),
atomics,
sf,
sh,
("load", oxide_builtins::atomics::atomics_load::<crate::vm::Vm>, 2),
("store", oxide_builtins::atomics::atomics_store::<crate::vm::Vm>, 3),
("exchange", oxide_builtins::atomics::atomics_exchange::<crate::vm::Vm>, 3),
+2 -8
View File
@@ -1,4 +1,4 @@
use crate::bindings::{bind_global_value, BindEnv};
use crate::bindings::{bind_global_value, kernel_env, BindEnv};
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
@@ -7,15 +7,9 @@ pub fn bind_console(env: BindEnv<'_>, global: &mut JsObject) {
let console_ptr = env.world().console_object.as_ptr() as *mut JsObject;
let console = unsafe { &mut *console_ptr };
let bw = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
oxide_kernel::bind_methods!(
bw,
kernel_env(env),
console,
sf,
sh,
("log", oxide_builtins::console::log::<crate::vm::Vm>, 1),
("warn", oxide_builtins::console::warn::<crate::vm::Vm>, 1),
("error", oxide_builtins::console::error::<crate::vm::Vm>, 1),
+2 -3
View File
@@ -3,7 +3,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use super::BindEnv;
use super::{BindEnv, kernel_env};
fn bind_error_subtype_constructor(
env: BindEnv<'_>, global: &mut JsObject, name: &str, proto_ptr: *mut JsObject, ctor_fn: *const (), arg_count: u8,
@@ -107,8 +107,7 @@ pub fn bind_error(env: BindEnv<'_>, global: &mut JsObject) {
is_error: oxide_builtins::error::error_is_error::<crate::vm::Vm> as *const (),
to_json: oxide_builtins::error::error_to_json::<crate::vm::Vm> as *const (),
};
env.world()
.bind_error_methods(&error_methods, env.string_forge(), env.shape_forge());
oxide_kernel::builtin::BuiltinWorld::bind_error_methods(kernel_env(env), &error_methods);
// stack 为访问器成对安装(getter 现算栈串 / setter 走
// SetterThatIgnoresPrototypeProperties),经 getset 绑定器登记复用键,
@@ -3,10 +3,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use super::apply_binding_table;
use super::bind_global_value;
use super::configure_native_constructor;
use super::BindEnv;
use super::{apply_binding_table, bind_global_value, configure_native_constructor, kernel_env, BindEnv};
/// 把 Function 构造器与原型方法绑定到 global。
///
@@ -20,8 +17,7 @@ pub fn bind_function(env: BindEnv<'_>, global: &mut JsObject) {
to_string: oxide_builtins::function::function_to_string::<crate::vm::Vm> as *const (),
has_instance: oxide_builtins::function::function_symbol_has_instance::<crate::vm::Vm> as *const (),
};
env.world()
.bind_function_methods(&function_methods, env.string_forge(), env.shape_forge(), env.realm_id);
oxide_kernel::builtin::BuiltinWorld::bind_function_methods(kernel_env(env), &function_methods, env.realm_id);
let function_ctor = env.world().function_constructor.as_ptr() as *mut JsObject;
configure_native_constructor(
+2 -8
View File
@@ -2,22 +2,16 @@ use oxide_kernel::bind_methods;
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
use crate::bindings::BindEnv;
use crate::bindings::{kernel_env, BindEnv};
/// 把 Math 单例对象及其方法(abs/floor/max/random 等)绑定到 global。
pub fn bind_math(env: BindEnv<'_>, global: &mut JsObject) {
let math_ptr = env.world().math_object.as_ptr() as *mut JsObject;
let math = unsafe { &mut *math_ptr };
let bw = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
bind_methods!(
bw,
kernel_env(env),
math,
sf,
sh,
("abs", oxide_builtins::math::math_abs::<crate::vm::Vm>, 1),
("acos", oxide_builtins::math::math_acos::<crate::vm::Vm>, 1),
("asin", oxide_builtins::math::math_asin::<crate::vm::Vm>, 1),
+2 -2
View File
@@ -2,7 +2,7 @@ use oxide_kernel::builtin::ObjectMethods;
use oxide_types::object::{JsObject, PropAttributes};
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, BindEnv};
use crate::bindings::{apply_binding_table, kernel_env, BindEnv};
/// 把 Object 构造器与原型方法绑定到 global。
pub fn bind_object(env: BindEnv<'_>, global: &mut JsObject) {
@@ -36,7 +36,7 @@ pub fn bind_object(env: BindEnv<'_>, global: &mut JsObject) {
as *const (),
group_by: oxide_builtins::object::object_group_by::<crate::vm::Vm> as *const (),
};
env.world().bind_object_methods(&methods, env.string_forge(), env.shape_forge());
oxide_kernel::builtin::BuiltinWorld::bind_object_methods(kernel_env(env), &methods);
let object_proto_ptr = env.world().object_proto.as_ptr() as *mut JsObject;
let object_proto = unsafe { &mut *object_proto_ptr };
+2 -3
View File
@@ -1,4 +1,4 @@
use crate::bindings::{apply_binding_table, configure_native_constructor, BindEnv};
use crate::bindings::{apply_binding_table, configure_native_constructor, kernel_env, BindEnv};
use oxide_kernel::builtin::StringMethods;
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -60,8 +60,7 @@ pub fn bind_string(env: BindEnv<'_>, global: &mut JsObject) {
sub: oxide_builtins::string::string_sub::<crate::vm::Vm> as *const (),
sup: oxide_builtins::string::string_sup::<crate::vm::Vm> as *const (),
};
env.world()
.bind_string_methods(&string_methods, env.string_forge(), env.shape_forge());
oxide_kernel::builtin::BuiltinWorld::bind_string_methods(kernel_env(env), &string_methods);
let ctor_ptr = env.world().string_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
@@ -1,10 +1,12 @@
use oxide_kernel::builtin::BuiltinWorld;
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
use crate::bind_constructor;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_accessor_getter_key, bind_global_value,
bind_well_known_method_alias, configure_native_constructor, BindEnv,
bind_well_known_method_alias, configure_native_constructor, kernel_env, BindEnv,
};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// 把 `%TypedArray%` 抽象构造器的 native 实现配置为恒抛 TypeError(不可 new/不可调用),
/// 设置 `length` 属性为 0,并挂载静态 `of`/`from`(具体构造器经原型链继承)。
@@ -26,16 +28,13 @@ fn bind_typed_array_abstract_ctor(env: BindEnv<'_>) {
let pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
let sf = env.string_forge();
let sh = env.shape_forge();
let world = env.world();
let ctor_ptr = world.typed_array_constructor.as_ptr() as *mut JsObject;
let kenv = kernel_env(env);
let ctor_ptr = env.world().typed_array_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
// SAFETY: of/from 是转成 *const () 的 NativeFn 函数项指针。
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
ctor,
sh,
sf,
"of",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -44,10 +43,9 @@ fn bind_typed_array_abstract_ctor(env: BindEnv<'_>) {
},
0,
);
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
ctor,
sh,
sf,
"from",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -270,16 +268,13 @@ pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
// base64/hex 四原型法挂 Uint8Array 专属原型(Uint8ClampedArray 经链继承、
// kind 校验拒绝);两静态法挂 Uint8Array 构造器。
let world = env.world();
let sh = env.shape_forge();
let sf = env.string_forge();
let kenv = kernel_env(env);
let u8_proto_ptr = env.world().uint8array_proto.as_ptr() as *mut JsObject;
let u8_proto = unsafe { &mut *u8_proto_ptr };
// SAFETY: 指针来自 session 存活期内的 BuiltinWorld 对象。
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
u8_proto,
sh,
sf,
"toBase64",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -288,10 +283,9 @@ pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
},
0,
);
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
u8_proto,
sh,
sf,
"toHex",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -300,10 +294,9 @@ pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
},
0,
);
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
u8_proto,
sh,
sf,
"setFromBase64",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -312,10 +305,9 @@ pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
},
1,
);
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
u8_proto,
sh,
sf,
"setFromHex",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -326,10 +318,9 @@ pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
);
let u8_ctor_ptr = env.world().uint8array_constructor.as_ptr() as *mut JsObject;
let u8_ctor = unsafe { &mut *u8_ctor_ptr };
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
u8_ctor,
sh,
sf,
"fromBase64",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
@@ -338,10 +329,9 @@ pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
},
1,
);
let _ = world.bind_method(
let _ = BuiltinWorld::bind_method(
kenv,
u8_ctor,
sh,
sf,
"fromHex",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
+1 -3
View File
@@ -29,13 +29,11 @@ fn bind_labeled_method(
// SAFETY: func 是转成 *const () 的 NativeFn 函数项指针。
let fn_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(func) };
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method_labeled_static(
oxide_kernel::builtin::BindEnv { world, shape_forge, string_forge },
proto,
shape_forge,
string_forge,
name,
fn_ptr,
nargs,
world,
label,
);
}
+21 -19
View File
@@ -84,6 +84,10 @@ use oxide_types::value::JsValue;
/// 消除各绑定函数签名前缀与函数体首行的三行解包。
///
/// `Copy`:值语义轻量(两个引用加一个 u32),可自由复制传递。
///
/// kernel 绑定层有同名字段集不同的 `BindEnv`(world/shape_forge/string_forge):
/// 本结构的 `world()` / `shape_forge()` / `string_forge()` 访问器是 kernel
/// 结构的构造来源(见 [`kernel_env`])。
#[derive(Copy, Clone)]
pub struct BindEnv<'a> {
pub core: &'a Arc<KernelCore>,
@@ -110,6 +114,17 @@ impl<'a> BindEnv<'a> {
}
}
/// 把 vm 绑定环境转换为 kernel 绑定环境:`world()` / `shape_forge()` /
/// `string_forge()` 三个访问器是 kernel `BindEnv` 的构造来源(此处直接
/// 从 `core` / `session` 字段借出,使返回引用可活过本函数)。
pub(crate) fn kernel_env<'a>(env: BindEnv<'a>) -> oxide_kernel::builtin::BindEnv<'a> {
oxide_kernel::builtin::BindEnv {
world: env.session.builtin_world(),
shape_forge: env.core.shape_forge().as_ref(),
string_forge: env.core.perm_interner().as_ref(),
}
}
#[macro_export]
macro_rules! bind_constructor {
($env:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal) => {{
@@ -177,21 +192,19 @@ fn configure_existing_ctor(ctor: &P<JsObject>, native_fn: *const (), arg_count:
/// 把 `(name, native_fn_ptr, nargs)` 绑定表逐条安装为目标对象的命名方法。
///
/// 每条经 `world.bind_method` 在 `target` 上建/复用方法 wrapper 并写命名属性;shape 与
/// 字符串 interner 由 `core` 借出,循环内共享。
/// 每条经 `BuiltinWorld::bind_method` 在 `target` 上建/复用方法 wrapper 并写命名属性;
/// kernel 绑定环境由 `env` 借出,循环内共享。
///
/// # 注意事项
/// - 表中所有函数项指针须为合法的 `NativeFn`(转成 `*const ()`),此处经
/// `NativeFnPtr::from_raw` 转换。
/// - `bind_method` 的返回值被丢弃:单条绑定失败不中断后续条目。
pub(crate) fn apply_binding_table(env: BindEnv<'_>, target: &mut JsObject, bindings: &[(&'static str, *const (), u8)]) {
let world = env.world();
let shape_forge = env.shape_forge();
let string_forge = env.string_forge();
let kenv = kernel_env(env);
for (name, func, nargs) in bindings {
// SAFETY: 绑定表中所有条目都是转成 *const () 的 NativeFn 函数项指针。
let fn_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(*func) };
let _ = world.bind_method(target, shape_forge, string_forge, name, fn_ptr, *nargs);
let _ = BuiltinWorld::bind_method(kenv, target, name, fn_ptr, *nargs);
}
}
@@ -395,22 +408,11 @@ pub(crate) fn bind_method_alias(core: &Arc<KernelCore>, proto: &mut JsObject, so
pub(crate) fn bind_well_known_method(
env: BindEnv<'_>, target: &mut JsObject, well_known_id: u32, method_name: &str, func: *const (), nargs: u8,
) {
let world = env.world();
let shape_forge = env.shape_forge();
let string_forge = env.string_forge();
let kenv = kernel_env(env);
// SAFETY: func 是转成 *const () 的 NativeFn 函数项指针。
let fn_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(func) };
let key = oxide_types::private_key::encode_symbol_key(env.realm_id, well_known_id);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method_key_static(
target,
shape_forge,
string_forge,
key,
method_name,
fn_ptr,
nargs,
world,
);
let _ = BuiltinWorld::bind_method_key_static(kenv, target, key, method_name, fn_ptr, nargs);
}
/// 把原型上 `source` 属性已绑定的函数值复制到 well-known symbol 键名下(共享同一函数对象)。
+4 -7
View File
@@ -809,11 +809,10 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
let mut gen_proto = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, iterator_proto_val));
// 站点标签:与 AsyncGenerator 原型的同名方法槽(next/return/throw)区分复用键。
let gen_label = sf.intern("GeneratorPrototype").0;
oxide_kernel::bind_methods_static!(
let kenv = oxide_kernel::builtin::BindEnv { world, shape_forge: sh, string_forge: sf };
oxide_kernel::bind_methods!(
kenv,
&mut gen_proto,
sf,
sh,
world,
gen_label,
("next", generator_next as *const (), 1),
("return", generator_return as *const (), 1),
@@ -831,14 +830,12 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
// @@iterator:返回自身(生成器是可迭代对象)。
let iter_key = oxide_types::private_key::encode_symbol_key(vm.realm_id(), 0);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method_key_labeled_static(
kenv,
&mut gen_proto,
sh,
sf,
iter_key,
"@@iterator",
unsafe { oxide_types::object::NativeFnPtr::from_raw(generator_symbol_iterator as *const ()) },
0,
world,
gen_label,
);
Vm::swap_intrinsic_proto(&mut vm.realm.generator_proto.borrow_mut(), *gen_proto);
+5 -8
View File
@@ -272,11 +272,10 @@ impl Vm {
proto.set_shape_id(ctor_shape);
proto.push_prop(JsValue::undefined());
proto.set_data_meta(0u32, PropAttributes::new(true, false, true));
oxide_kernel::bind_methods_static!(
let kenv = oxide_kernel::builtin::BindEnv { world, shape_forge: sh, string_forge: sf };
oxide_kernel::bind_methods!(
kenv,
&mut proto,
sf,
sh,
world,
("then", promise_then as *const (), 2),
("catch", promise_catch as *const (), 1),
("finally", promise_finally as *const (), 1),
@@ -313,11 +312,9 @@ impl Vm {
ctor.set_shape_id(ctor_shape3);
ctor.push_prop(JsValue::undefined());
ctor.set_data_meta(2u32, PropAttributes::new(false, false, false));
oxide_kernel::bind_methods_static!(
oxide_kernel::bind_methods!(
kenv,
&mut ctor,
sf,
sh,
world,
("resolve", promise_static_resolve as *const (), 1),
("reject", promise_static_reject as *const (), 1),
("all", promise_static_all as *const (), 1),