From 29ea2fd990972a04531733f94c7e32b7686fa3d2 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Mon, 12 Oct 2026 17:54:00 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=BB=91=E5=AE=9A=E5=B1=82?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=9B=9B=E4=BB=B6=E5=A5=97=E6=94=B6=E6=95=9B?= =?UTF-8?q?=E4=B8=BA=20BindEnv=20=E5=8D=95=E5=8F=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 42 ++-- Cargo.toml | 2 +- crates/oxide_kernel/src/builtin/bind.rs | 204 +++++++----------- crates/oxide_kernel/src/builtin/mod.rs | 48 +---- crates/oxide_kernel/src/builtin/rebuild.rs | 12 +- crates/oxide_kernel/src/kernel/session.rs | 10 +- .../oxide_kernel/tests/builtin_world_tests.rs | 29 ++- crates/oxide_vm/src/async_generator.rs | 11 +- crates/oxide_vm/src/bindings/bind_array.rs | 5 +- crates/oxide_vm/src/bindings/bind_atomics.rs | 10 +- crates/oxide_vm/src/bindings/bind_console.rs | 10 +- crates/oxide_vm/src/bindings/bind_error.rs | 5 +- crates/oxide_vm/src/bindings/bind_function.rs | 8 +- crates/oxide_vm/src/bindings/bind_math.rs | 10 +- crates/oxide_vm/src/bindings/bind_object.rs | 4 +- crates/oxide_vm/src/bindings/bind_string.rs | 5 +- .../oxide_vm/src/bindings/bind_typed_array.rs | 58 +++-- crates/oxide_vm/src/bindings/bind_weak.rs | 4 +- crates/oxide_vm/src/bindings/mod.rs | 40 ++-- crates/oxide_vm/src/generator.rs | 11 +- crates/oxide_vm/src/promise/constructor.rs | 13 +- 21 files changed, 222 insertions(+), 319 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c3ce87a..1d41b1bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.17.3" +version = "0.17.4" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.17.3" +version = "0.17.4" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.17.3" +version = "0.17.4" dependencies = [ "ansi_term", "bumpalo", @@ -1228,7 +1228,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.17.3" +version = "0.17.4" dependencies = [ "lru", "oxide_bytecode", @@ -1237,7 +1237,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1258,7 +1258,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.17.3" +version = "0.17.4" dependencies = [ "num-bigint", "oxc_allocator", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "oxide_fold" -version = "0.17.3" +version = "0.17.4" dependencies = [ "num-bigint", "oxide_bytecode", @@ -1312,7 +1312,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.17.3" +version = "0.17.4" dependencies = [ "bumpalo", "dashmap", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1347,7 +1347,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.17.3" +version = "0.17.4" dependencies = [ "tracing", "tracing-appender", @@ -1356,11 +1356,11 @@ dependencies = [ [[package]] name = "oxide_net" -version = "0.17.3" +version = "0.17.4" [[package]] name = "oxide_parser" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1375,7 +1375,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.17.3" +version = "0.17.4" dependencies = [ "num-bigint", "num-traits", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.17.3" +version = "0.17.4" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.17.3" +version = "0.17.4" dependencies = [ "bumpalo", "dashmap", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.17.3" +version = "0.17.4" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index c8a1a22c..70e04956 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ members = [ ] [workspace.package] -version = "0.17.3" +version = "0.17.4" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_kernel/src/builtin/bind.rs b/crates/oxide_kernel/src/builtin/bind.rs index c8f06287..0fcee402 100644 --- a/crates/oxide_kernel/src/builtin/bind.rs +++ b/crates/oxide_kernel/src/builtin/bind.rs @@ -8,20 +8,34 @@ use oxide_types::value::JsValue; use super::{ArrayMethods, BuiltinWorld, ErrorMethods, FnWrapperKey, FunctionMethods, ObjectMethods, StringMethods}; use crate::bind_methods; -use crate::bind_methods_static; use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID}; use crate::string_forge::PermInterner; +/// 绑定环境:把绑定层三环境要素(builtin world、shape forge、string forge) +/// 打包为单一首参,整体传入 `bind_method*` 家族与五家族函数。 +/// +/// `Copy`:值语义轻量(三个引用),可自由复制传递。 +/// +/// vm 绑定层有同名字段集不同的 `BindEnv`(core/session/realm_id):其 +/// `world()` / `shape_forge()` / `string_forge()` 访问器是本结构的构造来源。 +#[derive(Copy, Clone)] +pub struct BindEnv<'a> { + pub world: &'a BuiltinWorld, + pub shape_forge: &'a ShapeForge, + pub string_forge: &'a PermInterner, +} + impl BuiltinWorld { /// 把 Object 家族方法安装到 Object 构造器与原型上(含 `hasOwnProperty` 等非枚举元数据修正)。 - pub fn bind_object_methods(&self, methods: &ObjectMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) { - let ctor_ptr = P::as_ptr(&self.object_constructor) as *mut JsObject; + pub fn bind_object_methods(env: BindEnv<'_>, methods: &ObjectMethods) { + let world = env.world; + let string_forge = env.string_forge; + let shape_forge = env.shape_forge; + let ctor_ptr = P::as_ptr(&world.object_constructor) as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; bind_methods!( - self, + env, ctor, - string_forge, - shape_forge, ("keys", methods.keys, 1), ("create", methods.create, 2), ("assign", methods.assign, 2), @@ -47,13 +61,11 @@ impl BuiltinWorld { ("groupBy", methods.group_by, 2), ); - let proto_ptr = P::as_ptr(&self.object_proto) as *mut JsObject; + let proto_ptr = P::as_ptr(&world.object_proto) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; bind_methods!( - self, + env, proto, - string_forge, - shape_forge, ("hasOwnProperty", methods.has_own_property, 1), ("propertyIsEnumerable", methods.property_is_enumerable, 1), ); @@ -69,28 +81,24 @@ impl BuiltinWorld { /// /// `realm_id` 是安装目标所属 realm 的编号:`@@iterator` 符号键按 /// (realm 编号, 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 - pub fn bind_array_methods( - &self, methods: &ArrayMethods, string_forge: &PermInterner, shape_forge: &ShapeForge, realm_id: u32, - ) { - let ctor_ptr = P::as_ptr(&self.array_constructor) as *mut JsObject; + pub fn bind_array_methods(env: BindEnv<'_>, methods: &ArrayMethods, realm_id: u32) { + let world = env.world; + let shape_forge = env.shape_forge; + let ctor_ptr = P::as_ptr(&world.array_constructor) as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; bind_methods!( - self, + env, ctor, - string_forge, - shape_forge, ("isArray", methods.is_array, 1), ("from", methods.from, 1), ("of", methods.of, 0), ); - let proto_ptr = P::as_ptr(&self.array_proto) as *mut JsObject; + let proto_ptr = P::as_ptr(&world.array_proto) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; bind_methods!( - self, + env, proto, - string_forge, - shape_forge, ("push", methods.push, 1), ("pop", methods.pop, 0), ("slice", methods.slice, 2), @@ -133,28 +141,20 @@ impl BuiltinWorld { let raw = methods.values; // SAFETY: methods.values 是 VM 绑定层传入的 NativeFn 函数项。 let func_ptr = unsafe { NativeFnPtr::from_raw(raw) }; - let _ = Self::bind_method_key_static( - proto, - shape_forge, - string_forge, - iterator_key, - "@@iterator", - func_ptr, - 0, - self, - ); + let _ = Self::bind_method_key_static(env, proto, iterator_key, "@@iterator", func_ptr, 0); debug_assert!(shape_forge.lookup_position(proto.shape_id(), iterator_key).is_some()); } /// 把 Error 家族方法安装到 Error 及各子类型构造器与原型上。 - pub fn bind_error_methods(&self, methods: &ErrorMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) { - let ctor_ptr = P::as_ptr(&self.error_constructor) as *mut JsObject; + pub fn bind_error_methods(env: BindEnv<'_>, methods: &ErrorMethods) { + let world = env.world; + let string_forge = env.string_forge; + let shape_forge = env.shape_forge; + let ctor_ptr = P::as_ptr(&world.error_constructor) as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; bind_methods!( - self, + env, ctor, - string_forge, - shape_forge, ("Error", methods.error, 1), ("TypeError", methods.type_error, 1), ("ReferenceError", methods.reference_error, 1), @@ -166,13 +166,11 @@ impl BuiltinWorld { ("isError", methods.is_error, 1), ); - let proto_ptr = P::as_ptr(&self.error_proto) as *mut JsObject; + let proto_ptr = P::as_ptr(&world.error_proto) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; bind_methods!( - self, + env, proto, - string_forge, - shape_forge, ("toString", methods.to_string, 0), ("toJSON", methods.to_json, 1), ); @@ -194,24 +192,18 @@ impl BuiltinWorld { let msg_pos = proto.push_prop(empty_val); proto.set_data_meta(msg_pos, oxide_types::object::PropAttributes::new(true, false, true)); - self.set_subtype_proto_name(string_forge, shape_forge, &self.type_error_proto, "TypeError", si_name); - self.set_subtype_proto_name(string_forge, shape_forge, &self.reference_error_proto, "ReferenceError", si_name); - self.set_subtype_proto_name(string_forge, shape_forge, &self.range_error_proto, "RangeError", si_name); - self.set_subtype_proto_name(string_forge, shape_forge, &self.syntax_error_proto, "SyntaxError", si_name); - self.set_subtype_proto_name(string_forge, shape_forge, &self.uri_error_proto, "URIError", si_name); - self.set_subtype_proto_name(string_forge, shape_forge, &self.eval_error_proto, "EvalError", si_name); - self.set_subtype_proto_name( - string_forge, - shape_forge, - &self.suppressed_error_proto, - "SuppressedError", - si_name, - ); + Self::set_subtype_proto_name(env, &world.type_error_proto, "TypeError", si_name); + Self::set_subtype_proto_name(env, &world.reference_error_proto, "ReferenceError", si_name); + Self::set_subtype_proto_name(env, &world.range_error_proto, "RangeError", si_name); + Self::set_subtype_proto_name(env, &world.syntax_error_proto, "SyntaxError", si_name); + Self::set_subtype_proto_name(env, &world.uri_error_proto, "URIError", si_name); + Self::set_subtype_proto_name(env, &world.eval_error_proto, "EvalError", si_name); + Self::set_subtype_proto_name(env, &world.suppressed_error_proto, "SuppressedError", si_name); } - fn set_subtype_proto_name( - &self, string_forge: &PermInterner, shape_forge: &ShapeForge, proto_p: &P, name: &str, si_name: u32, - ) { + fn set_subtype_proto_name(env: BindEnv<'_>, proto_p: &P, name: &str, si_name: u32) { + let string_forge = env.string_forge; + let shape_forge = env.shape_forge; let proto_ptr = P::as_ptr(proto_p) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; let name_si = string_forge.intern(name).0; @@ -232,26 +224,25 @@ impl BuiltinWorld { } /// 把 String 家族方法安装到 String 构造器与原型上。 - pub fn bind_string_methods(&self, methods: &StringMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) { - let ctor_ptr = P::as_ptr(&self.string_constructor) as *mut JsObject; + pub fn bind_string_methods(env: BindEnv<'_>, methods: &StringMethods) { + let world = env.world; + let string_forge = env.string_forge; + let shape_forge = env.shape_forge; + let ctor_ptr = P::as_ptr(&world.string_constructor) as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; bind_methods!( - self, + env, ctor, - string_forge, - shape_forge, ("fromCharCode", methods.from_char_code, 1), ("fromCodePoint", methods.from_code_point, 1), ("raw", methods.from_raw, 1), ); - let proto_ptr = P::as_ptr(&self.string_proto) as *mut JsObject; + let proto_ptr = P::as_ptr(&world.string_proto) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; bind_methods!( - self, + env, proto, - string_forge, - shape_forge, ("indexOf", methods.index_of, 1), ("includes", methods.includes, 1), ("charAt", methods.char_at, 1), @@ -320,16 +311,13 @@ impl BuiltinWorld { /// /// `realm_id` 是安装目标所属 realm 的编号:`@@hasInstance` 符号键按 /// (realm 编号, 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 - pub fn bind_function_methods( - &self, methods: &FunctionMethods, string_forge: &PermInterner, shape_forge: &ShapeForge, realm_id: u32, - ) { - let proto_ptr = P::as_ptr(&self.function_proto) as *mut JsObject; + pub fn bind_function_methods(env: BindEnv<'_>, methods: &FunctionMethods, realm_id: u32) { + let world = env.world; + let proto_ptr = P::as_ptr(&world.function_proto) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; - bind_methods_static!( + bind_methods!( + env, proto, - string_forge, - shape_forge, - self, ("call", methods.call, 1), ("apply", methods.apply, 2), ("bind", methods.bind, 1), @@ -338,35 +326,21 @@ impl BuiltinWorld { // @@hasInstance 走 well-known symbol 键(id 6):instanceof 运算符经 // dispatch_instanceof 读该属性调用,绑定后属性存在性测试与全局改写生效。 let _ = Self::bind_method_key_static( + env, proto, - shape_forge, - string_forge, encode_symbol_key(realm_id, 6), "[Symbol.hasInstance]", unsafe { NativeFnPtr::from_raw(methods.has_instance) }, 1, - self, ); } /// 在指定原型上安装一个 native 方法,wrapper 函数以本 world 的 Function 原型为原型。 pub fn bind_method( - &self, proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, method_name: &str, - native_fn_ptr: NativeFnPtr, arg_count: u8, + env: BindEnv<'_>, proto: &mut JsObject, method_name: &str, native_fn_ptr: NativeFnPtr, arg_count: u8, ) -> Result<(), String> { - Self::bind_method_static(proto, shape_forge, string_forge, method_name, native_fn_ptr, arg_count, self) - } - - /// 构造并安装一个 native 方法 wrapper 函数对象(设置 `length`/`name` 属性与参数元数据)。 - /// - /// 无状态版本,供静态绑定宏在初始化阶段直接调用;需要传入当前 - /// `BuiltinWorld`:wrapper 的原型取自它,wrapper 本体登记进它的释放表。 - pub fn bind_method_static( - proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, method_name: &str, - native_fn_ptr: NativeFnPtr, arg_count: u8, world: &BuiltinWorld, - ) -> Result<(), String> { - let si = string_forge.intern(method_name).0; - Self::bind_method_key_static(proto, shape_forge, string_forge, si, method_name, native_fn_ptr, arg_count, world) + let si = env.string_forge.intern(method_name).0; + Self::bind_method_key_static(env, proto, si, method_name, native_fn_ptr, arg_count) } /// 按指定属性键安装方法 wrapper(键不要求字符串 intern,well-known symbol 键用此路径)。 @@ -374,43 +348,19 @@ impl BuiltinWorld { /// `method_name` 只用于 wrapper 的 `name` 属性;`key` 是属性的实际存储键。 /// 目标站点标签取 0:P 目标由家族下标区分,非 P 目标须经 /// [`Self::bind_method_key_labeled_static`] 传站点标签。 - #[expect(clippy::too_many_arguments)] pub fn bind_method_key_static( - proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, key: u32, method_name: &str, - native_fn_ptr: NativeFnPtr, arg_count: u8, world: &BuiltinWorld, + env: BindEnv<'_>, proto: &mut JsObject, key: u32, method_name: &str, native_fn_ptr: NativeFnPtr, arg_count: u8, ) -> Result<(), String> { - Self::bind_method_key_labeled_static( - proto, - shape_forge, - string_forge, - key, - method_name, - native_fn_ptr, - arg_count, - world, - 0, - ) + Self::bind_method_key_labeled_static(env, proto, key, method_name, native_fn_ptr, arg_count, 0) } - /// [`Self::bind_method_static`] 的站点标签版本:属性键由方法名 intern 得出, + /// [`Self::bind_method`] 的站点标签版本:属性键由方法名 intern 得出, /// 供非 P 目标(VM 内建原型 Box 对象)的静态绑定宏使用。 - #[expect(clippy::too_many_arguments)] pub fn bind_method_labeled_static( - proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, method_name: &str, - native_fn_ptr: NativeFnPtr, arg_count: u8, world: &BuiltinWorld, label: u32, + env: BindEnv<'_>, proto: &mut JsObject, method_name: &str, native_fn_ptr: NativeFnPtr, arg_count: u8, label: u32, ) -> Result<(), String> { - let si = string_forge.intern(method_name).0; - Self::bind_method_key_labeled_static( - proto, - shape_forge, - string_forge, - si, - method_name, - native_fn_ptr, - arg_count, - world, - label, - ) + let si = env.string_forge.intern(method_name).0; + Self::bind_method_key_labeled_static(env, proto, si, method_name, native_fn_ptr, arg_count, label) } /// 按指定属性键安装方法 wrapper,显式指定非 P 目标的绑定站点标签。 @@ -418,11 +368,13 @@ impl BuiltinWorld { /// 同一 session 内多个非 P 目标(VM 内建原型 Box 对象等)可绑定同名方法槽 /// (如 next/return/throw):站点标签(站点名 perm intern 键)使复用键跨 /// 站点唯一,重绑时只迁移本站点的旧 wrapper。 - #[expect(clippy::too_many_arguments)] pub fn bind_method_key_labeled_static( - proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, key: u32, method_name: &str, - native_fn_ptr: NativeFnPtr, arg_count: u8, world: &BuiltinWorld, label: u32, + env: BindEnv<'_>, proto: &mut JsObject, key: u32, method_name: &str, native_fn_ptr: NativeFnPtr, arg_count: u8, + label: u32, ) -> Result<(), String> { + let world = env.world; + let shape_forge = env.shape_forge; + let string_forge = env.string_forge; let si = string_forge.intern(method_name).0; // 选择性重建复用:同键旧 wrapper 迁移到新 proto 槽位——其 proto 槽 // 已由重建收尾改写到新指针(或 Function 家族保留而不变),length/name @@ -442,8 +394,8 @@ impl BuiltinWorld { wrapper.set_proto(wrapper_proto_val).ok(); } wrapper.set_function(true); - // NativeFnPtr 不变量由调用方维护(见 bind_method / bind_method_static - // 的调用方,均使用函数项表达式)。 + // NativeFnPtr 不变量由调用方维护(bind_method 家族的调用方 + // 均使用函数项表达式)。 wrapper.set_native_fn(Some(native_fn_ptr)); wrapper.set_native_arg_count(arg_count); // 设置 .length(JS 规范:值为形式参数个数, diff --git a/crates/oxide_kernel/src/builtin/mod.rs b/crates/oxide_kernel/src/builtin/mod.rs index d47ac349..4c7345ca 100644 --- a/crates/oxide_kernel/src/builtin/mod.rs +++ b/crates/oxide_kernel/src/builtin/mod.rs @@ -6,62 +6,34 @@ mod construct; mod methods; mod rebuild; mod world; +pub use bind::BindEnv; pub use methods::{ArrayMethods, ErrorMethods, FunctionMethods, ObjectMethods, RegExpMethods, StringMethods}; pub use world::{BuiltinWorld, FnWrapperKey}; -/// 把一个 native 方法绑定到目标对象:构造(或复用)wrapper 函数对象,以 -/// `$name` 为属性名写入目标对象的命名属性区。 +/// 批量绑定一组 native 方法,条目形如 `(名称, 函数指针, 参数个数)`。 /// -/// `$world` 是 wrapper 归属的 `BuiltinWorld`(wrapper 原型取自它的 -/// Function.prototype,本体登记进它的释放登记表,选择性重建时按键复用); -/// `$sf` / `$sh` 为字符串 / 形状 interner;`$nargs` 是 native 函数形式参数 -/// 个数,写入 wrapper 的 `length` 属性。 -#[macro_export] -macro_rules! bind_method { - ($world:expr, $target:expr, $sf:expr, $sh:expr, $name:literal, $func:expr, $nargs:expr) => {{ - let _raw: *const () = $func as *const (); - // SAFETY: $func 是 NativeFn 函数项;函数项强转为 *const () 始终有效。 - let _func_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(_raw) }; - let _ = $world.bind_method($target, $sh, $sf, $name, _func_ptr, $nargs); - }}; -} - -/// 批量绑定一组 native 方法,条目形如 `(名称, 函数指针, 参数个数)`; -/// 逐条展开为 `bind_method!`。 +/// 首参 `$env` 是 kernel 绑定环境 [`BindEnv`]:把 builtin world、shape forge、 +/// string forge 三要素打包为单一首参。第二形态多一个 `$label`(绑定站点标签): +/// 非 P 目标上同名方法槽(Generator / AsyncGenerator 原型的 next / return / +/// throw)靠它区分。 #[macro_export] macro_rules! bind_methods { - ($world:expr, $target:expr, $sf:expr, $sh:expr, - $(($name:literal, $func:expr, $nargs:expr)),* $(,)?) => { - $( $crate::bind_method!($world, $target, $sf, $sh, $name, $func, $nargs); )* - }; -} - -/// `bind_methods!` 的静态版本:初始化阶段调用,显式传入 `$world`(宏展开到 -/// `BuiltinWorld::bind_method_static` / `bind_method_labeled_static`)。 -/// 第二形态多一个 `$label`(绑定站点标签):非 P 目标上同名方法槽 -/// (Generator / AsyncGenerator 原型的 next / return / throw)靠它区分。 -#[macro_export] -macro_rules! bind_methods_static { - ($target:expr, $sf:expr, $sh:expr, $world:expr, + ($env:expr, $target:expr, $(($name:literal, $func:expr, $nargs:expr)),* $(,)?) => { $({ let _raw: *const () = $func as *const (); // SAFETY: $func 是 NativeFn 函数项;强转并包装合法。 let _func_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(_raw) }; - let _ = $crate::builtin::BuiltinWorld::bind_method_static( - $target, $sh, $sf, $name, _func_ptr, $nargs, $world, - ); + let _ = $crate::builtin::BuiltinWorld::bind_method($env, $target, $name, _func_ptr, $nargs); })* }; - ($target:expr, $sf:expr, $sh:expr, $world:expr, $label:expr, + ($env:expr, $target:expr, $label:expr, $(($name:literal, $func:expr, $nargs:expr)),* $(,)?) => { $({ let _raw: *const () = $func as *const (); // SAFETY: $func 是 NativeFn 函数项;强转并包装合法。 let _func_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(_raw) }; - let _ = $crate::builtin::BuiltinWorld::bind_method_labeled_static( - $target, $sh, $sf, $name, _func_ptr, $nargs, $world, $label, - ); + let _ = $crate::builtin::BuiltinWorld::bind_method_labeled_static($env, $target, $name, _func_ptr, $nargs, $label); })* }; } diff --git a/crates/oxide_kernel/src/builtin/rebuild.rs b/crates/oxide_kernel/src/builtin/rebuild.rs index c0d4b5a2..72f377dc 100644 --- a/crates/oxide_kernel/src/builtin/rebuild.rs +++ b/crates/oxide_kernel/src/builtin/rebuild.rs @@ -10,10 +10,9 @@ use super::construct::{ builtin_labels, make_error_subtypes, make_named_pair, make_typed_array_family, tag_boolean_proto, tag_number_proto, tag_string_proto, wire_builtin_world_links, ErrorSubtypeProtos, TypedArrayFamily, }; -use super::BuiltinWorld; +use super::{BindEnv, BuiltinWorld}; use crate::kernel::BuiltinDirtySet; -use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID}; -use crate::string_forge::PermInterner; +use crate::shape_forge::EMPTY_SHAPE_ID; impl BuiltinWorld { /// 选择性重建收尾:把保留对象的原型槽改写到新对象,并释放被替换旧对象的 @@ -147,9 +146,10 @@ impl BuiltinWorld { /// 本体同时充当 `retire_replaced` 原型槽改写遗漏的兜底:遗漏时读者仅见 /// 属性缺失,不产生 use-after-free。属性区于原型槽改写完成后由 /// `retire_replaced` 释放。 - pub fn rebuild_with_dirty( - current: &BuiltinWorld, string_forge: &PermInterner, shape_forge: &ShapeForge, dirty: &BuiltinDirtySet, - ) -> BuiltinWorld { + pub fn rebuild_with_dirty(env: BindEnv<'_>, dirty: &BuiltinDirtySet) -> BuiltinWorld { + let current = env.world; + let string_forge = env.string_forge; + let shape_forge = env.shape_forge; let labels = builtin_labels(string_forge); // 用 `mem::forget` 抬升 4 个对象(旧 Function/Object 对)的 Arc 计数 diff --git a/crates/oxide_kernel/src/kernel/session.rs b/crates/oxide_kernel/src/kernel/session.rs index 4e1481cc..decbd429 100644 --- a/crates/oxide_kernel/src/kernel/session.rs +++ b/crates/oxide_kernel/src/kernel/session.rs @@ -7,7 +7,7 @@ use oxide_types::mem::P; use oxide_types::object::JsObject; use oxide_types::value::JsValue; -use crate::builtin::BuiltinWorld; +use crate::builtin::{BindEnv, BuiltinWorld}; use crate::shape_forge::EMPTY_SHAPE_ID; use super::{BuiltinDirtySet, BuiltinId, BuiltinSnapshot, KernelCore}; @@ -258,9 +258,11 @@ impl KernelSession { if dirty.any_builtin_dirty() { let old_world = self.builtin_world.clone(); let new_world = BuiltinWorld::rebuild_with_dirty( - &old_world, - core.perm_interner.as_ref(), - core.shape_forge.as_ref(), + BindEnv { + world: &old_world, + shape_forge: core.shape_forge.as_ref(), + string_forge: core.perm_interner.as_ref(), + }, &dirty, ); // 旧 world 的释放登记表并入新 world:存活 wrapper(未污染家族别名) diff --git a/crates/oxide_kernel/tests/builtin_world_tests.rs b/crates/oxide_kernel/tests/builtin_world_tests.rs index a427ae6e..3e7c9ed3 100644 --- a/crates/oxide_kernel/tests/builtin_world_tests.rs +++ b/crates/oxide_kernel/tests/builtin_world_tests.rs @@ -1,4 +1,4 @@ -use oxide_kernel::builtin::BuiltinWorld; +use oxide_kernel::builtin::{BuiltinWorld, BindEnv}; use oxide_kernel::kernel::BuiltinDirtySet; use oxide_kernel::shape_forge::{ShapeForge, EMPTY_SHAPE_ID}; use oxide_kernel::string_forge::PermInterner; @@ -99,7 +99,14 @@ fn builtin_rebuild_with_dirty_reuses_clean_fields() { let sf = PermInterner::new(); let sh = ShapeForge::new(); let w = BuiltinWorld::new(&sf, &sh); - let rebuilt = BuiltinWorld::rebuild_with_dirty(&w, &sf, &sh, &BuiltinDirtySet::default()); + let rebuilt = BuiltinWorld::rebuild_with_dirty( + BindEnv { + world: &w, + shape_forge: &sh, + string_forge: &sf, + }, + &BuiltinDirtySet::default(), + ); assert!(std::ptr::eq(w.object_proto.as_ptr(), rebuilt.object_proto.as_ptr())); assert!(std::ptr::eq(w.array_proto.as_ptr(), rebuilt.array_proto.as_ptr())); @@ -115,7 +122,14 @@ fn builtin_rebuild_with_dirty_replaces_only_dirty_group() { array: true, ..Default::default() }; - let rebuilt = BuiltinWorld::rebuild_with_dirty(&w, &sf, &sh, &dirty); + let rebuilt = BuiltinWorld::rebuild_with_dirty( + BindEnv { + world: &w, + shape_forge: &sh, + string_forge: &sf, + }, + &dirty, + ); assert!(!std::ptr::eq(w.array_proto.as_ptr(), rebuilt.array_proto.as_ptr())); assert!(!std::ptr::eq(w.array_constructor.as_ptr(), rebuilt.array_constructor.as_ptr())); @@ -132,7 +146,14 @@ fn builtin_rebuild_with_dirty_repairs_ctor_proto_links() { array: true, ..Default::default() }; - let rebuilt = BuiltinWorld::rebuild_with_dirty(&w, &sf, &sh, &dirty); + let rebuilt = BuiltinWorld::rebuild_with_dirty( + BindEnv { + world: &w, + shape_forge: &sh, + string_forge: &sf, + }, + &dirty, + ); let ctor_proto = rebuilt.array_constructor.get_prop_at(0).as_js_object_ptr(); let proto_ctor = rebuilt.array_proto.get_prop_at(0).as_js_object_ptr(); diff --git a/crates/oxide_vm/src/async_generator.rs b/crates/oxide_vm/src/async_generator.rs index 2da8e767..462b8e04 100644 --- a/crates/oxide_vm/src/async_generator.rs +++ b/crates/oxide_vm/src/async_generator.rs @@ -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); diff --git a/crates/oxide_vm/src/bindings/bind_array.rs b/crates/oxide_vm/src/bindings/bind_array.rs index 67ac6a8f..9ddc66fb 100644 --- a/crates/oxide_vm/src/bindings/bind_array.rs +++ b/crates/oxide_vm/src/bindings/bind_array.rs @@ -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:: 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 }; diff --git a/crates/oxide_vm/src/bindings/bind_atomics.rs b/crates/oxide_vm/src/bindings/bind_atomics.rs index b84e2488..c4df9f2f 100644 --- a/crates/oxide_vm/src/bindings/bind_atomics.rs +++ b/crates/oxide_vm/src/bindings/bind_atomics.rs @@ -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::, 2), ("store", oxide_builtins::atomics::atomics_store::, 3), ("exchange", oxide_builtins::atomics::atomics_exchange::, 3), diff --git a/crates/oxide_vm/src/bindings/bind_console.rs b/crates/oxide_vm/src/bindings/bind_console.rs index 5eecb7a7..7ed75e88 100644 --- a/crates/oxide_vm/src/bindings/bind_console.rs +++ b/crates/oxide_vm/src/bindings/bind_console.rs @@ -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::, 1), ("warn", oxide_builtins::console::warn::, 1), ("error", oxide_builtins::console::error::, 1), diff --git a/crates/oxide_vm/src/bindings/bind_error.rs b/crates/oxide_vm/src/bindings/bind_error.rs index e24feca4..9f746299 100644 --- a/crates/oxide_vm/src/bindings/bind_error.rs +++ b/crates/oxide_vm/src/bindings/bind_error.rs @@ -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:: as *const (), to_json: oxide_builtins::error::error_to_json:: 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 绑定器登记复用键, diff --git a/crates/oxide_vm/src/bindings/bind_function.rs b/crates/oxide_vm/src/bindings/bind_function.rs index c8657b3e..424d882c 100644 --- a/crates/oxide_vm/src/bindings/bind_function.rs +++ b/crates/oxide_vm/src/bindings/bind_function.rs @@ -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:: as *const (), has_instance: oxide_builtins::function::function_symbol_has_instance:: 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( diff --git a/crates/oxide_vm/src/bindings/bind_math.rs b/crates/oxide_vm/src/bindings/bind_math.rs index 4011ae83..b81e1425 100644 --- a/crates/oxide_vm/src/bindings/bind_math.rs +++ b/crates/oxide_vm/src/bindings/bind_math.rs @@ -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::, 1), ("acos", oxide_builtins::math::math_acos::, 1), ("asin", oxide_builtins::math::math_asin::, 1), diff --git a/crates/oxide_vm/src/bindings/bind_object.rs b/crates/oxide_vm/src/bindings/bind_object.rs index da5202ae..e180b93a 100644 --- a/crates/oxide_vm/src/bindings/bind_object.rs +++ b/crates/oxide_vm/src/bindings/bind_object.rs @@ -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:: 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 }; diff --git a/crates/oxide_vm/src/bindings/bind_string.rs b/crates/oxide_vm/src/bindings/bind_string.rs index 052327d1..346fa6bc 100644 --- a/crates/oxide_vm/src/bindings/bind_string.rs +++ b/crates/oxide_vm/src/bindings/bind_string.rs @@ -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:: as *const (), sup: oxide_builtins::string::string_sup:: 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 }; diff --git a/crates/oxide_vm/src/bindings/bind_typed_array.rs b/crates/oxide_vm/src/bindings/bind_typed_array.rs index a90d120b..f54d72f3 100644 --- a/crates/oxide_vm/src/bindings/bind_typed_array.rs +++ b/crates/oxide_vm/src/bindings/bind_typed_array.rs @@ -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( diff --git a/crates/oxide_vm/src/bindings/bind_weak.rs b/crates/oxide_vm/src/bindings/bind_weak.rs index 297a0ca8..24cca57e 100644 --- a/crates/oxide_vm/src/bindings/bind_weak.rs +++ b/crates/oxide_vm/src/bindings/bind_weak.rs @@ -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, ); } diff --git a/crates/oxide_vm/src/bindings/mod.rs b/crates/oxide_vm/src/bindings/mod.rs index 986d2ab3..e792b898 100644 --- a/crates/oxide_vm/src/bindings/mod.rs +++ b/crates/oxide_vm/src/bindings/mod.rs @@ -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, @@ -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, 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, 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 键名下(共享同一函数对象)。 diff --git a/crates/oxide_vm/src/generator.rs b/crates/oxide_vm/src/generator.rs index 55690c06..e534f658 100644 --- a/crates/oxide_vm/src/generator.rs +++ b/crates/oxide_vm/src/generator.rs @@ -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); diff --git a/crates/oxide_vm/src/promise/constructor.rs b/crates/oxide_vm/src/promise/constructor.rs index 5b8465a1..8dca2551 100644 --- a/crates/oxide_vm/src/promise/constructor.rs +++ b/crates/oxide_vm/src/promise/constructor.rs @@ -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),