refactor: 绑定层函数签名收敛为 BindEnv 单参

This commit is contained in:
2026-10-12 17:25:40 +00:00
parent 3c89324736
commit a651cbff54
37 changed files with 770 additions and 1059 deletions
+15 -20
View File
@@ -1,17 +1,14 @@
use std::sync::Arc;
use oxide_kernel::builtin::ArrayMethods;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use crate::bind_constructor;
use crate::bindings::apply_binding_table;
use crate::bindings::{apply_binding_table, BindEnv};
/// 把 Array 构造器与原型方法绑定到 global。
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_array(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
pub fn bind_array(env: BindEnv<'_>, global: &mut JsObject) {
let _array_methods = ArrayMethods {
is_array: oxide_builtins::array::array_is_array::<crate::vm::Vm> as *const (),
from: oxide_builtins::array::array_from::<crate::vm::Vm> as *const (),
@@ -54,42 +51,40 @@ pub fn bind_array(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
with_method: oxide_builtins::array::array_with::<crate::vm::Vm> as *const (),
};
session.builtin_world().bind_array_methods(
env.world().bind_array_methods(
&_array_methods,
core.perm_interner().as_ref(),
core.shape_forge().as_ref(),
realm_id,
env.string_forge(),
env.shape_forge(),
env.realm_id,
);
let array_proto_ptr = session.builtin_world().array_proto.as_ptr() as *mut JsObject;
let array_proto_ptr = env.world().array_proto.as_ptr() as *mut JsObject;
let array_proto = unsafe { &mut *array_proto_ptr };
apply_binding_table(
session.builtin_world(),
env,
array_proto,
core,
&[
("toString", oxide_builtins::array::array_to_string::<crate::vm::Vm> as *const (), 0),
("toSource", oxide_builtins::to_source::to_source_array::<crate::vm::Vm> as *const (), 0),
],
);
// 内置原型方法不可枚举(否则会泄漏进 for-in)。
let si = core.perm_interner().intern("toString").0;
if let Some(pos) = core.shape_forge().lookup_position(array_proto.shape_id(), si) {
let si = env.string_forge().intern("toString").0;
if let Some(pos) = env.shape_forge().lookup_position(array_proto.shape_id(), si) {
array_proto.set_data_meta(pos, PropAttributes::new(true, false, true));
}
// Array.prototype[@@iterator] 与 values 共享同一函数对象。
super::bind_well_known_method_alias(core, array_proto, "values", 0, realm_id);
super::bind_well_known_method_alias(env.core, array_proto, "values", 0, env.realm_id);
let ctor_ptr = session.builtin_world().array_constructor.as_ptr() as *mut JsObject;
bind_constructor!(core, global, "Array", ctor_ptr, oxide_builtins::array::array_constructor::<crate::vm::Vm>, 1, hash: true);
let ctor_ptr = env.world().array_constructor.as_ptr() as *mut JsObject;
bind_constructor!(env, global, "Array", ctor_ptr, oxide_builtins::array::array_constructor::<crate::vm::Vm>, 1, hash: true);
// Array[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链
// 解析 @@species 得自身构造器(规范不给 class 默认 static @@species,类上
// 无 own 属性)。
super::bind_accessor_getter_key(
core,
session,
env,
unsafe { &mut *ctor_ptr },
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
"get [Symbol.species]",
oxide_builtins::array::array_species_get::<crate::vm::Vm> as *const (),
);
@@ -1,20 +1,17 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_accessor_getter_key, configure_native_constructor,
apply_binding_table, bind_accessor_getter, bind_accessor_getter_key, configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
/// 把 ArrayBuffer 构造器与原型方法绑定到 global。
///
/// `realm_id` 是目标所属 realm 的编号:`@@species` 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let ctor_ptr = session.builtin_world().array_buffer_constructor.as_ptr() as *mut JsObject;
pub fn bind_array_buffer(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().array_buffer_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().array_buffer_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().array_buffer_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(
@@ -24,9 +21,8 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
);
apply_binding_table(
session.builtin_world(),
env,
ctor,
core,
&[(
"isView",
oxide_builtins::array_buffer::array_buffer_is_view::<crate::vm::Vm> as *const (),
@@ -37,18 +33,16 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
// ArrayBuffer[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链
// 解析 @@species 得自身构造器(规范不给 class 默认 static @@species,类上无 own)。
bind_accessor_getter_key(
core,
session,
env,
ctor,
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
"get [Symbol.species]",
oxide_builtins::array::array_species_get::<crate::vm::Vm> as *const (),
);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
(
"resize",
@@ -91,8 +85,7 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
// byteLength 原型访问器(set 恒 undefined):读载荷字节数,实例无 own 属性。
bind_accessor_getter(
core,
session,
env,
proto,
"byteLength",
oxide_builtins::array_buffer::array_buffer_byte_length::<crate::vm::Vm> as *const (),
@@ -100,8 +93,7 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
// resizable 原型访问器(set 恒 undefined):读载荷 max_byte_length 状态位。
bind_accessor_getter(
core,
session,
env,
proto,
"resizable",
oxide_builtins::array_buffer::array_buffer_resizable::<crate::vm::Vm> as *const (),
@@ -110,8 +102,7 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
// maxByteLength 原型访问器(set 恒 undefined):detached 回 +0,定长回
// 当前字节数,resizable 回存储态上限 − 1。
bind_accessor_getter(
core,
session,
env,
proto,
"maxByteLength",
oxide_builtins::array_buffer::array_buffer_max_byte_length::<crate::vm::Vm> as *const (),
@@ -119,8 +110,7 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
// immutable 原型访问器(set 恒 undefined):读载荷 immutable 标志。
bind_accessor_getter(
core,
session,
env,
proto,
"immutable",
oxide_builtins::array_buffer::array_buffer_immutable::<crate::vm::Vm> as *const (),
@@ -128,15 +118,14 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
// detached 原型访问器(set 恒 undefined):读载荷 data 存活位。
bind_accessor_getter(
core,
session,
env,
proto,
"detached",
oxide_builtins::array_buffer::array_buffer_detached::<crate::vm::Vm> as *const (),
);
bind_constructor!(
core,
env,
global,
"ArrayBuffer",
ctor_ptr,
@@ -1,6 +1,3 @@
use std::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
@@ -8,7 +5,7 @@ use oxide_types::value::JsValue;
use crate::async_disposable::dispose_async;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_disposable_stack::write_proto_constructor, bind_global_value,
bind_well_known_data_property, bind_well_known_method_alias, configure_native_constructor,
bind_well_known_data_property, bind_well_known_method_alias, configure_native_constructor, BindEnv,
};
/// 在 `AsyncDisposableStack.prototype` 上安装方法/别名/访问器/@@toStringTag。
@@ -19,19 +16,18 @@ use crate::bindings::{
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_async_disposable_stack_protos(core: &Arc<KernelCore>, session: &KernelSession, realm_id: u32) {
let world = session.builtin_world();
pub fn bind_async_disposable_stack_protos(env: BindEnv<'_>) {
let world = env.world();
let proto_ptr = world.async_disposable_stack_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let si_use = core.perm_interner().intern("use").0;
if core.shape_forge().lookup_position(proto.shape_id(), si_use).is_some() {
let si_use = env.string_forge().intern("use").0;
if env.shape_forge().lookup_position(proto.shape_id(), si_use).is_some() {
return;
}
apply_binding_table(
world,
env,
proto,
core,
&[
(
"use",
@@ -57,17 +53,16 @@ pub fn bind_async_disposable_stack_protos(core: &Arc<KernelCore>, session: &Kern
],
);
bind_accessor_getter(
core,
session,
env,
proto,
"disposed",
oxide_builtins::disposable_stack::async_disposable_stack_disposed_getter::<crate::vm::Vm> as *const (),
);
// @@asyncDispose 与 disposeAsync 为同一函数对象(先绑 disposeAsync 再取源槽)。
bind_well_known_method_alias(core, proto, "disposeAsync", 11, realm_id);
let sf = core.perm_interner().as_ref();
bind_well_known_method_alias(env.core, proto, "disposeAsync", 11, env.realm_id);
let sf = env.string_forge();
let tag = JsValue::perm_string(sf.string_ptr(sf.intern("AsyncDisposableStack").0));
bind_well_known_data_property(core, proto, 9, tag, PropAttributes::new(false, false, true), realm_id);
bind_well_known_data_property(env.core, proto, 9, tag, PropAttributes::new(false, false, true), env.realm_id);
}
/// 把 `AsyncDisposableStack` 构造器绑定到 global(init 与 full_reset global 重建共用)。
@@ -78,14 +73,12 @@ pub fn bind_async_disposable_stack_protos(core: &Arc<KernelCore>, session: &Kern
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_async_disposable_stack(
core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32,
) {
let world = session.builtin_world();
pub fn bind_async_disposable_stack(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let proto_ptr = world.async_disposable_stack_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let si_constructor = core.perm_interner().intern("constructor").0;
let ctor_val = match core.shape_forge().lookup_position(proto.shape_id(), si_constructor) {
let si_constructor = env.string_forge().intern("constructor").0;
let ctor_val = match env.shape_forge().lookup_position(proto.shape_id(), si_constructor) {
Some(pos) => {
let existing = proto.get_prop_at(pos);
if existing.is_object() {
@@ -99,8 +92,8 @@ pub fn bind_async_disposable_stack(
let ctor_val = if ctor_val.is_object() {
ctor_val
} else {
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let sf = env.string_forge();
let sh = env.shape_forge();
let name_si = sf.intern("AsyncDisposableStack").0;
// 选择性重建复用:非 P 目标(家族 0)按键查找前轮旧构造器迁移,避免每轮
// 新建导致登记表无界累积;槽键取 global 槽名,该命名空间内全局唯一。
@@ -152,9 +145,9 @@ pub fn bind_async_disposable_stack(
JsValue::from_js_object(ctor_ptr)
};
write_proto_constructor(core, proto, ctor_val);
bind_async_disposable_stack_protos(core, session, realm_id);
bind_global_value(core, global, "AsyncDisposableStack", ctor_val);
write_proto_constructor(env, proto, ctor_val);
bind_async_disposable_stack_protos(env);
bind_global_value(env.core, global, "AsyncDisposableStack", ctor_val);
}
/// 对齐保留 global 上 `AsyncDisposableStack` 函数对象的 `prototype` 属性:object
@@ -163,9 +156,9 @@ pub fn bind_async_disposable_stack(
///
/// global 同时重建(global dirty)或初始化时无 `AsyncDisposableStack` 属性,
/// 直接跳过——彼时由 `bind_async_disposable_stack` 以新原型创建函数对象。
pub fn sync_async_disposable_stack_ctor(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let si_stack = core.perm_interner().intern("AsyncDisposableStack").0;
let Some(pos) = core.shape_forge().lookup_position(global.shape_id(), si_stack) else {
pub fn sync_async_disposable_stack_ctor(env: BindEnv<'_>, global: &mut JsObject) {
let si_stack = env.string_forge().intern("AsyncDisposableStack").0;
let Some(pos) = env.shape_forge().lookup_position(global.shape_id(), si_stack) else {
return;
};
let stack_val = global.get_prop_at(pos);
@@ -173,14 +166,14 @@ pub fn sync_async_disposable_stack_ctor(core: &Arc<KernelCore>, session: &Kernel
return;
}
let ctor = unsafe { &mut *stack_val.as_js_object_ptr() };
let si_prototype = core.perm_interner().intern("prototype").0;
let Some(proto_pos) = core.shape_forge().lookup_position(ctor.shape_id(), si_prototype) else {
let si_prototype = env.string_forge().intern("prototype").0;
let Some(proto_pos) = env.shape_forge().lookup_position(ctor.shape_id(), si_prototype) else {
return;
};
let new_proto =
JsValue::from_js_object(session.builtin_world().async_disposable_stack_proto.as_ptr() as *mut JsObject);
JsValue::from_js_object(env.world().async_disposable_stack_proto.as_ptr() as *mut JsObject);
ctor.set_prop_at(proto_pos, new_proto);
let proto_ptr = session.builtin_world().async_disposable_stack_proto.as_ptr() as *mut JsObject;
write_proto_constructor(core, unsafe { &mut *proto_ptr }, stack_val);
let proto_ptr = env.world().async_disposable_stack_proto.as_ptr() as *mut JsObject;
write_proto_constructor(env, unsafe { &mut *proto_ptr }, stack_val);
}
+7 -10
View File
@@ -1,23 +1,20 @@
use std::sync::Arc;
use oxide_kernel::bind_methods;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
use crate::bindings::bind_global_value;
use crate::bindings::{bind_global_value, BindEnv};
/// 把 Atomics 全局纯对象及其 10 个原子方法绑定到 global。
///
/// Atomics 非函数对象:原型链落 Object.prototype(`wire_builtin_world_links`),
/// `@@toStringTag` 由 `install_to_string_tags` 统一补装;此处只装方法与全局槽。
pub fn bind_atomics(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let atomics_ptr = session.builtin_world().atomics_object.as_ptr() as *mut JsObject;
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 = session.builtin_world();
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let bw = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
bind_methods!(
bw,
@@ -41,5 +38,5 @@ pub fn bind_atomics(core: &Arc<KernelCore>, session: &KernelSession, global: &mu
);
let a_val = JsValue::from_js_object(atomics_ptr);
bind_global_value(core, global, "Atomics", a_val);
bind_global_value(env.core, global, "Atomics", a_val);
}
+11 -16
View File
@@ -1,9 +1,6 @@
use std::sync::Arc;
use crate::bindings::{
apply_binding_table, bind_global_value, bind_well_known_data_property, configure_native_constructor,
apply_binding_table, bind_global_value, bind_well_known_data_property, configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -15,8 +12,8 @@ use oxide_types::value::JsValue;
///
/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号,
/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_bigint(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let world = session.builtin_world();
pub fn bind_bigint(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let ctor_ptr = world.bigint_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = world.bigint_proto.as_ptr() as *mut JsObject;
@@ -24,8 +21,8 @@ pub fn bind_bigint(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
configure_native_constructor(ctor, oxide_builtins::bigint::bigint_constructor::<crate::vm::Vm> as *const (), 1);
// BigInt.length = 1,属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(ctor.shape_id(), length_si);
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push(JsValue::int(1));
let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
@@ -33,9 +30,8 @@ pub fn bind_bigint(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// 静态方法:asIntN / asUintN(length 均为 2)。
apply_binding_table(
world,
env,
ctor,
core,
&[
("asIntN", oxide_builtins::bigint::bigint_as_int_n::<crate::vm::Vm> as *const (), 2),
("asUintN", oxide_builtins::bigint::bigint_as_uint_n::<crate::vm::Vm> as *const (), 2),
@@ -43,9 +39,8 @@ pub fn bind_bigint(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
);
apply_binding_table(
world,
env,
proto,
core,
&[
("toString", oxide_builtins::bigint::bigint_to_string::<crate::vm::Vm> as *const (), 0),
(
@@ -58,9 +53,9 @@ pub fn bind_bigint(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
);
// BigInt.prototype[@@toStringTag] = "BigInt",属性 { writable:false, enumerable:false, configurable:true }。
let tag_si = core.perm_interner().intern("BigInt").0;
let tag_value = JsValue::perm_string(core.perm_interner().string_ptr(tag_si));
bind_well_known_data_property(core, proto, 9, tag_value, PropAttributes::new(false, false, true), realm_id);
let tag_si = env.string_forge().intern("BigInt").0;
let tag_value = JsValue::perm_string(env.string_forge().string_ptr(tag_si));
bind_well_known_data_property(env.core, proto, 9, tag_value, PropAttributes::new(false, false, true), env.realm_id);
bind_global_value(core, global, "BigInt", JsValue::from_js_object(ctor_ptr));
bind_global_value(env.core, global, "BigInt", JsValue::from_js_object(ctor_ptr));
}
+6 -10
View File
@@ -1,23 +1,19 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, configure_native_constructor, BindEnv};
use oxide_types::object::JsObject;
/// 把 Boolean 构造器与原型方法绑定到 global。
pub fn bind_boolean(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let ctor_ptr = session.builtin_world().boolean_constructor.as_ptr() as *mut JsObject;
pub fn bind_boolean(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().boolean_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().boolean_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().boolean_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(ctor, oxide_builtins::boolean::boolean_constructor::<crate::vm::Vm> as *const (), 1);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
(
"valueOf",
@@ -33,5 +29,5 @@ pub fn bind_boolean(core: &Arc<KernelCore>, session: &KernelSession, global: &mu
],
);
bind_constructor!(core, global, "Boolean", ctor_ptr, oxide_builtins::boolean::boolean_constructor::<crate::vm::Vm>, 1, hash: true);
bind_constructor!(env, global, "Boolean", ctor_ptr, oxide_builtins::boolean::boolean_constructor::<crate::vm::Vm>, 1, hash: true);
}
@@ -1,8 +1,7 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, bind_accessor_getset, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{
apply_binding_table, bind_accessor_getset, bind_accessor_getter, configure_native_constructor, BindEnv,
};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -20,15 +19,15 @@ use oxide_types::value::JsValue;
///
/// `realm_id` 未使用(BroadcastChannel 无 well-known 符号键),保留签名与其他
/// 绑定函数一致。
pub fn bind_broadcast_channel(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, _realm_id: u32) {
let world = session.builtin_world();
pub fn bind_broadcast_channel(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let ctor_ptr = world.broadcast_channel_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = world.broadcast_channel_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let sf = env.string_forge();
let sh = env.shape_forge();
// ---- 填构造器占位 ----
ctor.set_function(true);
@@ -65,7 +64,7 @@ pub fn bind_broadcast_channel(core: &Arc<KernelCore>, session: &KernelSession, g
1,
);
bind_constructor!(
core,
env,
global,
"BroadcastChannel",
ctor_ptr,
@@ -93,9 +92,8 @@ pub fn bind_broadcast_channel(core: &Arc<KernelCore>, session: &KernelSession, g
let si_post_message = sf.intern("postMessage").0;
if sh.lookup_position(proto.shape_id(), si_post_message).is_none() {
apply_binding_table(
world,
env,
proto,
core,
&[
(
"postMessage",
@@ -115,8 +113,7 @@ pub fn bind_broadcast_channel(core: &Arc<KernelCore>, session: &KernelSession, g
let si_name_proto = sf.intern("name").0;
if sh.lookup_position(proto.shape_id(), si_name_proto).is_none() {
bind_accessor_getter(
core,
session,
env,
proto,
"name",
oxide_builtins::broadcast_channel::broadcast_channel_name::<crate::vm::Vm> as *const (),
@@ -127,8 +124,7 @@ pub fn bind_broadcast_channel(core: &Arc<KernelCore>, session: &KernelSession, g
let si_ready_state = sf.intern("readyState").0;
if sh.lookup_position(proto.shape_id(), si_ready_state).is_none() {
bind_accessor_getter(
core,
session,
env,
proto,
"readyState",
oxide_builtins::broadcast_channel::broadcast_channel_ready_state::<crate::vm::Vm> as *const (),
@@ -141,8 +137,7 @@ pub fn bind_broadcast_channel(core: &Arc<KernelCore>, session: &KernelSession, g
let key = sf.intern(name).0;
if sh.lookup_position(proto.shape_id(), key).is_none() {
bind_accessor_getset(
core,
session,
env,
proto,
key,
&format!("get {name}"),
+8 -11
View File
@@ -1,18 +1,15 @@
use std::sync::Arc;
use crate::bindings::bind_global_value;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{bind_global_value, BindEnv};
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
/// 把 Console 单例对象及其方法(log/warn/error/info/debug/trace)绑定到 global。
pub fn bind_console(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let console_ptr = session.builtin_world().console_object.as_ptr() as *mut JsObject;
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 = session.builtin_world();
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let bw = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
oxide_kernel::bind_methods!(
bw,
@@ -28,9 +25,9 @@ pub fn bind_console(core: &Arc<KernelCore>, session: &KernelSession, global: &mu
);
bind_global_value(
core,
env.core,
global,
"console",
JsValue::from_js_object(session.builtin_world().console_object.as_ptr() as *mut JsObject),
JsValue::from_js_object(env.world().console_object.as_ptr() as *mut JsObject),
);
}
+11 -18
View File
@@ -1,15 +1,12 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor, BindEnv};
use oxide_types::object::{JsObject, PropAttributes};
/// 把 DataView 构造器与原型方法绑定到 global。
pub fn bind_data_view(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let ctor_ptr = session.builtin_world().data_view_constructor.as_ptr() as *mut JsObject;
pub fn bind_data_view(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().data_view_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().data_view_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().data_view_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(
@@ -19,9 +16,8 @@ pub fn bind_data_view(core: &Arc<KernelCore>, session: &KernelSession, global: &
);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("getInt8", oxide_builtins::data_view::data_view_get_int8::<crate::vm::Vm> as *const (), 1),
(
@@ -133,34 +129,31 @@ pub fn bind_data_view(core: &Arc<KernelCore>, session: &KernelSession, global: &
],
);
bind_constructor!(core, global, "DataView", ctor_ptr, oxide_builtins::data_view::data_view_constructor::<crate::vm::Vm>, 1, hash: true);
bind_constructor!(env, global, "DataView", ctor_ptr, oxide_builtins::data_view::data_view_constructor::<crate::vm::Vm>, 1, hash: true);
// length 属性描述符补 { writable:false, enumerable:false, configurable:true }
// (bind_constructor! 宏的通用缺省 meta 不可写回,此处理仅覆盖 DataView)。
{
let length_si = core.perm_interner().intern("length").0;
if let Some(pos) = core.shape_forge().lookup_position(ctor.shape_id(), length_si) {
let length_si = env.string_forge().intern("length").0;
if let Some(pos) = env.shape_forge().lookup_position(ctor.shape_id(), length_si) {
ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
}
}
// buffer/byteOffset/byteLength 只读访问器(set 恒 undefined,getter 读视图状态盒)。
bind_accessor_getter(
core,
session,
env,
proto,
"buffer",
oxide_builtins::data_view::data_view_buffer_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"byteOffset",
oxide_builtins::data_view::data_view_byte_offset_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"byteLength",
oxide_builtins::data_view::data_view_byte_length_getter::<crate::vm::Vm> as *const (),
+9 -14
View File
@@ -1,30 +1,26 @@
use std::sync::Arc;
use crate::bindings::{apply_binding_table, bind_global_value, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_global_value, configure_native_constructor, BindEnv};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// 把 Date 构造器与原型方法绑定到 global。
pub fn bind_date(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let ctor_ptr = session.builtin_world().date_constructor.as_ptr() as *mut JsObject;
pub fn bind_date(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().date_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().date_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().date_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(ctor, oxide_builtins::date::date_constructor::<crate::vm::Vm> as *const (), 7);
// Date.length = 7,描述符 { writable:false, enumerable:false, configurable:true }。
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(ctor.shape_id(), length_si);
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push(JsValue::int(7));
let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
session.builtin_world(),
env,
ctor,
core,
&[
("now", oxide_builtins::date::date_now::<crate::vm::Vm> as *const (), 0),
("parse", oxide_builtins::date::date_parse::<crate::vm::Vm> as *const (), 1),
@@ -33,9 +29,8 @@ pub fn bind_date(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("getTime", oxide_builtins::date::date_get_time::<crate::vm::Vm> as *const (), 0),
("getFullYear", oxide_builtins::date::date_get_full_year::<crate::vm::Vm> as *const (), 0),
@@ -143,5 +138,5 @@ pub fn bind_date(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
],
);
bind_global_value(core, global, "Date", JsValue::from_js_object(ctor_ptr));
bind_global_value(env.core, global, "Date", JsValue::from_js_object(ctor_ptr));
}
@@ -1,13 +1,10 @@
use std::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_global_value, bind_well_known_data_property,
bind_well_known_method_alias, configure_native_constructor,
bind_well_known_method_alias, configure_native_constructor, BindEnv,
};
/// 在 `DisposableStack.prototype` 上安装方法/别名/访问器/@@toStringTag。
@@ -18,19 +15,18 @@ use crate::bindings::{
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_disposable_stack_protos(core: &Arc<KernelCore>, session: &KernelSession, realm_id: u32) {
let world = session.builtin_world();
pub fn bind_disposable_stack_protos(env: BindEnv<'_>) {
let world = env.world();
let proto_ptr = world.disposable_stack_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let si_use = core.perm_interner().intern("use").0;
if core.shape_forge().lookup_position(proto.shape_id(), si_use).is_some() {
let si_use = env.string_forge().intern("use").0;
if env.shape_forge().lookup_position(proto.shape_id(), si_use).is_some() {
return;
}
apply_binding_table(
world,
env,
proto,
core,
&[
(
"use",
@@ -60,23 +56,22 @@ pub fn bind_disposable_stack_protos(core: &Arc<KernelCore>, session: &KernelSess
],
);
bind_accessor_getter(
core,
session,
env,
proto,
"disposed",
oxide_builtins::disposable_stack::disposable_stack_disposed_getter::<crate::vm::Vm> as *const (),
);
// @@dispose 与 dispose 为同一函数对象(先绑 dispose 再取源槽)。
bind_well_known_method_alias(core, proto, "dispose", 12, realm_id);
let sf = core.perm_interner().as_ref();
bind_well_known_method_alias(env.core, proto, "dispose", 12, env.realm_id);
let sf = env.string_forge();
let tag = JsValue::perm_string(sf.string_ptr(sf.intern("DisposableStack").0));
bind_well_known_data_property(core, proto, 9, tag, PropAttributes::new(false, false, true), realm_id);
bind_well_known_data_property(env.core, proto, 9, tag, PropAttributes::new(false, false, true), env.realm_id);
}
/// 在 proto 上写 `constructor` 数据属性(非枚举,描述符 {t,f,t})。
pub(crate) fn write_proto_constructor(core: &Arc<KernelCore>, proto: &mut JsObject, ctor_val: JsValue) {
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
pub(crate) fn write_proto_constructor(env: BindEnv<'_>, proto: &mut JsObject, ctor_val: JsValue) {
let sf = env.string_forge();
let sh = env.shape_forge();
let si_constructor = sf.intern("constructor").0;
if sh.lookup_position(proto.shape_id(), si_constructor).is_some() {
return;
@@ -96,12 +91,12 @@ pub(crate) fn write_proto_constructor(core: &Arc<KernelCore>, proto: &mut JsObje
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_disposable_stack(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let world = session.builtin_world();
pub fn bind_disposable_stack(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let proto_ptr = world.disposable_stack_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let si_constructor = core.perm_interner().intern("constructor").0;
let ctor_val = match core.shape_forge().lookup_position(proto.shape_id(), si_constructor) {
let si_constructor = env.string_forge().intern("constructor").0;
let ctor_val = match env.shape_forge().lookup_position(proto.shape_id(), si_constructor) {
Some(pos) => {
let existing = proto.get_prop_at(pos);
if existing.is_object() {
@@ -115,8 +110,8 @@ pub fn bind_disposable_stack(core: &Arc<KernelCore>, session: &KernelSession, gl
let ctor_val = if ctor_val.is_object() {
ctor_val
} else {
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let sf = env.string_forge();
let sh = env.shape_forge();
let name_si = sf.intern("DisposableStack").0;
// 选择性重建复用:非 P 目标(家族 0)按键查找前轮旧构造器迁移,避免每轮
// 新建导致登记表无界累积;槽键取 global 槽名,该命名空间内全局唯一。
@@ -167,9 +162,9 @@ pub fn bind_disposable_stack(core: &Arc<KernelCore>, session: &KernelSession, gl
JsValue::from_js_object(ctor_ptr)
};
write_proto_constructor(core, proto, ctor_val);
bind_disposable_stack_protos(core, session, realm_id);
bind_global_value(core, global, "DisposableStack", ctor_val);
write_proto_constructor(env, proto, ctor_val);
bind_disposable_stack_protos(env);
bind_global_value(env.core, global, "DisposableStack", ctor_val);
}
/// 对齐保留 global 上 `DisposableStack` 函数对象的 `prototype` 属性:object 家族
@@ -178,9 +173,9 @@ pub fn bind_disposable_stack(core: &Arc<KernelCore>, session: &KernelSession, gl
///
/// global 同时重建(global dirty)或初始化时无 `DisposableStack` 属性,直接跳过
/// ——彼时由 `bind_disposable_stack` 以新原型创建函数对象。
pub fn sync_disposable_stack_ctor(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let si_stack = core.perm_interner().intern("DisposableStack").0;
let Some(pos) = core.shape_forge().lookup_position(global.shape_id(), si_stack) else {
pub fn sync_disposable_stack_ctor(env: BindEnv<'_>, global: &mut JsObject) {
let si_stack = env.string_forge().intern("DisposableStack").0;
let Some(pos) = env.shape_forge().lookup_position(global.shape_id(), si_stack) else {
return;
};
let stack_val = global.get_prop_at(pos);
@@ -188,13 +183,13 @@ pub fn sync_disposable_stack_ctor(core: &Arc<KernelCore>, session: &KernelSessio
return;
}
let ctor = unsafe { &mut *stack_val.as_js_object_ptr() };
let si_prototype = core.perm_interner().intern("prototype").0;
let Some(proto_pos) = core.shape_forge().lookup_position(ctor.shape_id(), si_prototype) else {
let si_prototype = env.string_forge().intern("prototype").0;
let Some(proto_pos) = env.shape_forge().lookup_position(ctor.shape_id(), si_prototype) else {
return;
};
let new_proto = JsValue::from_js_object(session.builtin_world().disposable_stack_proto.as_ptr() as *mut JsObject);
let new_proto = JsValue::from_js_object(env.world().disposable_stack_proto.as_ptr() as *mut JsObject);
ctor.set_prop_at(proto_pos, new_proto);
let proto_ptr = session.builtin_world().disposable_stack_proto.as_ptr() as *mut JsObject;
write_proto_constructor(core, unsafe { &mut *proto_ptr }, stack_val);
let proto_ptr = env.world().disposable_stack_proto.as_ptr() as *mut JsObject;
write_proto_constructor(env, unsafe { &mut *proto_ptr }, stack_val);
}
+36 -46
View File
@@ -1,18 +1,17 @@
use std::sync::Arc;
use oxide_kernel::builtin::ErrorMethods;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use super::BindEnv;
fn bind_error_subtype_constructor(
core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, name: &str, proto_ptr: *mut JsObject,
env: BindEnv<'_>, global: &mut JsObject, name: &str, proto_ptr: *mut JsObject,
ctor_fn: *const (), arg_count: u8,
) {
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let world = session.builtin_world();
let sf = env.string_forge();
let sh = env.shape_forge();
let world = env.world();
let name_si = sf.intern(name).0;
// SAFETY: ctor_fn 是调用方转成 *const () 的 NativeFn 函数项指针。
let ctor_fn_ptr = unsafe { NativeFnPtr::from_raw(ctor_fn) };
@@ -95,7 +94,7 @@ fn bind_error_subtype_constructor(
}
/// 把 Error 及各子类型(TypeError/ReferenceError/...)构造器与原型方法绑定到 global。
pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
pub fn bind_error(env: BindEnv<'_>, global: &mut JsObject) {
let error_methods = ErrorMethods {
error: oxide_builtins::error::error_constructor::<crate::vm::Vm> as *const (),
type_error: oxide_builtins::error::type_error_constructor::<crate::vm::Vm> as *const (),
@@ -109,23 +108,22 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
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 (),
};
session.builtin_world().bind_error_methods(
env.world().bind_error_methods(
&error_methods,
core.perm_interner().as_ref(),
core.shape_forge().as_ref(),
env.string_forge(),
env.shape_forge(),
);
// stack 为访问器成对安装(getter 现算栈串 / setter 走
// SetterThatIgnoresPrototypeProperties),经 getset 绑定器登记复用键,
// 选择性重建时同槽迁移旧 wrapper。
{
let proto_ptr = session.builtin_world().error_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().error_proto.as_ptr() as *mut JsObject;
// SAFETY: error_proto 由 session 持有,存活整个 session;本块内只改其 shape/属性区,无 reset。
let proto = unsafe { &mut *proto_ptr };
let si_stack = core.perm_interner().intern("stack").0;
let si_stack = env.string_forge().intern("stack").0;
super::bind_accessor_getset(
core,
session,
env,
proto,
si_stack,
"get stack",
@@ -138,25 +136,24 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// toSource 遗留扩展(Error 原型方法不走 kernel 侧 bind_error_methods,
// 此处独立经 apply_binding_table 安装,描述符非枚举由绑定器内置)。
{
let proto_ptr = session.builtin_world().error_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().error_proto.as_ptr() as *mut JsObject;
// SAFETY: error_proto 由 session 持有,存活整个 session;本块内只改其 shape/属性区,无 reset。
let proto = unsafe { &mut *proto_ptr };
super::apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[("toSource", oxide_builtins::to_source::to_source_error::<crate::vm::Vm> as *const (), 0)],
);
}
// 全局 Error 槽位既有槽原位更新(旧家族构造器指针不得滞留在属性 vec),
// 无槽时开新槽;描述符非枚举(规范 { writable:true, enumerable:false, configurable:true })。
let si_err = core.perm_interner().intern("Error").0;
let err_val = JsValue::from_js_object(session.builtin_world().error_constructor.as_ptr() as *mut JsObject);
if let Some(pos) = core.shape_forge().lookup_position(global.shape_id(), si_err) {
let si_err = env.string_forge().intern("Error").0;
let err_val = JsValue::from_js_object(env.world().error_constructor.as_ptr() as *mut JsObject);
if let Some(pos) = env.shape_forge().lookup_position(global.shape_id(), si_err) {
global.set_prop_at(pos, err_val);
} else {
let err_shape = core.shape_forge().make_shape(global.shape_id(), si_err);
let err_shape = env.shape_forge().make_shape(global.shape_id(), si_err);
global.set_shape_id(err_shape);
global.ensure_hash_props().push(err_val);
let err_pos = global.prop_vec_len().saturating_sub(1) as u32;
@@ -165,73 +162,66 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
}
bind_error_subtype_constructor(
core,
session,
env,
global,
"TypeError",
session.builtin_world().type_error_proto.as_ptr() as *mut JsObject,
env.world().type_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::type_error_constructor::<crate::vm::Vm> as *const (),
1,
);
bind_error_subtype_constructor(
core,
session,
env,
global,
"ReferenceError",
session.builtin_world().reference_error_proto.as_ptr() as *mut JsObject,
env.world().reference_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::reference_error_constructor::<crate::vm::Vm> as *const (),
1,
);
bind_error_subtype_constructor(
core,
session,
env,
global,
"RangeError",
session.builtin_world().range_error_proto.as_ptr() as *mut JsObject,
env.world().range_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::range_error_constructor::<crate::vm::Vm> as *const (),
1,
);
bind_error_subtype_constructor(
core,
session,
env,
global,
"SyntaxError",
session.builtin_world().syntax_error_proto.as_ptr() as *mut JsObject,
env.world().syntax_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::syntax_error_constructor::<crate::vm::Vm> as *const (),
1,
);
bind_error_subtype_constructor(
core,
session,
env,
global,
"URIError",
session.builtin_world().uri_error_proto.as_ptr() as *mut JsObject,
env.world().uri_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::uri_error_constructor::<crate::vm::Vm> as *const (),
1,
);
bind_error_subtype_constructor(
core,
session,
env,
global,
"EvalError",
session.builtin_world().eval_error_proto.as_ptr() as *mut JsObject,
env.world().eval_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::eval_error_constructor::<crate::vm::Vm> as *const (),
1,
);
// SuppressedError 为三参构造器(error, suppressed, message),length=3。
bind_error_subtype_constructor(
core,
session,
env,
global,
"SuppressedError",
session.builtin_world().suppressed_error_proto.as_ptr() as *mut JsObject,
env.world().suppressed_error_proto.as_ptr() as *mut JsObject,
oxide_builtins::error::suppressed_error_constructor::<crate::vm::Vm> as *const (),
3,
);
{
let err_ctor_ptr = session.builtin_world().error_constructor.as_ptr() as *mut JsObject;
let err_ctor_ptr = env.world().error_constructor.as_ptr() as *mut JsObject;
let err_ctor = unsafe { &mut *err_ctor_ptr };
err_ctor.type_tag = JsObject::OBJ_TYPE_CONSTRUCTOR;
// SAFETY: error_constructor 是 NativeFn 函数项。
@@ -239,8 +229,8 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
NativeFnPtr::from_raw(oxide_builtins::error::error_constructor::<crate::vm::Vm> as *const ())
}));
// 主 Error 构造器补 length 槽(值 1,与子类型构造器一致)。
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let sf = env.string_forge();
let sh = env.shape_forge();
let si_length = sf.intern("length").0;
let length_shape = sh.make_shape(err_ctor.shape_id(), si_length);
err_ctor.set_shape_id(length_shape);
+15 -20
View File
@@ -7,11 +7,8 @@
//! `custom_event_constructor` / `custom_event_proto` 两枚 P 字段占位(构造器
//! 本体与原型 getter),并绑全局 `CustomEvent`。
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor, BindEnv};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -31,15 +28,15 @@ use oxide_types::value::JsValue;
/// `bind_constructor!` 的全局槽臂自带既有槽原位更新,天然幂等。
///
/// `realm_id` 未使用(Event 无 well-known 符号键),保留签名与其他绑定函数一致。
pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, _realm_id: u32) {
let world = session.builtin_world();
pub fn bind_event(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let ctor_ptr = world.event_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = world.event_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let sf = env.string_forge();
let sh = env.shape_forge();
// ---- 填构造器占位 ----
ctor.set_function(true);
@@ -72,7 +69,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
configure_native_constructor(ctor, oxide_builtins::event::event_constructor::<crate::vm::Vm> as *const (), 2);
bind_constructor!(
core,
env,
global,
"Event",
ctor_ptr,
@@ -115,9 +112,8 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_prevent_default = sf.intern("preventDefault").0;
if sh.lookup_position(proto.shape_id(), si_prevent_default).is_none() {
apply_binding_table(
world,
env,
proto,
core,
&[
(
"preventDefault",
@@ -166,7 +162,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
for (name, fn_ptr) in getter_fns {
let si = sf.intern(name).0;
if sh.lookup_position(proto.shape_id(), si).is_none() {
bind_accessor_getter(core, session, proto, name, fn_ptr);
bind_accessor_getter(env, proto, name, fn_ptr);
}
}
@@ -204,7 +200,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
2,
);
bind_constructor!(
core,
env,
global,
"MessageEvent",
me_ctor_ptr,
@@ -239,7 +235,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
for (name, fn_ptr) in me_getter_fns {
let si = sf.intern(name).0;
if sh.lookup_position(me_proto.shape_id(), si).is_none() {
bind_accessor_getter(core, session, me_proto, name, fn_ptr);
bind_accessor_getter(env, me_proto, name, fn_ptr);
}
}
@@ -277,7 +273,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
2,
);
bind_constructor!(
core,
env,
global,
"ErrorEvent",
ee_ctor_ptr,
@@ -311,7 +307,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
for (name, fn_ptr) in ee_getter_fns {
let si = sf.intern(name).0;
if sh.lookup_position(ee_proto.shape_id(), si).is_none() {
bind_accessor_getter(core, session, ee_proto, name, fn_ptr);
bind_accessor_getter(env, ee_proto, name, fn_ptr);
}
}
@@ -349,7 +345,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
2,
);
bind_constructor!(
core,
env,
global,
"CustomEvent",
ce_ctor_ptr,
@@ -374,7 +370,7 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
for (name, fn_ptr) in ce_getter_fns {
let si = sf.intern(name).0;
if sh.lookup_position(ce_proto.shape_id(), si).is_none() {
bind_accessor_getter(core, session, ce_proto, name, fn_ptr);
bind_accessor_getter(env, ce_proto, name, fn_ptr);
}
}
@@ -390,9 +386,8 @@ pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_add = sf.intern("addEventListener").0;
if sh.lookup_position(et_proto.shape_id(), si_add).is_none() {
apply_binding_table(
world,
env,
et_proto,
core,
&[
(
"addEventListener",
+21 -24
View File
@@ -1,7 +1,4 @@
use std::sync::Arc;
use oxide_kernel::builtin::{FnWrapperKey, FunctionMethods};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
@@ -9,12 +6,13 @@ use oxide_types::value::JsValue;
use super::apply_binding_table;
use super::bind_global_value;
use super::configure_native_constructor;
use super::BindEnv;
/// 把 Function 构造器与原型方法绑定到 global。
///
/// `realm_id` 是目标所属 realm 的编号:`@@hasInstance` 符号键按 (realm 编号,
/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
pub fn bind_function(env: BindEnv<'_>, global: &mut JsObject) {
let function_methods = FunctionMethods {
call: oxide_builtins::function::function_call::<crate::vm::Vm> as *const (),
apply: oxide_builtins::function::function_apply::<crate::vm::Vm> as *const (),
@@ -22,14 +20,14 @@ pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &m
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 (),
};
session.builtin_world().bind_function_methods(
env.world().bind_function_methods(
&function_methods,
core.perm_interner().as_ref(),
core.shape_forge().as_ref(),
realm_id,
env.string_forge(),
env.shape_forge(),
env.realm_id,
);
let function_ctor = session.builtin_world().function_constructor.as_ptr() as *mut JsObject;
let function_ctor = env.world().function_constructor.as_ptr() as *mut JsObject;
configure_native_constructor(
unsafe { &mut *function_ctor },
oxide_builtins::function::function_constructor::<crate::vm::Vm> as *const (),
@@ -37,8 +35,8 @@ pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &m
);
// 设置 Function.length = 1(configure_native_constructor 不写 length 属性),
// 属性为不可写不可枚举可配置。
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(unsafe { &*function_ctor }.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(unsafe { &*function_ctor }.shape_id(), length_si);
let ctor = unsafe { &mut *function_ctor };
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push(JsValue::int(1));
@@ -47,36 +45,35 @@ pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &m
// Function.prototype 自身属性:length = 0、name = ""(不可写不可枚举可配置),
// 自身属性名序 length 在 name 之前。
let proto_ptr = session.builtin_world().function_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().function_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let proto_length_shape = core.shape_forge().make_shape(proto.shape_id(), length_si);
let proto_length_shape = env.shape_forge().make_shape(proto.shape_id(), length_si);
proto.set_shape_id(proto_length_shape);
proto.ensure_hash_props().push(JsValue::int(0));
let proto_length_pos = proto.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
proto.set_data_meta(proto_length_pos, PropAttributes::new(false, false, true));
let name_si = core.perm_interner().intern("name").0;
let name_shape = core.shape_forge().make_shape(proto.shape_id(), name_si);
let name_si = env.string_forge().intern("name").0;
let name_shape = env.shape_forge().make_shape(proto.shape_id(), name_si);
proto.set_shape_id(name_shape);
proto
.ensure_hash_props()
.push(JsValue::perm_string(core.perm_interner().string_ptr(core.perm_interner().intern("").0)));
.push(JsValue::perm_string(env.string_forge().string_ptr(env.string_forge().intern("").0)));
let name_pos = proto.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
proto.set_data_meta(name_pos, PropAttributes::new(false, false, true));
// caller/arguments 受限访问器:两属性 get/set 共用同一 %ThrowTypeError%
// 函数对象,任何访问抛 TypeError(AddRestrictedFunctionProperties 语义)。
bind_function_proto_restricted(core, session, proto);
bind_function_proto_restricted(env, proto);
// toSource 遗留扩展(Function 原型方法不走 kernel 侧 bind_function_methods,
// 此处独立经 apply_binding_table 安装,描述符非枚举由绑定器内置)。
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[("toSource", oxide_builtins::to_source::to_source_function::<crate::vm::Vm> as *const (), 0)],
);
bind_global_value(core, global, "Function", JsValue::from_js_object(function_ctor));
bind_global_value(env.core, global, "Function", JsValue::from_js_object(function_ctor));
}
/// 在 Function.prototype 上绑定 caller/arguments 受限访问器:两属性的
@@ -92,10 +89,10 @@ pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &m
/// # 副作用
/// - 为 caller/arguments 各开 shape 槽位并写入访问器 meta;thrower 函数对象
/// 登记进 world 释放表(与 `bind_accessor_getter` 的 getter 同一生命周期)。
fn bind_function_proto_restricted(core: &Arc<KernelCore>, session: &KernelSession, proto: &mut JsObject) {
let shape_forge = core.shape_forge().as_ref();
let string_forge = core.perm_interner().as_ref();
let world = session.builtin_world();
fn bind_function_proto_restricted(env: BindEnv<'_>, proto: &mut JsObject) {
let shape_forge = env.shape_forge();
let string_forge = env.string_forge();
let world = env.world();
let family = world.wrapper_family_of(proto as *const JsObject);
let si_name = string_forge.intern("name").0;
let si_length = string_forge.intern("length").0;
+3 -7
View File
@@ -1,16 +1,12 @@
use std::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
use crate::bindings::apply_binding_table;
use crate::bindings::{apply_binding_table, BindEnv};
/// 把普通全局函数(`isNaN`、`parseInt`、`decodeURIComponent` 等)绑定到 global。
pub fn bind_global(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
pub fn bind_global(env: BindEnv<'_>, global: &mut JsObject) {
apply_binding_table(
session.builtin_world(),
env,
global,
core,
&[
("escape", oxide_builtins::global::js_escape::<crate::vm::Vm> as *const (), 1),
("unescape", oxide_builtins::global::js_unescape::<crate::vm::Vm> as *const (), 1),
+8 -12
View File
@@ -1,13 +1,10 @@
use std::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
use crate::bindings::{
apply_binding_table, bind_global_value, bind_iterator_ctor_identity, bind_iterator_function_prototype,
configure_native_constructor,
configure_native_constructor, BindEnv,
};
/// 绑定 `Iterator` 全局构造器(`prototype` = %IteratorPrototype%、`from` 方法)。
@@ -15,8 +12,8 @@ use crate::bindings::{
/// 迭代器原型方法(%IteratorPrototype% 的 `@@iterator` 与各集合原型 `next`)由
/// `rebind_dirty_builtins` 的 object 分支统一安装,本入口不重复绑定,避免
/// 保留原型经 dirty reset 时属性槽膨胀。
pub fn bind_iterator(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let function_proto = session.builtin_world().function_proto.as_ptr() as *mut JsObject;
pub fn bind_iterator(env: BindEnv<'_>, global: &mut JsObject) {
let function_proto = env.world().function_proto.as_ptr() as *mut JsObject;
let mut iterator = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(function_proto)));
iterator.set_function(true);
configure_native_constructor(
@@ -24,18 +21,17 @@ pub fn bind_iterator(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::iterator::iterator_constructor::<crate::vm::Vm> as *const (),
0,
);
bind_iterator_ctor_identity(core, &mut iterator);
bind_iterator_function_prototype(core, session, &mut iterator);
bind_iterator_ctor_identity(env.core, &mut iterator);
bind_iterator_function_prototype(env, &mut iterator);
apply_binding_table(
session.builtin_world(),
env,
&mut iterator,
core,
&[("from", oxide_builtins::iterator::iterator_from::<crate::vm::Vm> as *const (), 1)],
);
let iterator_ptr = Box::into_raw(iterator);
// 登记进 world 释放表:session 收尾统一释放构造器本体与属性区。
session.builtin_world().track_leaked_object(iterator_ptr);
bind_global_value(core, global, "Iterator", JsValue::from_js_object(iterator_ptr));
env.world().track_leaked_object(iterator_ptr);
bind_global_value(env.core, global, "Iterator", JsValue::from_js_object(iterator_ptr));
}
+6 -10
View File
@@ -1,19 +1,15 @@
use std::sync::Arc;
use crate::bindings::{apply_binding_table, bind_global_value};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_global_value, BindEnv};
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
/// 把 JSON 单例对象及其方法(parse/stringify 等)绑定到 global。
pub fn bind_json(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let json_ptr = session.builtin_world().json_object.as_ptr() as *mut JsObject;
pub fn bind_json(env: BindEnv<'_>, global: &mut JsObject) {
let json_ptr = env.world().json_object.as_ptr() as *mut JsObject;
let json = unsafe { &mut *json_ptr };
apply_binding_table(
session.builtin_world(),
env,
json,
core,
&[
("parse", oxide_builtins::json::json_parse::<crate::vm::Vm> as *const (), 2),
("stringify", oxide_builtins::json::json_stringify::<crate::vm::Vm> as *const (), 3),
@@ -23,9 +19,9 @@ pub fn bind_json(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
);
bind_global_value(
core,
env.core,
global,
"JSON",
JsValue::from_js_object(session.builtin_world().json_object.as_ptr() as *mut JsObject),
JsValue::from_js_object(env.world().json_object.as_ptr() as *mut JsObject),
);
}
+11 -17
View File
@@ -1,30 +1,26 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_accessor_getter_key, bind_well_known_method_alias,
configure_native_constructor,
configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
/// 把 Map 构造器与原型方法绑定到 global。
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_map(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let ctor_ptr = session.builtin_world().map_constructor.as_ptr() as *mut JsObject;
pub fn bind_map(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().map_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().map_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().map_proto.as_ptr() as *mut JsObject;
configure_native_constructor(ctor, oxide_builtins::map::map_constructor::<crate::vm::Vm> as *const (), 1);
let proto = unsafe { &mut *proto_ptr };
// size 是访问器 getter,不进 apply_binding_table。
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("set", oxide_builtins::map::map_set::<crate::vm::Vm> as *const (), 2),
("get", oxide_builtins::map::map_get::<crate::vm::Vm> as *const (), 1),
@@ -45,27 +41,25 @@ pub fn bind_map(core: &Arc<KernelCore>, session: &KernelSession, global: &mut Js
);
// Map 的 @@iterator(Symbol.iterator)是 entries 的同一函数对象。
bind_well_known_method_alias(core, proto, "entries", 0, realm_id);
bind_accessor_getter(core, session, proto, "size", oxide_builtins::map::map_size::<crate::vm::Vm> as *const ());
bind_well_known_method_alias(env.core, proto, "entries", 0, env.realm_id);
bind_accessor_getter(env, proto, "size", oxide_builtins::map::map_size::<crate::vm::Vm> as *const ());
// Map[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析
// @@species 得自身构造器(规范不给 class 默认 static @@species,类上无 own)。
bind_accessor_getter_key(
core,
session,
env,
ctor,
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
"get [Symbol.species]",
oxide_builtins::array::array_species_get::<crate::vm::Vm> as *const (),
);
// Map.groupBy 静态方法。
apply_binding_table(
session.builtin_world(),
env,
ctor,
core,
&[("groupBy", oxide_builtins::map::map_group_by::<crate::vm::Vm> as *const (), 2)],
);
bind_constructor!(core, global, "Map", ctor_ptr, oxide_builtins::map::map_constructor::<crate::vm::Vm>, 0, hash: true);
bind_constructor!(env, global, "Map", ctor_ptr, oxide_builtins::map::map_constructor::<crate::vm::Vm>, 0, hash: true);
}
+13 -14
View File
@@ -1,18 +1,17 @@
use std::sync::Arc;
use oxide_kernel::bind_methods;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
use crate::bindings::BindEnv;
/// 把 Math 单例对象及其方法(abs/floor/max/random 等)绑定到 global。
pub fn bind_math(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let math_ptr = session.builtin_world().math_object.as_ptr() as *mut JsObject;
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 = session.builtin_world();
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let bw = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
bind_methods!(
bw,
@@ -68,8 +67,8 @@ pub fn bind_math(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
("SQRT1_2", std::f64::consts::FRAC_1_SQRT_2),
("SQRT2", std::f64::consts::SQRT_2),
] {
let si = core.perm_interner().as_ref().intern(name).0;
let sh_c = core.shape_forge().as_ref().make_shape(math.shape_id(), si);
let si = env.string_forge().intern(name).0;
let sh_c = env.shape_forge().make_shape(math.shape_id(), si);
math.set_shape_id(sh_c);
math.ensure_hash_props().push(JsValue::float(val));
// Math 常量描述符:{ writable:false, enumerable:false, configurable:false },
@@ -80,12 +79,12 @@ pub fn bind_math(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
// 全局 Math 槽位既有槽原位更新(旧对象指针不得滞留在属性 vec),无槽时
// 开新槽;描述符非枚举(规范全局命名空间对象属性均 enumerable:false)。
let si_m = core.perm_interner().intern("Math").0;
let m_val = JsValue::from_js_object(session.builtin_world().math_object.as_ptr() as *mut JsObject);
if let Some(pos) = core.shape_forge().lookup_position(global.shape_id(), si_m) {
let si_m = env.string_forge().intern("Math").0;
let m_val = JsValue::from_js_object(env.world().math_object.as_ptr() as *mut JsObject);
if let Some(pos) = env.shape_forge().lookup_position(global.shape_id(), si_m) {
global.set_prop_at(pos, m_val);
} else {
let m_shape = core.shape_forge().make_shape(global.shape_id(), si_m);
let m_shape = env.shape_forge().make_shape(global.shape_id(), si_m);
global.set_shape_id(m_shape);
global.ensure_hash_props().push(m_val);
let pos = global.prop_vec_len().saturating_sub(1) as u32;
@@ -1,8 +1,7 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, bind_accessor_getset, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{
apply_binding_table, bind_accessor_getset, bind_accessor_getter, configure_native_constructor, BindEnv,
};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -20,15 +19,15 @@ use oxide_types::value::JsValue;
///
/// `realm_id` 未使用(MessageChannel 无 well-known 符号键),保留签名与其他
/// 绑定函数一致。
pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, _realm_id: u32) {
let world = session.builtin_world();
pub fn bind_message_channel(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let ctor_ptr = world.message_channel_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = world.message_port_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let sf = env.string_forge();
let sh = env.shape_forge();
// ---- 填构造器占位 ----
ctor.set_function(true);
@@ -65,7 +64,7 @@ pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, glo
0,
);
bind_constructor!(
core,
env,
global,
"MessageChannel",
ctor_ptr,
@@ -93,9 +92,8 @@ pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, glo
let si_post_message = sf.intern("postMessage").0;
if sh.lookup_position(proto.shape_id(), si_post_message).is_none() {
apply_binding_table(
world,
env,
proto,
core,
&[
(
"postMessage",
@@ -120,8 +118,7 @@ pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, glo
let si_ready_state = sf.intern("readyState").0;
if sh.lookup_position(proto.shape_id(), si_ready_state).is_none() {
bind_accessor_getter(
core,
session,
env,
proto,
"readyState",
oxide_builtins::message_channel::message_port_ready_state::<crate::vm::Vm> as *const (),
@@ -134,8 +131,7 @@ pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, glo
let key = sf.intern(name).0;
if sh.lookup_position(proto.shape_id(), key).is_none() {
bind_accessor_getset(
core,
session,
env,
proto,
key,
&format!("get {name}"),
+13 -19
View File
@@ -1,24 +1,20 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, configure_native_constructor, BindEnv};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// 把 Number 构造器与原型方法绑定到 global(含 NaN/POSITIVE_INFINITY 等常量)。
pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let ctor_ptr = session.builtin_world().number_constructor.as_ptr() as *mut JsObject;
pub fn bind_number(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().number_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().number_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().number_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(ctor, oxide_builtins::number::number_constructor::<crate::vm::Vm> as *const (), 1);
apply_binding_table(
session.builtin_world(),
env,
ctor,
core,
&[
("isNaN", oxide_builtins::number::number_is_nan::<crate::vm::Vm> as *const (), 1),
("isFinite", oxide_builtins::number::number_is_finite::<crate::vm::Vm> as *const (), 1),
@@ -35,9 +31,8 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("toString", oxide_builtins::number::number_to_string::<crate::vm::Vm> as *const (), 1),
("toFixed", oxide_builtins::number::number_to_fixed::<crate::vm::Vm> as *const (), 1),
@@ -75,18 +70,17 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
] {
ctor.ensure_hash_props().push(value);
let pos = ctor.ensure_hash_props().len() - 1;
let prop_si = core.perm_interner().intern(name).0;
let next_shape = core.shape_forge().make_shape(ctor.shape_id(), prop_si);
let prop_si = env.string_forge().intern(name).0;
let next_shape = env.shape_forge().make_shape(ctor.shape_id(), prop_si);
ctor.set_shape_id(next_shape);
ctor.set_data_meta(pos, PropAttributes::new(false, false, false));
}
bind_constructor!(core, global, "Number", ctor_ptr, oxide_builtins::number::number_constructor::<crate::vm::Vm>, 1, hash: true);
bind_constructor!(env, global, "Number", ctor_ptr, oxide_builtins::number::number_constructor::<crate::vm::Vm>, 1, hash: true);
apply_binding_table(
session.builtin_world(),
env,
global,
core,
&[
// parseInt 形式参数为 (string, radix),length 按规范取 2。
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 2),
@@ -100,10 +94,10 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// 是同一函数对象(SameValue)。ctor 侧绑定先执行、产生独立 wrapper,
// 此处把 global 侧 wrapper 值原位写回 ctor 同名槽,描述符形态不变。
for name in ["parseInt", "parseFloat"] {
let si = core.perm_interner().intern(name).0;
if let Some(global_pos) = core.shape_forge().lookup_position(global.shape_id(), si) {
let si = env.string_forge().intern(name).0;
if let Some(global_pos) = env.shape_forge().lookup_position(global.shape_id(), si) {
let val = global.get_prop_at(global_pos);
if let Some(ctor_pos) = core.shape_forge().lookup_position(ctor.shape_id(), si) {
if let Some(ctor_pos) = env.shape_forge().lookup_position(ctor.shape_id(), si) {
ctor.set_prop_at(ctor_pos, val);
}
}
+10 -15
View File
@@ -1,14 +1,11 @@
use std::sync::Arc;
use oxide_kernel::builtin::ObjectMethods;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use crate::bind_constructor;
use crate::bindings::apply_binding_table;
use crate::bindings::{apply_binding_table, BindEnv};
/// 把 Object 构造器与原型方法绑定到 global。
pub fn bind_object(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
pub fn bind_object(env: BindEnv<'_>, global: &mut JsObject) {
let methods = ObjectMethods {
keys: oxide_builtins::object::object_keys::<crate::vm::Vm> as *const (),
create: oxide_builtins::object::object_create::<crate::vm::Vm> as *const (),
@@ -39,16 +36,14 @@ pub fn bind_object(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
as *const (),
group_by: oxide_builtins::object::object_group_by::<crate::vm::Vm> as *const (),
};
session
.builtin_world()
.bind_object_methods(&methods, core.perm_interner().as_ref(), core.shape_forge().as_ref());
env.world()
.bind_object_methods(&methods, env.string_forge(), env.shape_forge());
let object_proto_ptr = session.builtin_world().object_proto.as_ptr() as *mut JsObject;
let object_proto_ptr = env.world().object_proto.as_ptr() as *mut JsObject;
let object_proto = unsafe { &mut *object_proto_ptr };
apply_binding_table(
session.builtin_world(),
env,
object_proto,
core,
&[
(
"toString",
@@ -101,15 +96,15 @@ pub fn bind_object(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
"__lookupSetter__",
"toSource",
] {
let si = core.perm_interner().intern(name).0;
if let Some(pos) = core.shape_forge().lookup_position(object_proto.shape_id(), si) {
let si = env.string_forge().intern(name).0;
if let Some(pos) = env.shape_forge().lookup_position(object_proto.shape_id(), si) {
object_proto.set_data_meta(pos, PropAttributes::new(true, false, true));
}
}
let ctor_ptr = session.builtin_world().object_constructor.as_ptr() as *mut JsObject;
let ctor_ptr = env.world().object_constructor.as_ptr() as *mut JsObject;
bind_constructor!(
core,
env,
global,
"Object",
ctor_ptr,
+6 -10
View File
@@ -1,22 +1,18 @@
use std::sync::Arc;
use crate::bindings::{apply_binding_table, bind_global_value};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_global_value, BindEnv};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
/// 把 Reflect 单例对象及其方法(get/set/construct/defineProperty 等)绑定到 global。
pub fn bind_reflect(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
pub fn bind_reflect(env: BindEnv<'_>, global: &mut JsObject) {
let mut reflect = Box::new(JsObject::new_empty(
EMPTY_SHAPE_ID,
JsValue::from_js_object(session.builtin_world().object_proto.as_ptr() as *mut JsObject),
JsValue::from_js_object(env.world().object_proto.as_ptr() as *mut JsObject),
));
apply_binding_table(
session.builtin_world(),
env,
&mut reflect,
core,
&[
("apply", oxide_builtins::reflect::reflect_apply::<crate::vm::Vm> as *const (), 3),
("construct", oxide_builtins::reflect::reflect_construct::<crate::vm::Vm> as *const (), 2),
@@ -64,6 +60,6 @@ pub fn bind_reflect(core: &Arc<KernelCore>, session: &KernelSession, global: &mu
let reflect_ptr = Box::into_raw(reflect);
// 登记进 world 释放表:session 收尾统一释放对象本体与属性区。
session.builtin_world().track_leaked_object(reflect_ptr);
bind_global_value(core, global, "Reflect", JsValue::from_js_object(reflect_ptr));
env.world().track_leaked_object(reflect_ptr);
bind_global_value(env.core, global, "Reflect", JsValue::from_js_object(reflect_ptr));
}
+27 -54
View File
@@ -1,10 +1,7 @@
use std::sync::Arc;
use crate::bindings::{
apply_binding_table, bind_accessor_getset, bind_accessor_getter, bind_accessor_getter_key, bind_well_known_method,
configure_native_constructor,
configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
use crate::bind_constructor;
@@ -13,26 +10,24 @@ use crate::bind_constructor;
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_regexp(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let ctor_ptr = session.builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
pub fn bind_regexp(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().regexp_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().regexp_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().regexp_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(ctor, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm> as *const (), 2);
// 静态方法 escape 装到构造器对象(wrapper 的 length/name 与槽属性由 bind_method 统一保证)。
apply_binding_table(
session.builtin_world(),
env,
ctor,
core,
&[("escape", oxide_builtins::regexp::regexp_escape::<crate::vm::Vm> as *const (), 1)],
);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("exec", oxide_builtins::regexp::regexp_exec::<crate::vm::Vm> as *const (), 1),
("test", oxide_builtins::regexp::regexp_test::<crate::vm::Vm> as *const (), 1),
@@ -47,10 +42,10 @@ pub fn bind_regexp(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// [[RegExpInput]] 槽);其余 18 个为 getter(set 恒 undefined):lastMatch/$&、
// lastParen/$+、leftContext/$`、rightContext/$' 各共享一槽,index 与 $1-$9 各
// 独占一槽。
let sf = core.perm_interner().as_ref();
let sf = env.string_forge();
let mut bind_getset = |name: &str, getter: *const (), setter: *const ()| {
let key = sf.intern(name).0;
bind_accessor_getset(core, session, ctor, key, &format!("get {name}"), &format!("set {name}"), getter, setter);
bind_accessor_getset(env, ctor, key, &format!("get {name}"), &format!("set {name}"), getter, setter);
};
// input/$_:get+set 对(唯一带 setter 的遗留访问器)。
bind_getset(
@@ -99,20 +94,18 @@ pub fn bind_regexp(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
("$8", oxide_builtins::regexp::regexp_legacy_get_dollar_8::<crate::vm::Vm> as *const ()),
("$9", oxide_builtins::regexp::regexp_legacy_get_dollar_9::<crate::vm::Vm> as *const ()),
] {
bind_accessor_getter(core, session, ctor, name, getter);
bind_accessor_getter(env, ctor, name, getter);
}
// source/flags 只读访问器(set 恒 undefined,getter 读实例字段)。
bind_accessor_getter(
core,
session,
env,
proto,
"source",
oxide_builtins::regexp::regexp_get_source::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"flags",
oxide_builtins::regexp::regexp_get_flags::<crate::vm::Vm> as *const (),
@@ -120,125 +113,105 @@ pub fn bind_regexp(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// 8 个单 flag 只读访问器(set 恒 undefined,getter 读实例 flags 串判码元)。
bind_accessor_getter(
core,
session,
env,
proto,
"global",
oxide_builtins::regexp::regexp_get_global::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"ignoreCase",
oxide_builtins::regexp::regexp_get_ignore_case::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"multiline",
oxide_builtins::regexp::regexp_get_multiline::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"dotAll",
oxide_builtins::regexp::regexp_get_dot_all::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"sticky",
oxide_builtins::regexp::regexp_get_sticky::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"unicode",
oxide_builtins::regexp::regexp_get_unicode::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"hasIndices",
oxide_builtins::regexp::regexp_get_has_indices::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"unicodeSets",
oxide_builtins::regexp::regexp_get_unicode_sets::<crate::vm::Vm> as *const (),
);
// well-known symbol 方法按 Symbol 键安装,name 属性取 `[Symbol.match]` 式标签,供 `re[Symbol.match]` 等读取。
let world = session.builtin_world();
bind_well_known_method(
world,
core,
env,
proto,
1,
"[Symbol.match]",
oxide_builtins::regexp::regexp_symbol_match::<crate::vm::Vm> as *const (),
1,
realm_id,
);
bind_well_known_method(
world,
core,
env,
proto,
2,
"[Symbol.replace]",
oxide_builtins::regexp::regexp_symbol_replace::<crate::vm::Vm> as *const (),
2,
realm_id,
);
bind_well_known_method(
world,
core,
env,
proto,
3,
"[Symbol.search]",
oxide_builtins::regexp::regexp_symbol_search::<crate::vm::Vm> as *const (),
1,
realm_id,
);
bind_well_known_method(
world,
core,
env,
proto,
4,
"[Symbol.split]",
oxide_builtins::regexp::regexp_symbol_split::<crate::vm::Vm> as *const (),
2,
realm_id,
);
bind_well_known_method(
world,
core,
env,
proto,
7,
"[Symbol.matchAll]",
oxide_builtins::regexp::regexp_symbol_match_all::<crate::vm::Vm> as *const (),
1,
realm_id,
);
// RegExp[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析
// @@species 得自身构造器(规范不给 class 默认 static @@species,类上无 own)。
bind_accessor_getter_key(
core,
session,
env,
ctor,
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
"get [Symbol.species]",
oxide_builtins::array::array_species_get::<crate::vm::Vm> as *const (),
);
bind_constructor!(core, global, "RegExp", ctor_ptr, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm>, 2, hash: true);
bind_constructor!(env, global, "RegExp", ctor_ptr, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm>, 2, hash: true);
}
+11 -16
View File
@@ -1,30 +1,26 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_accessor_getter_key, bind_method_alias,
bind_well_known_method_alias, configure_native_constructor,
bind_well_known_method_alias, configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
/// 把 Set 构造器与原型方法绑定到 global。
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_set(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let ctor_ptr = session.builtin_world().set_constructor.as_ptr() as *mut JsObject;
pub fn bind_set(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().set_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().set_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().set_proto.as_ptr() as *mut JsObject;
configure_native_constructor(ctor, oxide_builtins::set::set_constructor::<crate::vm::Vm> as *const (), 1);
let proto = unsafe { &mut *proto_ptr };
// size 是访问器 getter,不进 apply_binding_table。
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("add", oxide_builtins::set::set_add::<crate::vm::Vm> as *const (), 1),
("has", oxide_builtins::set::set_has::<crate::vm::Vm> as *const (), 1),
@@ -52,20 +48,19 @@ pub fn bind_set(core: &Arc<KernelCore>, session: &KernelSession, global: &mut Js
);
// keys 与 @@iterator(Symbol.iterator)是 values 的同一函数对象。
bind_method_alias(core, proto, "values", "keys");
bind_well_known_method_alias(core, proto, "values", 0, realm_id);
bind_accessor_getter(core, session, proto, "size", oxide_builtins::set::set_size::<crate::vm::Vm> as *const ());
bind_method_alias(env.core, proto, "values", "keys");
bind_well_known_method_alias(env.core, proto, "values", 0, env.realm_id);
bind_accessor_getter(env, proto, "size", oxide_builtins::set::set_size::<crate::vm::Vm> as *const ());
// Set[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析
// @@species 得自身构造器(规范不给 class 默认 static @@species,类上无 own)。
bind_accessor_getter_key(
core,
session,
env,
ctor,
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
"get [Symbol.species]",
oxide_builtins::array::array_species_get::<crate::vm::Vm> as *const (),
);
bind_constructor!(core, global, "Set", ctor_ptr, oxide_builtins::set::set_constructor::<crate::vm::Vm>, 0, hash: true);
bind_constructor!(env, global, "Set", ctor_ptr, oxide_builtins::set::set_constructor::<crate::vm::Vm>, 0, hash: true);
}
@@ -1,15 +1,12 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor, BindEnv};
use oxide_types::object::JsObject;
/// 把 SharedArrayBuffer 构造器与原型访问器绑定到 global。
pub fn bind_shared_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let ctor_ptr = session.builtin_world().shared_array_buffer_constructor.as_ptr() as *mut JsObject;
pub fn bind_shared_array_buffer(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().shared_array_buffer_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().shared_array_buffer_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().shared_array_buffer_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(
@@ -21,9 +18,8 @@ pub fn bind_shared_array_buffer(core: &Arc<KernelCore>, session: &KernelSession,
// grow/slice 方法:grow 原地增长(只增不缩);slice 复制字节区间生成
// 新 SAB。
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
(
"grow",
@@ -41,16 +37,14 @@ pub fn bind_shared_array_buffer(core: &Arc<KernelCore>, session: &KernelSession,
// byteLength/maxByteLength 两枚访问器(set 恒 undefined)读载荷字节数 /
// 存储态上限,品牌校验抛 TypeError(proto 自身访问即抛)。
bind_accessor_getter(
core,
session,
env,
proto,
"byteLength",
oxide_builtins::array_buffer::shared_array_buffer_byte_length::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
proto,
"maxByteLength",
oxide_builtins::array_buffer::shared_array_buffer_max_byte_length::<crate::vm::Vm> as *const (),
@@ -58,15 +52,14 @@ pub fn bind_shared_array_buffer(core: &Arc<KernelCore>, session: &KernelSession,
// growable 真值臂:读载荷存储态上限(0 定长 false / 非 0 growable true)。
bind_accessor_getter(
core,
session,
env,
proto,
"growable",
oxide_builtins::array_buffer::shared_array_buffer_growable::<crate::vm::Vm> as *const (),
);
bind_constructor!(
core,
env,
global,
"SharedArrayBuffer",
ctor_ptr,
+18 -25
View File
@@ -1,8 +1,5 @@
use std::sync::Arc;
use crate::bindings::{apply_binding_table, configure_native_constructor};
use crate::bindings::{apply_binding_table, configure_native_constructor, BindEnv};
use oxide_kernel::builtin::StringMethods;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -10,7 +7,7 @@ use oxide_types::value::JsValue;
///
/// `realm_id` 是目标所属 realm 的编号:`@@iterator` 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
pub fn bind_string(env: BindEnv<'_>, global: &mut JsObject) {
let string_methods = StringMethods {
from_char_code: oxide_builtins::string::string_from_char_code::<crate::vm::Vm> as *const (),
index_of: oxide_builtins::string::string_index_of::<crate::vm::Vm> as *const (),
@@ -63,29 +60,28 @@ pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
sub: oxide_builtins::string::string_sub::<crate::vm::Vm> as *const (),
sup: oxide_builtins::string::string_sup::<crate::vm::Vm> as *const (),
};
session.builtin_world().bind_string_methods(
env.world().bind_string_methods(
&string_methods,
core.perm_interner().as_ref(),
core.shape_forge().as_ref(),
env.string_forge(),
env.shape_forge(),
);
let ctor_ptr = session.builtin_world().string_constructor.as_ptr() as *mut JsObject;
let ctor_ptr = env.world().string_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
configure_native_constructor(ctor, oxide_builtins::string::string_constructor::<crate::vm::Vm> as *const (), 1);
// String.length = 1,描述符 { writable:false, enumerable:false, configurable:true }。
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(ctor.shape_id(), length_si);
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push(JsValue::int(1));
let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
let proto_ptr = session.builtin_world().string_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().string_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("toString", oxide_builtins::string::string_to_string::<crate::vm::Vm> as *const (), 0),
("toSource", oxide_builtins::to_source::to_source_string::<crate::vm::Vm> as *const (), 0),
@@ -94,23 +90,20 @@ pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// String.prototype[@@iterator]:逐 code point 迭代字符;name 属性按规范
// 落 "[Symbol.iterator]"。
super::bind_well_known_method(
session.builtin_world(),
core,
env,
proto,
0,
"[Symbol.iterator]",
oxide_builtins::string::string_symbol_iterator::<crate::vm::Vm> as *const (),
0,
realm_id,
);
// 捕获默认迭代器函数对象指针写入 world:String 臂覆盖判定以此做指针比较。
// 此时槽为初始数据属性(用户覆盖尚未可能),读回即默认函数本体。
let iter_key = oxide_types::private_key::encode_symbol_key(realm_id, 0);
if let Some(pos) = core.shape_forge().lookup_position(proto.shape_id(), iter_key) {
let iter_key = oxide_types::private_key::encode_symbol_key(env.realm_id, 0);
if let Some(pos) = env.shape_forge().lookup_position(proto.shape_id(), iter_key) {
let v = proto.get_prop_at(pos);
if v.is_object() {
session
.builtin_world()
env.world()
.string_default_iterator
.set(v.as_js_object_ptr() as *const JsObject);
}
@@ -118,12 +111,12 @@ pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// 全局 String 槽位既有槽原位更新(旧家族构造器指针不得滞留在属性 vec),
// 无槽时开新槽;描述符非枚举(规范 { writable:true, enumerable:false, configurable:true })。
let si_str = core.perm_interner().intern("String").0;
let str_val = JsValue::from_js_object(session.builtin_world().string_constructor.as_ptr() as *mut JsObject);
if let Some(pos) = core.shape_forge().lookup_position(global.shape_id(), si_str) {
let si_str = env.string_forge().intern("String").0;
let str_val = JsValue::from_js_object(env.world().string_constructor.as_ptr() as *mut JsObject);
if let Some(pos) = env.shape_forge().lookup_position(global.shape_id(), si_str) {
global.set_prop_at(pos, str_val);
} else {
let str_shape = core.shape_forge().make_shape(global.shape_id(), si_str);
let str_shape = env.shape_forge().make_shape(global.shape_id(), si_str);
global.set_shape_id(str_shape);
global.ensure_hash_props().push(str_val);
let pos = global.prop_vec_len().saturating_sub(1) as u32;
+15 -23
View File
@@ -1,9 +1,6 @@
use std::sync::Arc;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_well_known_method, configure_native_constructor,
apply_binding_table, bind_accessor_getter, bind_well_known_method, configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::private_key::{encode_symbol_key, WELL_KNOWN_SYMBOL_TO_PRIMITIVE};
use oxide_types::value::JsValue;
@@ -14,18 +11,17 @@ use crate::bind_constructor;
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let ctor_ptr = session.builtin_world().symbol_constructor.as_ptr() as *mut JsObject;
pub fn bind_symbol(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().symbol_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = session.builtin_world().symbol_proto.as_ptr() as *mut JsObject;
let proto_ptr = env.world().symbol_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(ctor, oxide_builtins::symbol::symbol_constructor::<crate::vm::Vm> as *const (), 1);
apply_binding_table(
session.builtin_world(),
env,
ctor,
core,
&[
("for", oxide_builtins::symbol::symbol_for::<crate::vm::Vm> as *const (), 1),
("keyFor", oxide_builtins::symbol::symbol_key_for::<crate::vm::Vm> as *const (), 1),
@@ -33,9 +29,8 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
);
apply_binding_table(
session.builtin_world(),
env,
proto,
core,
&[
("toString", oxide_builtins::symbol::symbol_to_string::<crate::vm::Vm> as *const (), 0),
("valueOf", oxide_builtins::symbol::symbol_value_of::<crate::vm::Vm> as *const (), 0),
@@ -44,8 +39,7 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// description 是访问器 getter(Symbol 原始值成员访问经 Symbol.prototype 链命中)。
bind_accessor_getter(
core,
session,
env,
proto,
"description",
oxide_builtins::symbol::symbol_description_getter::<crate::vm::Vm> as *const (),
@@ -53,17 +47,15 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// [Symbol.toPrimitive] 方法:bind 默认描述符可写,规范为不可写,绑定后改 meta。
bind_well_known_method(
session.builtin_world(),
core,
env,
proto,
WELL_KNOWN_SYMBOL_TO_PRIMITIVE,
"[Symbol.toPrimitive]",
oxide_builtins::symbol::symbol_to_primitive::<crate::vm::Vm> as *const (),
1,
realm_id,
);
let to_prim_key = encode_symbol_key(realm_id, WELL_KNOWN_SYMBOL_TO_PRIMITIVE);
if let Some(pos) = core.shape_forge().lookup_position(proto.shape_id(), to_prim_key) {
let to_prim_key = encode_symbol_key(env.realm_id, WELL_KNOWN_SYMBOL_TO_PRIMITIVE);
if let Some(pos) = env.shape_forge().lookup_position(proto.shape_id(), to_prim_key) {
proto.set_data_meta(pos, PropAttributes::new(false, false, true));
proto.bump_generation();
}
@@ -74,15 +66,15 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// 非零 realm 下与键物化值保持同一符号。
for (id, full_name) in oxide_types::private_key::WELL_KNOWN_SYMBOL_NAMES.iter().enumerate() {
let name = full_name.strip_prefix("Symbol.").unwrap_or(full_name);
bind_well_known_symbol(core, ctor, name, JsValue::symbol_realm(realm_id, id as u32));
bind_well_known_symbol(env, ctor, name, JsValue::symbol_realm(env.realm_id, id as u32));
}
bind_constructor!(core, global, "Symbol", ctor_ptr, oxide_builtins::symbol::symbol_constructor::<crate::vm::Vm>, 0, hash: true);
bind_constructor!(env, global, "Symbol", ctor_ptr, oxide_builtins::symbol::symbol_constructor::<crate::vm::Vm>, 0, hash: true);
}
fn bind_well_known_symbol(core: &Arc<KernelCore>, ctor: &mut JsObject, name: &str, val: JsValue) {
let si = core.perm_interner().intern(name).0;
let shape_id = core.shape_forge().make_shape(ctor.shape_id(), si);
fn bind_well_known_symbol(env: BindEnv<'_>, ctor: &mut JsObject, name: &str, val: JsValue) {
let si = env.string_forge().intern(name).0;
let shape_id = env.shape_forge().make_shape(ctor.shape_id(), si);
ctor.set_shape_id(shape_id);
ctor.ensure_hash_props().push(val);
// well-known symbol 属性按规范 { writable:false, enumerable:false, configurable:false }。
+134 -210
View File
@@ -1,10 +1,7 @@
use std::sync::Arc;
use crate::bindings::{
apply_binding_table, bind_accessor_getter, bind_global_value, bind_well_known_data_property,
configure_native_constructor,
configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -12,8 +9,8 @@ use oxide_types::value::JsValue;
///
/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号,
/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let world = session.builtin_world();
pub fn bind_temporal(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let temporal_ptr = world.temporal_object.as_ptr() as *mut JsObject;
let temporal = unsafe { &mut *temporal_ptr };
@@ -21,9 +18,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
let now_ptr = world.temporal_now_object.as_ptr() as *mut JsObject;
let now = unsafe { &mut *now_ptr };
apply_binding_table(
world,
env,
now,
core,
&[
("instant", oxide_builtins::temporal::now_instant::<crate::vm::Vm> as *const (), 0),
("timeZoneId", oxide_builtins::temporal::now_time_zone_id::<crate::vm::Vm> as *const (), 0),
@@ -38,8 +34,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::instant_constructor::<crate::vm::Vm> as *const (),
1,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(instant_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(instant_ctor.shape_id(), length_si);
instant_ctor.set_shape_id(length_shape);
instant_ctor.ensure_hash_props().push(JsValue::int(1));
let length_pos = instant_ctor
@@ -49,9 +45,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
instant_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
instant_ctor,
core,
&[
("from", oxide_builtins::temporal::instant_from::<crate::vm::Vm> as *const (), 1),
("compare", oxide_builtins::temporal::instant_compare::<crate::vm::Vm> as *const (), 2),
@@ -70,37 +65,32 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
let instant_proto_ptr = world.instant_proto.as_ptr() as *mut JsObject;
let instant_proto = unsafe { &mut *instant_proto_ptr };
bind_accessor_getter(
core,
session,
env,
instant_proto,
"epochSeconds",
oxide_builtins::temporal::instant_epoch_seconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
instant_proto,
"epochMilliseconds",
oxide_builtins::temporal::instant_epoch_milliseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
instant_proto,
"epochMicroseconds",
oxide_builtins::temporal::instant_epoch_microseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
instant_proto,
"epochNanoseconds",
oxide_builtins::temporal::instant_epoch_nanoseconds::<crate::vm::Vm> as *const (),
);
apply_binding_table(
world,
env,
instant_proto,
core,
&[
("add", oxide_builtins::temporal::instant_add::<crate::vm::Vm> as *const (), 1),
("equals", oxide_builtins::temporal::instant_equals::<crate::vm::Vm> as *const (), 1),
@@ -124,15 +114,15 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
],
);
bind_well_known_data_property(
core,
env.core,
instant_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.Instant").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.Instant").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
// Temporal.ZonedDateTime:最小构造器与三个稳定内部槽 getter。
@@ -143,8 +133,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::zoned_date_time_constructor::<crate::vm::Vm> as *const (),
2,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(zoned_date_time_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(zoned_date_time_ctor.shape_id(), length_si);
zoned_date_time_ctor.set_shape_id(length_shape);
zoned_date_time_ctor.ensure_hash_props().push(JsValue::int(2));
let length_pos = zoned_date_time_ctor
@@ -153,9 +143,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
.saturating_sub(1);
zoned_date_time_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
zoned_date_time_ctor,
core,
&[
("from", oxide_builtins::temporal::zoned_date_time_from::<crate::vm::Vm> as *const (), 1),
(
@@ -169,230 +158,199 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
let zoned_date_time_proto_ptr = world.zoned_date_time_proto.as_ptr() as *mut JsObject;
let zoned_date_time_proto = unsafe { &mut *zoned_date_time_proto_ptr };
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"epochNanoseconds",
oxide_builtins::temporal::zoned_date_time_epoch_nanoseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"timeZoneId",
oxide_builtins::temporal::zoned_date_time_time_zone_id::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"calendarId",
oxide_builtins::temporal::zoned_date_time_calendar_id::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"epochSeconds",
oxide_builtins::temporal::zoned_date_time_epoch_seconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"epochMilliseconds",
oxide_builtins::temporal::zoned_date_time_epoch_milliseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"epochMicroseconds",
oxide_builtins::temporal::zoned_date_time_epoch_microseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"offset",
oxide_builtins::temporal::zoned_date_time_offset::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"offsetNanoseconds",
oxide_builtins::temporal::zoned_date_time_offset_nanoseconds::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"year",
oxide_builtins::temporal::zoned_date_time_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"month",
oxide_builtins::temporal::zoned_date_time_month::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"day",
oxide_builtins::temporal::zoned_date_time_day::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"hour",
oxide_builtins::temporal::zoned_date_time_hour::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"minute",
oxide_builtins::temporal::zoned_date_time_minute::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"second",
oxide_builtins::temporal::zoned_date_time_second::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"millisecond",
oxide_builtins::temporal::zoned_date_time_millisecond::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"microsecond",
oxide_builtins::temporal::zoned_date_time_microsecond::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"nanosecond",
oxide_builtins::temporal::zoned_date_time_nanosecond::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"dayOfWeek",
oxide_builtins::temporal::zoned_date_time_day_of_week::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"dayOfYear",
oxide_builtins::temporal::zoned_date_time_day_of_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"weekOfYear",
oxide_builtins::temporal::zoned_date_time_week_of_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"yearOfWeek",
oxide_builtins::temporal::zoned_date_time_year_of_week::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"monthCode",
oxide_builtins::temporal::zoned_date_time_month_code::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"daysInMonth",
oxide_builtins::temporal::zoned_date_time_days_in_month::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"daysInWeek",
oxide_builtins::temporal::zoned_date_time_days_in_week::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"daysInYear",
oxide_builtins::temporal::zoned_date_time_days_in_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"monthsInYear",
oxide_builtins::temporal::zoned_date_time_months_in_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"inLeapYear",
oxide_builtins::temporal::zoned_date_time_in_leap_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"era",
oxide_builtins::temporal::zoned_date_time_era::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"eraYear",
oxide_builtins::temporal::zoned_date_time_era_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
zoned_date_time_proto,
"hoursInDay",
oxide_builtins::temporal::zoned_date_time_hours_in_day::<crate::vm::Vm> as *const (),
);
bind_well_known_data_property(
core,
env.core,
zoned_date_time_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.ZonedDateTime").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.ZonedDateTime").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
apply_binding_table(
world,
env,
zoned_date_time_proto,
core,
&[
(
"toJSON",
@@ -480,8 +438,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_date_constructor::<crate::vm::Vm> as *const (),
3,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(plain_date_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(plain_date_ctor.shape_id(), length_si);
plain_date_ctor.set_shape_id(length_shape);
plain_date_ctor.ensure_hash_props().push(JsValue::int(3));
let length_pos = plain_date_ctor
@@ -491,9 +449,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
plain_date_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
plain_date_ctor,
core,
&[
("from", oxide_builtins::temporal::plain_date_from::<crate::vm::Vm> as *const (), 1),
("compare", oxide_builtins::temporal::plain_date_compare::<crate::vm::Vm> as *const (), 2),
@@ -502,121 +459,104 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
let plain_date_proto_ptr = world.plain_date_proto.as_ptr() as *mut JsObject;
let plain_date_proto = unsafe { &mut *plain_date_proto_ptr };
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"year",
oxide_builtins::temporal::plain_date_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"month",
oxide_builtins::temporal::plain_date_month::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"day",
oxide_builtins::temporal::plain_date_day::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"dayOfWeek",
oxide_builtins::temporal::plain_date_day_of_week::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"dayOfYear",
oxide_builtins::temporal::plain_date_day_of_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"daysInMonth",
oxide_builtins::temporal::plain_date_days_in_month::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"daysInWeek",
oxide_builtins::temporal::plain_date_days_in_week::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"daysInYear",
oxide_builtins::temporal::plain_date_days_in_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"monthsInYear",
oxide_builtins::temporal::plain_date_months_in_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"inLeapYear",
oxide_builtins::temporal::plain_date_in_leap_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"weekOfYear",
oxide_builtins::temporal::plain_date_week_of_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"yearOfWeek",
oxide_builtins::temporal::plain_date_year_of_week::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"monthCode",
oxide_builtins::temporal::plain_date_month_code::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"era",
oxide_builtins::temporal::plain_date_era::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"eraYear",
oxide_builtins::temporal::plain_date_era_year::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_date_proto,
"calendarId",
oxide_builtins::temporal::plain_date_calendar_id::<crate::vm::Vm> as *const (),
);
apply_binding_table(
world,
env,
plain_date_proto,
core,
&[
(
"toString",
@@ -641,8 +581,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_time_constructor::<crate::vm::Vm> as *const (),
6,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(plain_time_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(plain_time_ctor.shape_id(), length_si);
plain_time_ctor.set_shape_id(length_shape);
plain_time_ctor.ensure_hash_props().push(JsValue::int(0));
let length_pos = plain_time_ctor
@@ -651,9 +591,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
.saturating_sub(1);
plain_time_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
plain_time_ctor,
core,
&[
("from", oxide_builtins::temporal::plain_time_from::<crate::vm::Vm> as *const (), 1),
("compare", oxide_builtins::temporal::plain_time_compare::<crate::vm::Vm> as *const (), 2),
@@ -663,51 +602,44 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
let plain_time_proto_ptr = world.plain_time_proto.as_ptr() as *mut JsObject;
let plain_time_proto = unsafe { &mut *plain_time_proto_ptr };
bind_accessor_getter(
core,
session,
env,
plain_time_proto,
"hour",
oxide_builtins::temporal::plain_time_hour::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_time_proto,
"minute",
oxide_builtins::temporal::plain_time_minute::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_time_proto,
"second",
oxide_builtins::temporal::plain_time_second::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_time_proto,
"millisecond",
oxide_builtins::temporal::plain_time_millisecond::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_time_proto,
"microsecond",
oxide_builtins::temporal::plain_time_microsecond::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
plain_time_proto,
"nanosecond",
oxide_builtins::temporal::plain_time_nanosecond::<crate::vm::Vm> as *const (),
);
apply_binding_table(
world,
env,
plain_time_proto,
core,
&[
(
"toString",
@@ -731,15 +663,15 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
],
);
bind_well_known_data_property(
core,
env.core,
plain_time_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.PlainTime").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.PlainTime").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
// Temporal.PlainDateTime:ISO 日期时间分量、拆分转换与禁止隐式原始值转换。
@@ -750,8 +682,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_date_time_constructor::<crate::vm::Vm> as *const (),
3,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(plain_date_time_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(plain_date_time_ctor.shape_id(), length_si);
plain_date_time_ctor.set_shape_id(length_shape);
plain_date_time_ctor.ensure_hash_props().push(JsValue::int(3));
let length_pos = plain_date_time_ctor
@@ -760,9 +692,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
.saturating_sub(1);
plain_date_time_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
plain_date_time_ctor,
core,
&[
("from", oxide_builtins::temporal::plain_date_time_from::<crate::vm::Vm> as *const (), 1),
(
@@ -843,12 +774,11 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_date_time_calendar_id::<crate::vm::Vm> as *const (),
),
] {
bind_accessor_getter(core, session, plain_date_time_proto, name, getter);
bind_accessor_getter(env, plain_date_time_proto, name, getter);
}
apply_binding_table(
world,
env,
plain_date_time_proto,
core,
&[
(
"toPlainDate",
@@ -891,15 +821,15 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
],
);
bind_well_known_data_property(
core,
env.core,
plain_date_time_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.PlainDateTime").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.PlainDateTime").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
// Temporal.Duration:构造器、from、分量 getter 与 ISO 字符串转换。
@@ -910,8 +840,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::duration_constructor::<crate::vm::Vm> as *const (),
10,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(duration_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(duration_ctor.shape_id(), length_si);
duration_ctor.set_shape_id(length_shape);
duration_ctor.ensure_hash_props().push(JsValue::int(0));
let length_pos = duration_ctor
@@ -921,9 +851,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
duration_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
duration_ctor,
core,
&[
("from", oxide_builtins::temporal::duration_from::<crate::vm::Vm> as *const (), 1),
("compare", oxide_builtins::temporal::duration_compare::<crate::vm::Vm> as *const (), 2),
@@ -954,12 +883,11 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
("sign", oxide_builtins::temporal::duration_sign::<crate::vm::Vm> as *const ()),
("blank", oxide_builtins::temporal::duration_blank::<crate::vm::Vm> as *const ()),
] {
bind_accessor_getter(core, session, duration_proto, name, getter);
bind_accessor_getter(env, duration_proto, name, getter);
}
apply_binding_table(
world,
env,
duration_proto,
core,
&[
("abs", oxide_builtins::temporal::duration_abs::<crate::vm::Vm> as *const (), 0),
("negated", oxide_builtins::temporal::duration_negated::<crate::vm::Vm> as *const (), 0),
@@ -980,15 +908,15 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
],
);
bind_well_known_data_property(
core,
env.core,
duration_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.Duration").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.Duration").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
// Temporal.PlainMonthDay:构造器、3 个分量 getter 与 toString/toJSON。
@@ -999,8 +927,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_month_day_constructor::<crate::vm::Vm> as *const (),
2,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(plain_month_day_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(plain_month_day_ctor.shape_id(), length_si);
plain_month_day_ctor.set_shape_id(length_shape);
plain_month_day_ctor.ensure_hash_props().push(JsValue::int(2));
let length_pos = plain_month_day_ctor
@@ -1009,9 +937,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
.saturating_sub(1);
plain_month_day_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
plain_month_day_ctor,
core,
&[("from", oxide_builtins::temporal::plain_month_day_from::<crate::vm::Vm> as *const (), 1)],
);
@@ -1028,12 +955,11 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_month_day_calendar_id::<crate::vm::Vm> as *const (),
),
] {
bind_accessor_getter(core, session, plain_month_day_proto, name, getter);
bind_accessor_getter(env, plain_month_day_proto, name, getter);
}
apply_binding_table(
world,
env,
plain_month_day_proto,
core,
&[
(
"toString",
@@ -1069,15 +995,15 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
],
);
bind_well_known_data_property(
core,
env.core,
plain_month_day_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.PlainMonthDay").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.PlainMonthDay").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
// Temporal.PlainYearMonth:构造器、10 个 getter 与 toString/toJSON。
@@ -1088,8 +1014,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_year_month_constructor::<crate::vm::Vm> as *const (),
2,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(plain_year_month_ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(plain_year_month_ctor.shape_id(), length_si);
plain_year_month_ctor.set_shape_id(length_shape);
plain_year_month_ctor.ensure_hash_props().push(JsValue::int(2));
let length_pos = plain_year_month_ctor
@@ -1098,9 +1024,8 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
.saturating_sub(1);
plain_year_month_ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
apply_binding_table(
world,
env,
plain_year_month_ctor,
core,
&[
("from", oxide_builtins::temporal::plain_year_month_from::<crate::vm::Vm> as *const (), 1),
(
@@ -1146,12 +1071,11 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
oxide_builtins::temporal::plain_year_month_era_year::<crate::vm::Vm> as *const (),
),
] {
bind_accessor_getter(core, session, plain_year_month_proto, name, getter);
bind_accessor_getter(env, plain_year_month_proto, name, getter);
}
apply_binding_table(
world,
env,
plain_year_month_proto,
core,
&[
(
"toString",
@@ -1195,26 +1119,26 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
],
);
bind_well_known_data_property(
core,
env.core,
plain_year_month_proto,
9,
JsValue::perm_string(
core.perm_interner()
.string_ptr(core.perm_interner().intern("Temporal.PlainYearMonth").0),
env.string_forge()
.string_ptr(env.string_forge().intern("Temporal.PlainYearMonth").0),
),
PropAttributes::new(false, false, true),
realm_id,
env.realm_id,
);
// 把子对象挂到 Temporal 命名空间对象上,再把 Temporal 挂到 global。
bind_global_value(core, temporal, "Now", JsValue::from_js_object(now_ptr));
bind_global_value(core, temporal, "Instant", JsValue::from_js_object(instant_ctor_ptr));
bind_global_value(core, temporal, "PlainDate", JsValue::from_js_object(plain_date_ctor_ptr));
bind_global_value(core, temporal, "PlainTime", JsValue::from_js_object(plain_time_ctor_ptr));
bind_global_value(core, temporal, "PlainDateTime", JsValue::from_js_object(plain_date_time_ctor_ptr));
bind_global_value(core, temporal, "Duration", JsValue::from_js_object(duration_ctor_ptr));
bind_global_value(core, temporal, "ZonedDateTime", JsValue::from_js_object(zoned_date_time_ctor_ptr));
bind_global_value(core, temporal, "PlainMonthDay", JsValue::from_js_object(plain_month_day_ctor_ptr));
bind_global_value(core, temporal, "PlainYearMonth", JsValue::from_js_object(plain_year_month_ctor_ptr));
bind_global_value(core, global, "Temporal", JsValue::from_js_object(temporal_ptr));
bind_global_value(env.core, temporal, "Now", JsValue::from_js_object(now_ptr));
bind_global_value(env.core, temporal, "Instant", JsValue::from_js_object(instant_ctor_ptr));
bind_global_value(env.core, temporal, "PlainDate", JsValue::from_js_object(plain_date_ctor_ptr));
bind_global_value(env.core, temporal, "PlainTime", JsValue::from_js_object(plain_time_ctor_ptr));
bind_global_value(env.core, temporal, "PlainDateTime", JsValue::from_js_object(plain_date_time_ctor_ptr));
bind_global_value(env.core, temporal, "Duration", JsValue::from_js_object(duration_ctor_ptr));
bind_global_value(env.core, temporal, "ZonedDateTime", JsValue::from_js_object(zoned_date_time_ctor_ptr));
bind_global_value(env.core, temporal, "PlainMonthDay", JsValue::from_js_object(plain_month_day_ctor_ptr));
bind_global_value(env.core, temporal, "PlainYearMonth", JsValue::from_js_object(plain_year_month_ctor_ptr));
bind_global_value(env.core, global, "Temporal", JsValue::from_js_object(temporal_ptr));
}
@@ -1,11 +1,8 @@
use std::sync::Arc;
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,
bind_well_known_method_alias, configure_native_constructor, BindEnv,
};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -14,24 +11,24 @@ use oxide_types::value::JsValue;
///
/// `realm_id` 是目标所属 realm 的编号:`@@species` 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
fn bind_typed_array_abstract_ctor(core: &Arc<KernelCore>, session: &KernelSession, realm_id: u32) {
let ctor_ptr = session.builtin_world().typed_array_constructor.as_ptr() as *mut JsObject;
fn bind_typed_array_abstract_ctor(env: BindEnv<'_>) {
let ctor_ptr = env.world().typed_array_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
configure_native_constructor(
ctor,
oxide_builtins::typed_array::typed_array_abstract_constructor::<crate::vm::Vm> as *const (),
0,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si);
let length_si = env.string_forge().intern("length").0;
let length_shape = env.shape_forge().make_shape(ctor.shape_id(), length_si);
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push(JsValue::int(0));
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 = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let world = session.builtin_world();
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 ctor = unsafe { &mut *ctor_ptr };
// SAFETY: of/from 是转成 *const () 的 NativeFn 函数项指针。
@@ -64,11 +61,10 @@ fn bind_typed_array_abstract_ctor(core: &Arc<KernelCore>, session: &KernelSessio
// (及派生类)沿原型链解析 @@species 得自身(具体构造器无 own 属性)。绑定站
// 与 TA 构造器后续消费面改造共用,先查槽位防重复绑定追加第二访问器槽。
let species_key =
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES);
if core.shape_forge().lookup_position(ctor.shape_id(), species_key).is_none() {
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES);
if env.shape_forge().lookup_position(ctor.shape_id(), species_key).is_none() {
bind_accessor_getter_key(
core,
session,
env,
ctor,
species_key,
"get [Symbol.species]",
@@ -82,20 +78,20 @@ fn bind_typed_array_abstract_ctor(core: &Arc<KernelCore>, session: &KernelSessio
/// # 步骤
/// 1. 构造器走 hash_props 存储(与 `bind_constructor` 的 hash 路径一致)。
/// 2. 原型走 shape 属性存储(与 `bind_method`/`bind_accessor_getter` 一致)。
fn set_bypes_per_element(core: &Arc<KernelCore>, ctor_ptr: *mut JsObject, proto_ptr: *mut JsObject, bpe: u32) {
let bpe_si = core.perm_interner().intern("BYTES_PER_ELEMENT").0;
fn set_bypes_per_element(env: BindEnv<'_>, ctor_ptr: *mut JsObject, proto_ptr: *mut JsObject, bpe: u32) {
let bpe_si = env.string_forge().intern("BYTES_PER_ELEMENT").0;
let bpe_val = JsValue::int(bpe as i32);
let attrs = PropAttributes::new(false, false, false);
let ctor = unsafe { &mut *ctor_ptr };
ctor.ensure_hash_props().push(bpe_val);
let ctor_pos = ctor.ensure_hash_props().len() - 1;
let ctor_shape = core.shape_forge().make_shape(ctor.shape_id(), bpe_si);
let ctor_shape = env.shape_forge().make_shape(ctor.shape_id(), bpe_si);
ctor.set_shape_id(ctor_shape);
ctor.set_data_meta(ctor_pos as u32, attrs);
let proto = unsafe { &mut *proto_ptr };
let proto_shape = core.shape_forge().make_shape(proto.shape_id(), bpe_si);
let proto_shape = env.shape_forge().make_shape(proto.shape_id(), bpe_si);
proto.set_shape_id(proto_shape);
let proto_pos = proto.push_prop(bpe_val);
proto.set_data_meta(proto_pos, attrs);
@@ -103,14 +99,14 @@ fn set_bypes_per_element(core: &Arc<KernelCore>, ctor_ptr: *mut JsObject, proto_
}
macro_rules! bind_typed_array_constructor {
($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $proto_ptr:expr, $bpe:expr, $ctor_fn:path) => {{
($env:expr, $global:expr, $name:literal, $ctor_ptr:expr, $proto_ptr:expr, $bpe:expr, $ctor_fn:path) => {{
let ctor = unsafe { &mut *$ctor_ptr };
configure_native_constructor(ctor, ($ctor_fn as fn(&mut $crate::vm::Vm, &[u8]) -> oxide_runtime_api::NativeResult) as *const (), 3);
bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, 3, hash: true);
bind_constructor!($env, $global, $name, $ctor_ptr, $ctor_fn, 3, hash: true);
// Function.length 描述符:不可写、不可枚举、可配置。
let len_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(len_pos, PropAttributes::new(false, false, true));
set_bypes_per_element($core, $ctor_ptr, $proto_ptr, $bpe);
set_bypes_per_element($env, $ctor_ptr, $proto_ptr, $bpe);
}};
}
@@ -118,13 +114,12 @@ macro_rules! bind_typed_array_constructor {
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, realm_id: u32) {
let shared_proto_ptr = session.builtin_world().typed_array_proto.as_ptr() as *mut JsObject;
pub fn bind_typed_array(env: BindEnv<'_>, global: &mut JsObject) {
let shared_proto_ptr = env.world().typed_array_proto.as_ptr() as *mut JsObject;
let shared_proto = unsafe { &mut *shared_proto_ptr };
apply_binding_table(
session.builtin_world(),
env,
shared_proto,
core,
&[
("at", oxide_builtins::typed_array::typed_array_at::<crate::vm::Vm> as *const (), 1),
("fill", oxide_builtins::typed_array::typed_array_fill::<crate::vm::Vm> as *const (), 1),
@@ -220,44 +215,39 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
);
// `keys` 已由方法表独立绑定(索引流 ≠ 值流);@@iterator 与 `values`
// 共享同一函数对象。
bind_well_known_method_alias(core, shared_proto, "values", 0, realm_id);
bind_well_known_method_alias(env.core, shared_proto, "values", 0, env.realm_id);
// 原型访问器:视图属性(buffer/byteOffset/byteLength/length)读内部数据槽,
// @@toStringTag 返回具体类型名,供 Object.prototype.toString 区分类型。
bind_accessor_getter(
core,
session,
env,
shared_proto,
"buffer",
oxide_builtins::typed_array::typed_array_buffer_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
shared_proto,
"byteOffset",
oxide_builtins::typed_array::typed_array_byte_offset_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
shared_proto,
"byteLength",
oxide_builtins::typed_array::typed_array_byte_length_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
env,
shared_proto,
"length",
oxide_builtins::typed_array::typed_array_length_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter_key(
core,
session,
env,
shared_proto,
oxide_types::private_key::encode_symbol_key(
realm_id,
env.realm_id,
oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG,
),
"get [Symbol.toStringTag]",
@@ -266,12 +256,12 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
// 共享原型的 own toString 与 Array.prototype.toString 共享同一函数对象
// (规范:同一内置函数对象;身份与描述符均按 own 属性验收)。
let to_string_si = core.perm_interner().intern("toString").0;
let array_proto_ref = unsafe { &*session.builtin_world().array_proto.as_ptr() };
let to_string_si = env.string_forge().intern("toString").0;
let array_proto_ref = unsafe { &*env.world().array_proto.as_ptr() };
// SAFETY: array_proto 由 BuiltinWorld 构造期建立,session 存活期内恒有效。
if let Some(pos) = core.shape_forge().lookup_position(array_proto_ref.shape_id(), to_string_si) {
if let Some(pos) = env.shape_forge().lookup_position(array_proto_ref.shape_id(), to_string_si) {
let value = array_proto_ref.get_prop_at(pos);
let new_shape = core.shape_forge().make_shape(shared_proto.shape_id(), to_string_si);
let new_shape = env.shape_forge().make_shape(shared_proto.shape_id(), to_string_si);
shared_proto.set_shape_id(new_shape);
let new_pos = shared_proto.push_prop(value);
shared_proto.set_data_meta(new_pos, PropAttributes::new(true, false, true));
@@ -280,10 +270,10 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
// base64/hex 四原型法挂 Uint8Array 专属原型(Uint8ClampedArray 经链继承、
// kind 校验拒绝);两静态法挂 Uint8Array 构造器。
let world = session.builtin_world();
let sh = core.shape_forge().as_ref();
let sf = core.perm_interner().as_ref();
let u8_proto_ptr = session.builtin_world().uint8array_proto.as_ptr() as *mut JsObject;
let world = env.world();
let sh = env.shape_forge();
let sf = env.string_forge();
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(
@@ -334,7 +324,7 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
},
1,
);
let u8_ctor_ptr = session.builtin_world().uint8array_constructor.as_ptr() as *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(
u8_ctor,
@@ -361,109 +351,109 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
1,
);
bind_typed_array_abstract_ctor(core, session, realm_id);
bind_typed_array_abstract_ctor(env);
// 把 `%TypedArray%` 抽象构造器暴露为全局 `TypedArray`(具体构造器的 [[Prototype]])。
let abstract_ctor_val =
JsValue::from_js_object(session.builtin_world().typed_array_constructor.as_ptr() as *mut JsObject);
bind_global_value(core, global, "TypedArray", abstract_ctor_val);
JsValue::from_js_object(env.world().typed_array_constructor.as_ptr() as *mut JsObject);
bind_global_value(env.core, global, "TypedArray", abstract_ctor_val);
bind_typed_array_constructor!(
core,
env,
global,
"Int8Array",
session.builtin_world().int8array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().int8array_proto.as_ptr() as *mut JsObject,
env.world().int8array_constructor.as_ptr() as *mut JsObject,
env.world().int8array_proto.as_ptr() as *mut JsObject,
1,
oxide_builtins::typed_array::int8array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Uint8Array",
session.builtin_world().uint8array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().uint8array_proto.as_ptr() as *mut JsObject,
env.world().uint8array_constructor.as_ptr() as *mut JsObject,
env.world().uint8array_proto.as_ptr() as *mut JsObject,
1,
oxide_builtins::typed_array::uint8array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Uint8ClampedArray",
session.builtin_world().uint8clampedarray_constructor.as_ptr() as *mut JsObject,
session.builtin_world().uint8clampedarray_proto.as_ptr() as *mut JsObject,
env.world().uint8clampedarray_constructor.as_ptr() as *mut JsObject,
env.world().uint8clampedarray_proto.as_ptr() as *mut JsObject,
1,
oxide_builtins::typed_array::uint8clampedarray_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Int16Array",
session.builtin_world().int16array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().int16array_proto.as_ptr() as *mut JsObject,
env.world().int16array_constructor.as_ptr() as *mut JsObject,
env.world().int16array_proto.as_ptr() as *mut JsObject,
2,
oxide_builtins::typed_array::int16array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Uint16Array",
session.builtin_world().uint16array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().uint16array_proto.as_ptr() as *mut JsObject,
env.world().uint16array_constructor.as_ptr() as *mut JsObject,
env.world().uint16array_proto.as_ptr() as *mut JsObject,
2,
oxide_builtins::typed_array::uint16array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Int32Array",
session.builtin_world().int32array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().int32array_proto.as_ptr() as *mut JsObject,
env.world().int32array_constructor.as_ptr() as *mut JsObject,
env.world().int32array_proto.as_ptr() as *mut JsObject,
4,
oxide_builtins::typed_array::int32array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Uint32Array",
session.builtin_world().uint32array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().uint32array_proto.as_ptr() as *mut JsObject,
env.world().uint32array_constructor.as_ptr() as *mut JsObject,
env.world().uint32array_proto.as_ptr() as *mut JsObject,
4,
oxide_builtins::typed_array::uint32array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Float32Array",
session.builtin_world().float32array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().float32array_proto.as_ptr() as *mut JsObject,
env.world().float32array_constructor.as_ptr() as *mut JsObject,
env.world().float32array_proto.as_ptr() as *mut JsObject,
4,
oxide_builtins::typed_array::float32array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"Float64Array",
session.builtin_world().float64array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().float64array_proto.as_ptr() as *mut JsObject,
env.world().float64array_constructor.as_ptr() as *mut JsObject,
env.world().float64array_proto.as_ptr() as *mut JsObject,
8,
oxide_builtins::typed_array::float64array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"BigInt64Array",
session.builtin_world().bigint64array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().bigint64array_proto.as_ptr() as *mut JsObject,
env.world().bigint64array_constructor.as_ptr() as *mut JsObject,
env.world().bigint64array_proto.as_ptr() as *mut JsObject,
8,
oxide_builtins::typed_array::bigint64array_constructor
);
bind_typed_array_constructor!(
core,
env,
global,
"BigUint64Array",
session.builtin_world().biguint64array_constructor.as_ptr() as *mut JsObject,
session.builtin_world().biguint64array_proto.as_ptr() as *mut JsObject,
env.world().biguint64array_constructor.as_ptr() as *mut JsObject,
env.world().biguint64array_proto.as_ptr() as *mut JsObject,
8,
oxide_builtins::typed_array::biguint64array_constructor
);
+3 -2
View File
@@ -10,7 +10,7 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::configure_native_constructor;
use crate::bindings::{configure_native_constructor, BindEnv};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::mem::P;
@@ -151,8 +151,9 @@ pub fn bind_weak_map(core: &Arc<KernelCore>, session: &mut KernelSession, global
ctor.set_data_meta(proto_pos, PropAttributes::new(false, false, false));
world.stub_objects.push(stub);
let env = BindEnv::new(core, &*session, realm_id);
bind_constructor!(
core,
env,
global,
"WeakMap",
ctor_ptr,
+14 -24
View File
@@ -6,11 +6,8 @@
//! 登记表(session 收尾统一释放),全局 `Worker` 槽经 `bind_constructor!` 原位
//! 安装(既有槽更新槽值、无槽新开)。
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, bind_accessor_getset, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use crate::bindings::{apply_binding_table, bind_accessor_getset, bind_accessor_getter, configure_native_constructor, BindEnv};
use oxide_kernel::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::string_forge::PermInterner;
@@ -33,10 +30,10 @@ use oxide_types::value::JsValue;
/// 主 realm 无 `self` 时为无害占位)。
///
/// `realm_id` 未使用(Worker 无 well-known 符号键),保留签名与其他绑定函数一致。
pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, _realm_id: u32) {
let world = session.builtin_world();
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
pub fn bind_worker(env: BindEnv<'_>, global: &mut JsObject) {
let world = env.world();
let sf = env.string_forge();
let sh = env.shape_forge();
// ---- 构造器本体(Box 分配,不占 P 字段)----
// 幂等:全局 `Worker` 槽已有构造器时复用(不新建)。
@@ -113,9 +110,8 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_post_message = sf.intern("postMessage").0;
if sh.lookup_position(proto.shape_id(), si_post_message).is_none() {
apply_binding_table(
world,
env,
proto,
core,
&[
("postMessage", crate::worker::bindings::worker_post_message as *const (), 1),
("terminate", crate::worker::bindings::worker_terminate as *const (), 0),
@@ -129,8 +125,7 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let key = sf.intern(name).0;
if sh.lookup_position(proto.shape_id(), key).is_none() {
bind_accessor_getset(
core,
session,
env,
proto,
key,
&format!("get {name}"),
@@ -144,7 +139,7 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
// 全局 `Worker` 槽(bind_constructor! 自带既有槽原位更新、无槽新开)。
bind_constructor!(
core,
env,
global,
"Worker",
ctor_ptr,
@@ -158,9 +153,8 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_self_post = sf.intern("postMessage").0;
if sh.lookup_position(global.shape_id(), si_self_post).is_none() {
apply_binding_table(
world,
env,
global,
core,
&[
("postMessage", crate::worker::bindings::self_post_message as *const (), 1),
("close", crate::worker::bindings::self_close as *const (), 0),
@@ -172,9 +166,8 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_import_scripts = sf.intern("importScripts").0;
if sh.lookup_position(global.shape_id(), si_import_scripts).is_none() {
apply_binding_table(
world,
env,
global,
core,
&[("importScripts", crate::worker::bindings::import_scripts as *const (), 1)],
);
}
@@ -183,9 +176,8 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_self_add = sf.intern("addEventListener").0;
if sh.lookup_position(global.shape_id(), si_self_add).is_none() {
apply_binding_table(
world,
env,
global,
core,
&[
(
"addEventListener",
@@ -224,8 +216,7 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let key = sf.intern(name).0;
if sh.lookup_position(global.shape_id(), key).is_none() {
bind_accessor_getset(
core,
session,
env,
global,
key,
&format!("get {name}"),
@@ -242,7 +233,7 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
let si_name_global = sf.intern("name").0;
if sh.lookup_position(global.shape_id(), si_name_global).is_none() {
if worker_realm {
bind_accessor_getter(core, session, global, "name", crate::worker::bindings::self_name as *const ());
bind_accessor_getter(env, global, "name", crate::worker::bindings::self_name as *const ());
} else {
bind_global_empty_string_property(global, sf, sh, si_name_global);
}
@@ -251,8 +242,7 @@ pub fn bind_worker(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
if sh.lookup_position(global.shape_id(), si_location).is_none() {
if worker_realm {
bind_accessor_getter(
core,
session,
env,
global,
"location",
crate::worker::bindings::self_location as *const (),
+131 -150
View File
@@ -85,15 +85,19 @@ use oxide_types::value::JsValue;
///
/// `Copy`:值语义轻量(两个引用加一个 u32),可自由复制传递。
#[derive(Copy, Clone)]
pub(crate) struct BindEnv<'a> {
core: &'a Arc<KernelCore>,
pub struct BindEnv<'a> {
pub core: &'a Arc<KernelCore>,
session: &'a KernelSession,
realm_id: u32,
}
impl BindEnv<'_> {
impl<'a> BindEnv<'a> {
/// 构造绑定环境。
pub(crate) fn new(core: &'a Arc<KernelCore>, session: &'a KernelSession, realm_id: u32) -> Self {
BindEnv { core, session, realm_id }
}
/// 当前 session 的 builtin world(共享借用)。
fn world(&self) -> &BuiltinWorld {
pub fn world(&self) -> &BuiltinWorld {
self.session.builtin_world()
}
/// 共享 shape forge。
@@ -108,18 +112,18 @@ impl BindEnv<'_> {
#[macro_export]
macro_rules! bind_constructor {
($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal) => {{
bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, $nargs, hash: false)
($env:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal) => {{
bind_constructor!($env, $global, $name, $ctor_ptr, $ctor_fn, $nargs, hash: false)
}};
($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal, hash: $hash:literal) => {{
let si = $core.perm_interner().intern($name).0;
($env:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path, $nargs:literal, hash: $hash:literal) => {{
let si = $env.string_forge().intern($name).0;
let val = $crate::JsValue::from_js_object($ctor_ptr);
if let Some(pos) = $core.shape_forge().lookup_position($global.shape_id(), si) {
if let Some(pos) = $env.shape_forge().lookup_position($global.shape_id(), si) {
// 既有槽(重建后保留的 global):原位更新槽值,不追加新槽——旧家族
// 构造器指针不得滞留属性 vec,shape 链不得继续增长。
$global.set_prop_at(pos, val);
} else {
let shape = $core.shape_forge().make_shape($global.shape_id(), si);
let shape = $env.shape_forge().make_shape($global.shape_id(), si);
$global.set_shape_id(shape);
if $hash {
$global.ensure_hash_props().push(val);
@@ -139,8 +143,8 @@ macro_rules! bind_constructor {
ctor.set_native_arg_count($nargs);
ctor.type_tag = oxide_types::object::JsObject::OBJ_TYPE_CONSTRUCTOR;
// 设置 constructor.length (Function.length = formal parameter count)
let length_si = $core.perm_interner().intern("length").0;
let length_shape = $core.shape_forge().make_shape(ctor.shape_id(), length_si);
let length_si = $env.string_forge().intern("length").0;
let length_shape = $env.shape_forge().make_shape(ctor.shape_id(), length_si);
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push($crate::JsValue::int($nargs as i32));
// length 描述符 { writable:false, enumerable:false, configurable:true }
@@ -180,11 +184,10 @@ fn configure_existing_ctor(ctor: &P<JsObject>, native_fn: *const (), arg_count:
/// - 表中所有函数项指针须为合法的 `NativeFn`(转成 `*const ()`),此处经
/// `NativeFnPtr::from_raw` 转换。
/// - `bind_method` 的返回值被丢弃:单条绑定失败不中断后续条目。
pub(crate) fn apply_binding_table(
world: &BuiltinWorld, target: &mut JsObject, core: &Arc<KernelCore>, bindings: &[(&'static str, *const (), u8)],
) {
let shape_forge = core.shape_forge().as_ref();
let string_forge = core.perm_interner().as_ref();
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();
for (name, func, nargs) in bindings {
// SAFETY: 绑定表中所有条目都是转成 *const () 的 NativeFn 函数项指针。
let fn_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(*func) };
@@ -201,12 +204,10 @@ pub(crate) fn apply_binding_table(
/// # 注意事项
/// getter 函数对象登记进 world 释放表,与 `bind_method` 的方法 wrapper 同一生命周期约定
/// (session 收尾时统一释放)。
pub(crate) fn bind_accessor_getter(
core: &Arc<KernelCore>, session: &KernelSession, proto: &mut JsObject, name: &str, getter_fn: *const (),
) {
let si = core.perm_interner().intern(name).0;
pub(crate) fn bind_accessor_getter(env: BindEnv<'_>, proto: &mut JsObject, name: &str, getter_fn: *const ()) {
let si = env.string_forge().intern(name).0;
let getter_name = format!("get {name}");
bind_accessor_getter_key(core, session, proto, si, &getter_name, getter_fn)
bind_accessor_getter_key(env, proto, si, &getter_name, getter_fn)
}
/// 在原型上按任意属性键(字符串 intern 键或 well-known symbol 键)绑定一个
@@ -220,12 +221,11 @@ pub(crate) fn bind_accessor_getter(
/// getter 函数对象登记进 world 释放表,与 `bind_method` 的方法 wrapper 同一生命周期约定
/// (session 收尾时统一释放)。
pub(crate) fn bind_accessor_getter_key(
core: &Arc<KernelCore>, session: &KernelSession, proto: &mut JsObject, key: u32, getter_label: &str,
getter_fn: *const (),
env: BindEnv<'_>, proto: &mut JsObject, key: u32, getter_label: &str, getter_fn: *const (),
) {
let shape_forge = core.shape_forge().as_ref();
let string_forge = core.perm_interner().as_ref();
let world = session.builtin_world();
let shape_forge = env.shape_forge();
let string_forge = env.string_forge();
let world = env.world();
let si_label = string_forge.intern(getter_label).0;
// SAFETY: getter_fn 是转成 *const () 的 NativeFn 函数项指针。
@@ -284,14 +284,13 @@ pub(crate) fn bind_accessor_getter_key(
/// # 注意事项
/// getter/setter 函数对象登记进 world 释放表,session 收尾时统一释放,
/// 与 `bind_accessor_getter` 的 getter 及方法 wrapper 同一生命周期约定。
#[expect(clippy::too_many_arguments)]
pub(crate) fn bind_accessor_getset(
core: &Arc<KernelCore>, session: &KernelSession, proto: &mut JsObject, key: u32, getter_name: &str,
setter_name: &str, getter_fn: *const (), setter_fn: *const (),
env: BindEnv<'_>, proto: &mut JsObject, key: u32, getter_name: &str, setter_name: &str,
getter_fn: *const (), setter_fn: *const (),
) {
let shape_forge = core.shape_forge().as_ref();
let string_forge = core.perm_interner().as_ref();
let world = session.builtin_world();
let shape_forge = env.shape_forge();
let string_forge = env.string_forge();
let world = env.world();
let family = world.wrapper_family_of(proto as *const JsObject);
let si_length = string_forge.intern("length").0;
let si_name = string_forge.intern("name").0;
@@ -393,16 +392,15 @@ pub(crate) fn bind_method_alias(core: &Arc<KernelCore>, proto: &mut JsObject, so
///
/// `realm_id` 是目标所属 realm 的编号:符号键按 (realm 编号, 局部下标) 编码,
/// realm 编号为 0 时与旧编码逐字节一致。
#[expect(clippy::too_many_arguments)]
pub(crate) fn bind_well_known_method(
world: &BuiltinWorld, core: &Arc<KernelCore>, target: &mut JsObject, well_known_id: u32, method_name: &str,
func: *const (), nargs: u8, realm_id: u32,
env: BindEnv<'_>, target: &mut JsObject, well_known_id: u32, method_name: &str, func: *const (), nargs: u8,
) {
let shape_forge = core.shape_forge().as_ref();
let string_forge = core.perm_interner().as_ref();
let world = env.world();
let shape_forge = env.shape_forge();
let string_forge = env.string_forge();
// SAFETY: func 是转成 *const () 的 NativeFn 函数项指针。
let fn_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(func) };
let key = oxide_types::private_key::encode_symbol_key(realm_id, well_known_id);
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,
@@ -468,12 +466,10 @@ pub(crate) fn bind_well_known_data_property(
/// 在 Iterator 函数对象上绑定 `prototype` 属性 = %IteratorPrototype%(规范形状:
/// 构造器函数带 prototype 属性;描述符不可写/不可枚举/不可配置)。
pub(crate) fn bind_iterator_function_prototype(
core: &Arc<KernelCore>, session: &KernelSession, iterator: &mut JsObject,
) {
let iter_proto_ptr = session.builtin_world().iterator_proto.as_ptr() as *mut JsObject;
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
pub(crate) fn bind_iterator_function_prototype(env: BindEnv<'_>, iterator: &mut JsObject) {
let iter_proto_ptr = env.world().iterator_proto.as_ptr() as *mut JsObject;
let sf = env.string_forge();
let sh = env.shape_forge();
let si_prototype = sf.intern("prototype").0;
let iterator_shape = sh.make_shape(iterator.shape_id(), si_prototype);
iterator.set_shape_id(iterator_shape);
@@ -485,15 +481,13 @@ pub(crate) fn bind_iterator_function_prototype(
/// 在集合迭代器原型上绑定 `next` 方法(规范形状:next 挂原型,wrapper 不设 own)。
///
/// `next` 键已存在时跳过:保留原型在 dirty reset 重复经过时不再追加重复属性槽。
pub(crate) fn bind_iterator_proto_next(
core: &Arc<KernelCore>, session: &KernelSession, proto: *mut JsObject, func: *const (),
) {
pub(crate) fn bind_iterator_proto_next(env: BindEnv<'_>, proto: *mut JsObject, func: *const ()) {
let proto = unsafe { &mut *proto };
let si_next = core.perm_interner().intern("next").0;
if core.shape_forge().lookup_position(proto.shape_id(), si_next).is_some() {
let si_next = env.string_forge().intern("next").0;
if env.shape_forge().lookup_position(proto.shape_id(), si_next).is_some() {
return;
}
apply_binding_table(session.builtin_world(), proto, core, &[("next", func, 0)]);
apply_binding_table(env, proto, &[("next", func, 0)]);
}
/// 把迭代器原型方法安装到当前 builtin world 的迭代器原型上:
@@ -508,7 +502,6 @@ pub(crate) fn bind_iterator_proto_next(
fn bind_iterator_protos(env: BindEnv<'_>) {
let world = env.world();
let core = env.core;
let session = env.session;
let realm_id = env.realm_id;
// %IteratorPrototype% 自身可迭代:@@iterator 返回 this,经原型链被全部
@@ -518,14 +511,12 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
let sym_iter = oxide_types::private_key::encode_symbol_key(realm_id, 0);
if core.shape_forge().lookup_position(iter_proto.shape_id(), sym_iter).is_none() {
bind_well_known_method(
world,
core,
env,
iter_proto,
0,
"iterator",
oxide_builtins::iterator::iterator_symbol_iterator::<crate::vm::Vm> as *const (),
0,
realm_id,
);
}
@@ -539,8 +530,7 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
.is_none()
{
bind_accessor_getset(
core,
session,
env,
iter_proto,
si_constructor,
"get constructor",
@@ -559,8 +549,7 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
.is_none()
{
bind_accessor_getset(
core,
session,
env,
iter_proto,
sym_to_string_tag,
"get [Symbol.toStringTag]",
@@ -575,14 +564,12 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
let sym_dispose = oxide_types::private_key::encode_symbol_key(realm_id, dispose_id);
if core.shape_forge().lookup_position(iter_proto.shape_id(), sym_dispose).is_none() {
bind_well_known_method(
world,
core,
env,
iter_proto,
dispose_id,
"[Symbol.dispose]",
oxide_builtins::iterator::iterator_dispose::<crate::vm::Vm> as *const (),
0,
realm_id,
);
}
@@ -592,9 +579,8 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
let si_for_each = core.perm_interner().intern("forEach").0;
if core.shape_forge().lookup_position(iter_proto.shape_id(), si_for_each).is_none() {
apply_binding_table(
world,
env,
iter_proto,
core,
&[
("forEach", oxide_builtins::iterator::iterator_for_each::<crate::vm::Vm> as *const (), 1),
("every", oxide_builtins::iterator::iterator_every::<crate::vm::Vm> as *const (), 1),
@@ -611,9 +597,8 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
let si_map = core.perm_interner().intern("map").0;
if core.shape_forge().lookup_position(iter_proto.shape_id(), si_map).is_none() {
apply_binding_table(
world,
env,
iter_proto,
core,
&[
("map", oxide_builtins::iterator::iterator_map::<crate::vm::Vm> as *const (), 1),
("filter", oxide_builtins::iterator::iterator_filter::<crate::vm::Vm> as *const (), 1),
@@ -634,14 +619,12 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
);
if core.shape_forge().lookup_position(aiter_proto.shape_id(), sym_aiter).is_none() {
bind_well_known_method(
world,
core,
env,
aiter_proto,
oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_ITERATOR,
"[Symbol.asyncIterator]",
crate::async_generator::async_generator_symbol_async_iterator as *const (),
0,
realm_id,
);
}
let sym_adispose = oxide_types::private_key::encode_symbol_key(
@@ -654,14 +637,12 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
.is_none()
{
bind_well_known_method(
world,
core,
env,
aiter_proto,
oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_DISPOSE,
"[Symbol.asyncDispose]",
crate::async_generator::async_iterator_async_dispose as *const (),
0,
realm_id,
);
}
@@ -673,9 +654,8 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
let si_next = core.perm_interner().intern("next").0;
if core.shape_forge().lookup_position(helper_proto.shape_id(), si_next).is_none() {
apply_binding_table(
world,
env,
helper_proto,
core,
&[
("next", oxide_builtins::iterator::iterator_helper_next::<crate::vm::Vm> as *const (), 0),
(
@@ -700,26 +680,22 @@ fn bind_iterator_protos(env: BindEnv<'_>) {
// %ArrayIteratorPrototype% 服务 Array/TA 两族;Map/Set 共用按 `__mode__`
// 分发的实现;%RegExpStringIteratorPrototype% 供 matchAll。
bind_iterator_proto_next(
core,
session,
env,
world.array_iterator_proto.as_ptr() as *mut JsObject,
oxide_builtins::array::array_iterator_next::<crate::vm::Vm> as *const (),
);
bind_iterator_proto_next(
core,
session,
env,
world.map_iterator_proto.as_ptr() as *mut JsObject,
oxide_builtins::iterator::map_set_iterator_next::<crate::vm::Vm> as *const (),
);
bind_iterator_proto_next(
core,
session,
env,
world.set_iterator_proto.as_ptr() as *mut JsObject,
oxide_builtins::iterator::map_set_iterator_next::<crate::vm::Vm> as *const (),
);
bind_iterator_proto_next(
core,
session,
env,
world.regexp_string_iterator_proto.as_ptr() as *mut JsObject,
oxide_builtins::string::string_match_all_next::<crate::vm::Vm> as *const (),
);
@@ -876,9 +852,8 @@ fn bind_error_subtype_global(
fn bind_global_functions(env: BindEnv<'_>, global: &mut JsObject) {
apply_binding_table(
env.world(),
env,
global,
env.core,
&[
// parseInt 形式参数为 (string, radix),length 按规范取 2。
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 2),
@@ -915,9 +890,8 @@ fn bind_reflect_global(env: BindEnv<'_>, global: &mut JsObject) {
JsValue::from_js_object(env.world().object_proto.as_ptr() as *mut JsObject),
));
apply_binding_table(
env.world(),
env,
&mut reflect,
env.core,
&[
("apply", oxide_builtins::reflect::reflect_apply::<crate::vm::Vm> as *const (), 3),
("construct", oxide_builtins::reflect::reflect_construct::<crate::vm::Vm> as *const (), 2),
@@ -977,11 +951,10 @@ fn bind_iterator_global(env: BindEnv<'_>, global: &mut JsObject) {
0,
);
bind_iterator_ctor_identity(env.core, &mut iterator);
bind_iterator_function_prototype(env.core, env.session, &mut iterator);
bind_iterator_function_prototype(env, &mut iterator);
apply_binding_table(
env.world(),
env,
&mut iterator,
env.core,
&[("from", oxide_builtins::iterator::iterator_from::<crate::vm::Vm> as *const (), 1)],
);
let iterator_ptr = Box::into_raw(iterator);
@@ -1266,13 +1239,13 @@ pub fn bind_global_builtin_slots(
bind_reflect_global(env, global);
bind_iterator_global(env, global);
bind_worker::bind_worker(core, session, global, realm_id);
bind_disposable_stack::bind_disposable_stack(core, session, global, realm_id);
bind_async_disposable_stack::bind_async_disposable_stack(core, session, global, realm_id);
bind_worker::bind_worker(env, global);
bind_disposable_stack::bind_disposable_stack(env, global);
bind_async_disposable_stack::bind_async_disposable_stack(env, global);
bind_stub_globals(env, global);
bind_bigint::bind_bigint(core, session, global, realm_id);
bind_bigint::bind_bigint(env, global);
bind_global_functions(env, global);
crate::test262_host::bind_test262_host(core, session, global);
crate::test262_host::bind_test262_host(env, global);
let global_this = JsValue::from_js_object(global as *mut JsObject);
bind_existing_global(core, global, "globalThis", global_this);
}
@@ -1290,111 +1263,114 @@ pub fn rebind_dirty_builtins(
) {
let global_ptr = session.global_object().as_ptr() as *mut JsObject;
let global = unsafe { &mut *global_ptr };
let env = BindEnv {
core,
session: &*session,
realm_id,
};
if dirty.map_or(true, |d| d.object) {
bind_object::bind_object(core, session, global);
bind_object::bind_object(env, global);
// object 家族重建连带重建 6 个迭代器原型与两资源栈原型(其链到新
// Object.prototype),须同步安装原型方法并让保留的 global 构造器指向新原型。
let env = BindEnv {
core,
session: &*session,
realm_id,
};
bind_iterator_protos(env);
sync_iterator_function_prototype(env, global);
bind_disposable_stack::bind_disposable_stack_protos(core, session, realm_id);
bind_disposable_stack::sync_disposable_stack_ctor(core, session, global);
bind_async_disposable_stack::bind_async_disposable_stack_protos(core, session, realm_id);
bind_async_disposable_stack::sync_async_disposable_stack_ctor(core, session, global);
bind_disposable_stack::bind_disposable_stack_protos(env);
bind_disposable_stack::sync_disposable_stack_ctor(env, global);
bind_async_disposable_stack::bind_async_disposable_stack_protos(env);
bind_async_disposable_stack::sync_async_disposable_stack_ctor(env, global);
}
if dirty.map_or(true, |d| d.array) {
bind_array::bind_array(core, session, global, realm_id);
bind_array::bind_array(env, global);
}
if dirty.map_or(true, |d| d.array_buffer) {
bind_array_buffer::bind_array_buffer(core, session, global, realm_id);
bind_array_buffer::bind_array_buffer(env, global);
}
if dirty.map_or(true, |d| d.shared_array_buffer) {
bind_shared_array_buffer::bind_shared_array_buffer(core, session, global);
bind_shared_array_buffer::bind_shared_array_buffer(env, global);
}
if dirty.map_or(true, |d| d.data_view) {
bind_data_view::bind_data_view(core, session, global);
bind_data_view::bind_data_view(env, global);
}
if dirty.map_or(true, |d| d.typed_array_family) {
bind_typed_array::bind_typed_array(core, session, global, realm_id);
bind_typed_array::bind_typed_array(env, global);
}
if dirty.map_or(true, |d| d.error_family) {
bind_error::bind_error(core, session, global);
bind_error::bind_error(env, global);
}
if dirty.map_or(true, |d| d.string) {
bind_string::bind_string(core, session, global, realm_id);
bind_string::bind_string(env, global);
}
if dirty.map_or(true, |d| d.number) {
bind_number::bind_number(core, session, global);
bind_number::bind_number(env, global);
}
if dirty.map_or(true, |d| d.math) {
bind_math::bind_math(core, session, global);
bind_math::bind_math(env, global);
}
if dirty.map_or(true, |d| d.atomics) {
bind_atomics::bind_atomics(core, session, global);
bind_atomics::bind_atomics(env, global);
}
if dirty.map_or(true, |d| d.json) {
bind_json::bind_json(core, session, global);
bind_json::bind_json(env, global);
}
if dirty.map_or(true, |d| d.date) {
bind_date::bind_date(core, session, global);
bind_date::bind_date(env, global);
}
if dirty.map_or(true, |d| d.set) {
bind_set::bind_set(core, session, global, realm_id);
bind_set::bind_set(env, global);
}
if dirty.map_or(true, |d| d.map) {
bind_map::bind_map(core, session, global, realm_id);
bind_map::bind_map(env, global);
}
if dirty.map_or(true, |d| d.boolean) {
bind_boolean::bind_boolean(core, session, global);
bind_boolean::bind_boolean(env, global);
}
if dirty.map_or(true, |d| d.function) {
bind_function::bind_function(core, session, global, realm_id);
bind_function::bind_function(env, global);
}
if dirty.map_or(true, |d| d.regexp) {
bind_regexp::bind_regexp(core, session, global, realm_id);
bind_regexp::bind_regexp(env, global);
}
if dirty.map_or(true, |d| d.symbol_family) {
bind_symbol::bind_symbol(core, session, global, realm_id);
bind_symbol::bind_symbol(env, global);
}
if dirty.map_or(true, |d| d.temporal) {
bind_temporal::bind_temporal(core, session, global, realm_id);
bind_temporal::bind_temporal(env, global);
}
// 独占函数(bind_stubs / bind_weak_map)需要 session 的可变借用,与 env
// 的共享借用冲突;env 的最后一次使用在上面的 temporal 分支,独占调用
// 之后重建 env 供后续分支使用。
if dirty.map_or(true, |d| d.stubs) {
bind_stubs::bind_stubs(core, session, global, realm_id);
// WeakMap 真构造器面与 stub 族同脏位:原型对象经 leaked 登记表迁移,
// 重绑时全局槽原位更新,不占 BuiltinWorld 槽。
bind_weak::bind_weak_map(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.stubs) {
bind_bigint::bind_bigint(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.message_channel) {
bind_message_channel::bind_message_channel(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.broadcast_channel) {
bind_broadcast_channel::bind_broadcast_channel(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.event) {
bind_event::bind_event(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.console) {
bind_console::bind_console(core, session, global);
}
// worker 构造器是 Box 分配对象(不在 BuiltinWorld 快照内),不占脏位:
// 无条件重绑(构造器经 lookup_position 守卫复用,幂等)。
bind_worker::bind_worker(core, session, global, realm_id);
// tag 目标横跨多个脏分组(Map/Set/DataView/Math/JSON/迭代器原型),
// 各组各自重绑后统一补装;安装点自带幂等检查。
let env = BindEnv {
core,
session: &*session,
realm_id,
};
if dirty.map_or(true, |d| d.stubs) {
bind_bigint::bind_bigint(env, global);
}
if dirty.map_or(true, |d| d.message_channel) {
bind_message_channel::bind_message_channel(env, global);
}
if dirty.map_or(true, |d| d.broadcast_channel) {
bind_broadcast_channel::bind_broadcast_channel(env, global);
}
if dirty.map_or(true, |d| d.event) {
bind_event::bind_event(env, global);
}
if dirty.map_or(true, |d| d.console) {
bind_console::bind_console(env, global);
}
// worker 构造器是 Box 分配对象(不在 BuiltinWorld 快照内),不占脏位:
// 无条件重绑(构造器经 lookup_position 守卫复用,幂等)。
bind_worker::bind_worker(env, global);
// tag 目标横跨多个脏分组(Map/Set/DataView/Math/JSON/迭代器原型),
// 各组各自重绑后统一补装;安装点自带幂等检查。
install_to_string_tags(env);
}
@@ -1406,13 +1382,18 @@ pub fn init_kernel_builtins(core: &Arc<KernelCore>, session: &mut KernelSession,
rebind_dirty_builtins(core, session, None, realm_id);
let global_ptr = session.global_object().as_ptr() as *mut oxide_types::object::JsObject;
let global = unsafe { &mut *global_ptr };
bind_iterator::bind_iterator(core, session, global);
bind_disposable_stack::bind_disposable_stack(core, session, global, realm_id);
bind_async_disposable_stack::bind_async_disposable_stack(core, session, global, realm_id);
bind_reflect::bind_reflect(core, session, global);
bind_global::bind_global(core, session, global);
let env = BindEnv {
core,
session: &*session,
realm_id,
};
bind_iterator::bind_iterator(env, global);
bind_disposable_stack::bind_disposable_stack(env, global);
bind_async_disposable_stack::bind_async_disposable_stack(env, global);
bind_reflect::bind_reflect(env, global);
bind_global::bind_global(env, global);
bind_global_value(core, global, "globalThis", JsValue::from_js_object(global_ptr));
bind_console::bind_console(core, session, global);
crate::test262_host::bind_test262_host(core, session, global);
bind_console::bind_console(env, global);
crate::test262_host::bind_test262_host(env, global);
session.record_snapshot();
}
+1 -2
View File
@@ -353,8 +353,7 @@ impl Vm {
// Promise[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链
// 解析 @@species 得自身构造器。ctor 经本函数每次调用全新构造,同键槽不累积。
crate::bindings::bind_accessor_getter_key(
&self.kernel_core,
&self.realm.session.borrow(),
crate::bindings::BindEnv::new(&self.kernel_core, &self.realm.session.borrow(), self.realm_id()),
ctor_mut,
oxide_types::private_key::encode_symbol_key(
self.realm_id(),
+9 -13
View File
@@ -5,15 +5,12 @@
//! `$262.*` 的测试真实执行而非一律抛 `ReferenceError` 被 runner 吞为 skip;
//! 未实现的方法抛 `not supported` 错误,runner 按能力缺失归类。
use std::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_runtime_api::{to_units_full, NativeResult};
use oxide_types::object::{JsObject, NativeFnPtr};
use oxide_types::value::JsValue;
use crate::bindings::{apply_binding_table, bind_global_value};
use crate::bindings::{apply_binding_table, bind_global_value, BindEnv};
use crate::vm::Vm;
/// `$262` 未实现方法统一抛错:消息带 `not supported`,runner 据此按能力缺失跳过。
@@ -111,13 +108,12 @@ pub fn is_html_dda_call(_vm: &mut Vm, _args: &[u8]) -> NativeResult {
/// - 宿主对象登记进 world 释放表,session 收尾时统一释放(与 Reflect/Iterator
/// 等全局对象同一约定);每次调用新建对象,同一 session 内重复绑定会泄漏旧对象
/// (全量初始化与 full_reset 频率低,可接受)。
pub fn bind_test262_host(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
let object_proto = session.builtin_world().object_proto.as_ptr() as *mut JsObject;
pub fn bind_test262_host(env: BindEnv<'_>, global: &mut JsObject) {
let object_proto = env.world().object_proto.as_ptr() as *mut JsObject;
let mut host = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
apply_binding_table(
session.builtin_world(),
env,
&mut host,
core,
&[
("evalScript", eval_script as *const (), 1),
("detachArrayBuffer", detach_array_buffer as *const (), 1),
@@ -127,7 +123,7 @@ pub fn bind_test262_host(core: &Arc<KernelCore>, session: &KernelSession, global
],
);
let global_this = JsValue::from_js_object(global as *mut JsObject);
bind_global_value(core, &mut host, "global", global_this);
bind_global_value(env.core, &mut host, "global", global_this);
// [[IsHTMLDDA]] 宿主值(B.3.4):可调用(被调用时返回 null),
// ToBoolean/typeof/宽松相等按 undefined 处理,Type 与其余强制转换按普通对象处理。
let mut dda = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
@@ -136,9 +132,9 @@ pub fn bind_test262_host(core: &Arc<KernelCore>, session: &KernelSession, global
dda.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(is_html_dda_call as *const ()) }));
dda.set_native_arg_count(0);
let dda_ptr = Box::into_raw(Box::new(dda));
session.builtin_world().track_leaked_object(dda_ptr);
bind_global_value(core, &mut host, "IsHTMLDDA", JsValue::from_js_object(dda_ptr));
env.world().track_leaked_object(dda_ptr);
bind_global_value(env.core, &mut host, "IsHTMLDDA", JsValue::from_js_object(dda_ptr));
let host_ptr = Box::into_raw(Box::new(host));
session.builtin_world().track_leaked_object(host_ptr);
bind_global_value(core, global, "$262", JsValue::from_js_object(host_ptr));
env.world().track_leaked_object(host_ptr);
bind_global_value(env.core, global, "$262", JsValue::from_js_object(host_ptr));
}