mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: 绑定层环境四件套收敛为 BindEnv 单参
This commit is contained in:
Generated
+21
-21
@@ -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",
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.17.3"
|
||||
version = "0.17.4"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
rust-version = "1.80"
|
||||
|
||||
@@ -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<JsObject>, name: &str, si_name: u32,
|
||||
) {
|
||||
fn set_subtype_proto_name(env: BindEnv<'_>, proto_p: &P<JsObject>, 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 规范:值为形式参数个数,
|
||||
|
||||
@@ -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);
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 计数
|
||||
|
||||
@@ -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(未污染家族别名)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,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,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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,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,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 };
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 键名下(共享同一函数对象)。
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user