From aa881783bfb8c7d40d6e8264a8be34d77988249a Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 7 Oct 2026 03:48:59 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=BB=91=E5=AE=9A=E4=B8=8E=20kerne?= =?UTF-8?q?l=20=E7=AC=A6=E5=8F=B7=E9=94=AE=E6=94=B9=E7=BB=8F=20realm=20?= =?UTF-8?q?=E7=BB=B4=E5=BA=A6=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 36 +++--- Cargo.toml | 2 +- crates/oxide_kernel/src/builtin/bind.rs | 18 ++- crates/oxide_vm/src/bindings/bind_array.rs | 10 +- .../src/bindings/bind_array_buffer.rs | 7 +- .../bindings/bind_async_disposable_stack.rs | 18 ++- crates/oxide_vm/src/bindings/bind_bigint.rs | 7 +- .../src/bindings/bind_disposable_stack.rs | 16 ++- crates/oxide_vm/src/bindings/bind_function.rs | 6 +- crates/oxide_vm/src/bindings/bind_map.rs | 9 +- crates/oxide_vm/src/bindings/bind_regexp.rs | 12 +- crates/oxide_vm/src/bindings/bind_set.rs | 9 +- crates/oxide_vm/src/bindings/bind_string.rs | 8 +- crates/oxide_vm/src/bindings/bind_stubs.rs | 8 +- crates/oxide_vm/src/bindings/bind_symbol.rs | 10 +- crates/oxide_vm/src/bindings/bind_temporal.rs | 12 +- .../oxide_vm/src/bindings/bind_typed_array.rs | 18 ++- crates/oxide_vm/src/bindings/bind_weak.rs | 7 +- crates/oxide_vm/src/bindings/mod.rs | 117 ++++++++++++------ crates/oxide_vm/src/vm_support.rs | 30 +++-- 20 files changed, 244 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 076a6698..2fb91e35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.8.53" +version = "0.8.54" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.8.53" +version = "0.8.54" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.8.53" +version = "0.8.54" dependencies = [ "ansi_term", "bumpalo", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.8.53" +version = "0.8.54" dependencies = [ "lru", "oxide_bytecode", @@ -1234,7 +1234,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1253,7 +1253,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.8.53" +version = "0.8.54" dependencies = [ "num-bigint", "oxc_allocator", @@ -1282,7 +1282,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1291,7 +1291,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.8.53" +version = "0.8.54" dependencies = [ "bumpalo", "dashmap", @@ -1306,7 +1306,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1318,7 +1318,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.8.53" +version = "0.8.54" dependencies = [ "tracing", "tracing-appender", @@ -1327,7 +1327,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1342,7 +1342,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1358,7 +1358,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.8.53" +version = "0.8.54" dependencies = [ "num-bigint", "num-traits", @@ -1370,7 +1370,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.8.53" +version = "0.8.54" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.8.53" +version = "0.8.54" dependencies = [ "bumpalo", "hashbrown 0.14.5", @@ -1399,7 +1399,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.8.53" +version = "0.8.54" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 419e6913..1287576b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ members = [ ] [workspace.package] -version = "0.8.53" +version = "0.8.54" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_kernel/src/builtin/bind.rs b/crates/oxide_kernel/src/builtin/bind.rs index 0102171d..c8f06287 100644 --- a/crates/oxide_kernel/src/builtin/bind.rs +++ b/crates/oxide_kernel/src/builtin/bind.rs @@ -3,7 +3,7 @@ use oxide_types::mem::P; use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes}; -use oxide_types::private_key::make_well_known_symbol_key; +use oxide_types::private_key::encode_symbol_key; use oxide_types::value::JsValue; use super::{ArrayMethods, BuiltinWorld, ErrorMethods, FnWrapperKey, FunctionMethods, ObjectMethods, StringMethods}; @@ -66,7 +66,12 @@ impl BuiltinWorld { } /// 把 Array 家族方法安装到 Array 构造器与原型上。 - pub fn bind_array_methods(&self, methods: &ArrayMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) { + /// + /// `realm_id` 是安装目标所属 realm 的编号:`@@iterator` 符号键按 + /// (realm 编号, 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 + pub fn bind_array_methods( + &self, methods: &ArrayMethods, string_forge: &PermInterner, shape_forge: &ShapeForge, realm_id: u32, + ) { let ctor_ptr = P::as_ptr(&self.array_constructor) as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; bind_methods!( @@ -124,7 +129,7 @@ impl BuiltinWorld { ("with", methods.with_method, 2), ); - let iterator_key = make_well_known_symbol_key(0); + let iterator_key = encode_symbol_key(realm_id, 0); let raw = methods.values; // SAFETY: methods.values 是 VM 绑定层传入的 NativeFn 函数项。 let func_ptr = unsafe { NativeFnPtr::from_raw(raw) }; @@ -312,8 +317,11 @@ impl BuiltinWorld { } /// 把 Function 原型方法安装到 Function.prototype 上。 + /// + /// `realm_id` 是安装目标所属 realm 的编号:`@@hasInstance` 符号键按 + /// (realm 编号, 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 pub fn bind_function_methods( - &self, methods: &FunctionMethods, string_forge: &PermInterner, shape_forge: &ShapeForge, + &self, methods: &FunctionMethods, string_forge: &PermInterner, shape_forge: &ShapeForge, realm_id: u32, ) { let proto_ptr = P::as_ptr(&self.function_proto) as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; @@ -333,7 +341,7 @@ impl BuiltinWorld { proto, shape_forge, string_forge, - make_well_known_symbol_key(6), + encode_symbol_key(realm_id, 6), "[Symbol.hasInstance]", unsafe { NativeFnPtr::from_raw(methods.has_instance) }, 1, diff --git a/crates/oxide_vm/src/bindings/bind_array.rs b/crates/oxide_vm/src/bindings/bind_array.rs index 0696625e..5e9a7746 100644 --- a/crates/oxide_vm/src/bindings/bind_array.rs +++ b/crates/oxide_vm/src/bindings/bind_array.rs @@ -8,7 +8,10 @@ use crate::bind_constructor; use crate::bindings::apply_binding_table; /// 把 Array 构造器与原型方法绑定到 global。 -pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let _array_methods = ArrayMethods { is_array: oxide_builtins::array::array_is_array:: as *const (), from: oxide_builtins::array::array_from:: as *const (), @@ -55,6 +58,7 @@ pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut &_array_methods, core.perm_interner().as_ref(), core.shape_forge().as_ref(), + realm_id, ); let array_proto_ptr = session.builtin_world().array_proto.as_ptr() as *mut JsObject; @@ -71,7 +75,7 @@ pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut 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); + super::bind_well_known_method_alias(core, array_proto, "values", 0, 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::, 1, hash: true); @@ -82,7 +86,7 @@ pub fn bind_array(core: &Arc, session: &KernelSession, global: &mut core, session, unsafe { &mut *ctor_ptr }, - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), "get [Symbol.species]", oxide_builtins::array::array_species_get:: as *const (), ); diff --git a/crates/oxide_vm/src/bindings/bind_array_buffer.rs b/crates/oxide_vm/src/bindings/bind_array_buffer.rs index ec5ab346..945f4f36 100644 --- a/crates/oxide_vm/src/bindings/bind_array_buffer.rs +++ b/crates/oxide_vm/src/bindings/bind_array_buffer.rs @@ -8,7 +8,10 @@ use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::{JsObject, PropAttributes}; /// 把 ArrayBuffer 构造器与原型方法绑定到 global。 -pub fn bind_array_buffer(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@species` 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_array_buffer(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let ctor_ptr = session.builtin_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; @@ -37,7 +40,7 @@ pub fn bind_array_buffer(core: &Arc, session: &KernelSession, global core, session, ctor, - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), "get [Symbol.species]", oxide_builtins::array::array_species_get:: as *const (), ); diff --git a/crates/oxide_vm/src/bindings/bind_async_disposable_stack.rs b/crates/oxide_vm/src/bindings/bind_async_disposable_stack.rs index 6111d5ae..08037844 100644 --- a/crates/oxide_vm/src/bindings/bind_async_disposable_stack.rs +++ b/crates/oxide_vm/src/bindings/bind_async_disposable_stack.rs @@ -16,7 +16,10 @@ use crate::bindings::{ /// 幂等:proto 上已有 `use` 方法(全新 proto 或已完整绑定)时整组跳过, /// 保留原型经 dirty reset 重复经过时安全。`@@asyncDispose` 别名须在 /// `disposeAsync` 绑定之后调用(读源槽 lookup_position,顺序敏感)。 -pub fn bind_async_disposable_stack_protos(core: &Arc, session: &KernelSession) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_async_disposable_stack_protos(core: &Arc, session: &KernelSession, realm_id: u32) { let world = session.builtin_world(); let proto_ptr = world.async_disposable_stack_proto.as_ptr() as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; @@ -61,10 +64,10 @@ pub fn bind_async_disposable_stack_protos(core: &Arc, session: &Kern oxide_builtins::disposable_stack::async_disposable_stack_disposed_getter:: as *const (), ); // @@asyncDispose 与 disposeAsync 为同一函数对象(先绑 disposeAsync 再取源槽)。 - bind_well_known_method_alias(core, proto, "disposeAsync", 11); + bind_well_known_method_alias(core, proto, "disposeAsync", 11, realm_id); let sf = core.perm_interner().as_ref(); 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)); + bind_well_known_data_property(core, proto, 9, tag, PropAttributes::new(false, false, true), realm_id); } /// 把 `AsyncDisposableStack` 构造器绑定到 global(init 与 full_reset global 重建共用)。 @@ -72,7 +75,12 @@ pub fn bind_async_disposable_stack_protos(core: &Arc, session: &Kern /// proto.constructor 已有则复用(dirty reset 保留路径);否则 Box 自建构造器 /// (proto=Function.prototype,prototype 槽=AsyncDisposableStack.prototype, /// 描述符按规范)。幂等:protos 安装与 global 槽写入均自带重复跳过。 -pub fn bind_async_disposable_stack(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_async_disposable_stack( + core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32, +) { let world = session.builtin_world(); let proto_ptr = world.async_disposable_stack_proto.as_ptr() as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; @@ -145,7 +153,7 @@ pub fn bind_async_disposable_stack(core: &Arc, session: &KernelSessi }; write_proto_constructor(core, proto, ctor_val); - bind_async_disposable_stack_protos(core, session); + bind_async_disposable_stack_protos(core, session, realm_id); bind_global_value(core, global, "AsyncDisposableStack", ctor_val); } diff --git a/crates/oxide_vm/src/bindings/bind_bigint.rs b/crates/oxide_vm/src/bindings/bind_bigint.rs index fe173ccc..5a0cc185 100644 --- a/crates/oxide_vm/src/bindings/bind_bigint.rs +++ b/crates/oxide_vm/src/bindings/bind_bigint.rs @@ -12,7 +12,10 @@ use oxide_types::value::JsValue; /// 构造器/原型对象由 `BuiltinWorld` 创建(含 name/prototype/constructor 互指), /// 这里只配置 native 实现并挂方法。`BigInt(value)` 当函数调用时返回 BigInt 值; /// `new BigInt()` 抛 TypeError(BigInt 不可 new)。 -pub fn bind_bigint(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_bigint(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let world = session.builtin_world(); let ctor_ptr = world.bigint_constructor.as_ptr() as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; @@ -57,7 +60,7 @@ pub fn bind_bigint(core: &Arc, 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)); + bind_well_known_data_property(core, proto, 9, tag_value, PropAttributes::new(false, false, true), realm_id); bind_global_value(core, global, "BigInt", JsValue::from_js_object(ctor_ptr)); } diff --git a/crates/oxide_vm/src/bindings/bind_disposable_stack.rs b/crates/oxide_vm/src/bindings/bind_disposable_stack.rs index 85c4e82c..8a6b45b5 100644 --- a/crates/oxide_vm/src/bindings/bind_disposable_stack.rs +++ b/crates/oxide_vm/src/bindings/bind_disposable_stack.rs @@ -15,7 +15,10 @@ use crate::bindings::{ /// 幂等:proto 上已有 `use` 方法(全新 proto 或已完整绑定)时整组跳过, /// 保留原型经 dirty reset 重复经过时安全。`@@dispose` 别名须在 `dispose` /// 绑定之后调用(读源槽 lookup_position,顺序敏感)。 -pub fn bind_disposable_stack_protos(core: &Arc, session: &KernelSession) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_disposable_stack_protos(core: &Arc, session: &KernelSession, realm_id: u32) { let world = session.builtin_world(); let proto_ptr = world.disposable_stack_proto.as_ptr() as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; @@ -64,10 +67,10 @@ pub fn bind_disposable_stack_protos(core: &Arc, session: &KernelSess oxide_builtins::disposable_stack::disposable_stack_disposed_getter:: as *const (), ); // @@dispose 与 dispose 为同一函数对象(先绑 dispose 再取源槽)。 - bind_well_known_method_alias(core, proto, "dispose", 12); + bind_well_known_method_alias(core, proto, "dispose", 12, realm_id); let sf = core.perm_interner().as_ref(); 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)); + bind_well_known_data_property(core, proto, 9, tag, PropAttributes::new(false, false, true), realm_id); } /// 在 proto 上写 `constructor` 数据属性(非枚举,描述符 {t,f,t})。 @@ -90,7 +93,10 @@ pub(crate) fn write_proto_constructor(core: &Arc, proto: &mut JsObje /// proto.constructor 已有则复用(dirty reset 保留路径);否则 Box 自建构造器 /// (proto=Function.prototype,prototype 槽=DisposableStack.prototype,描述符按规范)。 /// 幂等:protos 安装与 global 槽写入均自带重复跳过。 -pub fn bind_disposable_stack(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_disposable_stack(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let world = session.builtin_world(); let proto_ptr = world.disposable_stack_proto.as_ptr() as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; @@ -162,7 +168,7 @@ pub fn bind_disposable_stack(core: &Arc, session: &KernelSession, gl }; write_proto_constructor(core, proto, ctor_val); - bind_disposable_stack_protos(core, session); + bind_disposable_stack_protos(core, session, realm_id); bind_global_value(core, global, "DisposableStack", ctor_val); } diff --git a/crates/oxide_vm/src/bindings/bind_function.rs b/crates/oxide_vm/src/bindings/bind_function.rs index 9f2472c0..62346788 100644 --- a/crates/oxide_vm/src/bindings/bind_function.rs +++ b/crates/oxide_vm/src/bindings/bind_function.rs @@ -10,7 +10,10 @@ use super::bind_global_value; use super::configure_native_constructor; /// 把 Function 构造器与原型方法绑定到 global。 -pub fn bind_function(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@hasInstance` 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_function(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let function_methods = FunctionMethods { call: oxide_builtins::function::function_call:: as *const (), apply: oxide_builtins::function::function_apply:: as *const (), @@ -22,6 +25,7 @@ pub fn bind_function(core: &Arc, session: &KernelSession, global: &m &function_methods, core.perm_interner().as_ref(), core.shape_forge().as_ref(), + realm_id, ); let function_ctor = session.builtin_world().function_constructor.as_ptr() as *mut JsObject; diff --git a/crates/oxide_vm/src/bindings/bind_map.rs b/crates/oxide_vm/src/bindings/bind_map.rs index a9a55e8a..f5226362 100644 --- a/crates/oxide_vm/src/bindings/bind_map.rs +++ b/crates/oxide_vm/src/bindings/bind_map.rs @@ -9,7 +9,10 @@ use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; /// 把 Map 构造器与原型方法绑定到 global。 -pub fn bind_map(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_map(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let ctor_ptr = session.builtin_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; @@ -42,7 +45,7 @@ pub fn bind_map(core: &Arc, session: &KernelSession, global: &mut Js ); // Map 的 @@iterator(Symbol.iterator)是 entries 的同一函数对象。 - bind_well_known_method_alias(core, proto, "entries", 0); + bind_well_known_method_alias(core, proto, "entries", 0, realm_id); bind_accessor_getter(core, session, proto, "size", oxide_builtins::map::map_size:: as *const ()); // Map[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析 @@ -51,7 +54,7 @@ pub fn bind_map(core: &Arc, session: &KernelSession, global: &mut Js core, session, ctor, - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), "get [Symbol.species]", oxide_builtins::array::array_species_get:: as *const (), ); diff --git a/crates/oxide_vm/src/bindings/bind_regexp.rs b/crates/oxide_vm/src/bindings/bind_regexp.rs index 353bc477..923b559d 100644 --- a/crates/oxide_vm/src/bindings/bind_regexp.rs +++ b/crates/oxide_vm/src/bindings/bind_regexp.rs @@ -10,7 +10,10 @@ use oxide_types::object::JsObject; use crate::bind_constructor; /// 把 RegExp 构造器与原型方法绑定到 global。 -pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let ctor_ptr = session.builtin_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; @@ -121,6 +124,7 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut "[Symbol.match]", oxide_builtins::regexp::regexp_symbol_match:: as *const (), 1, + realm_id, ); bind_well_known_method( world, @@ -130,6 +134,7 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut "[Symbol.replace]", oxide_builtins::regexp::regexp_symbol_replace:: as *const (), 2, + realm_id, ); bind_well_known_method( world, @@ -139,6 +144,7 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut "[Symbol.search]", oxide_builtins::regexp::regexp_symbol_search:: as *const (), 1, + realm_id, ); bind_well_known_method( world, @@ -148,6 +154,7 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut "[Symbol.split]", oxide_builtins::regexp::regexp_symbol_split:: as *const (), 2, + realm_id, ); bind_well_known_method( world, @@ -157,6 +164,7 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut "[Symbol.matchAll]", oxide_builtins::regexp::regexp_symbol_match_all:: as *const (), 1, + realm_id, ); // RegExp[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析 @@ -165,7 +173,7 @@ pub fn bind_regexp(core: &Arc, session: &KernelSession, global: &mut core, session, ctor, - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), "get [Symbol.species]", oxide_builtins::array::array_species_get:: as *const (), ); diff --git a/crates/oxide_vm/src/bindings/bind_set.rs b/crates/oxide_vm/src/bindings/bind_set.rs index e9a809c7..3f7f3d03 100644 --- a/crates/oxide_vm/src/bindings/bind_set.rs +++ b/crates/oxide_vm/src/bindings/bind_set.rs @@ -9,7 +9,10 @@ use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::JsObject; /// 把 Set 构造器与原型方法绑定到 global。 -pub fn bind_set(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_set(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let ctor_ptr = session.builtin_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; @@ -50,7 +53,7 @@ pub fn bind_set(core: &Arc, 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); + bind_well_known_method_alias(core, proto, "values", 0, realm_id); bind_accessor_getter(core, session, proto, "size", oxide_builtins::set::set_size:: as *const ()); // Set[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析 @@ -59,7 +62,7 @@ pub fn bind_set(core: &Arc, session: &KernelSession, global: &mut Js core, session, ctor, - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES), "get [Symbol.species]", oxide_builtins::array::array_species_get:: as *const (), ); diff --git a/crates/oxide_vm/src/bindings/bind_string.rs b/crates/oxide_vm/src/bindings/bind_string.rs index 175fcb10..da1f59e4 100644 --- a/crates/oxide_vm/src/bindings/bind_string.rs +++ b/crates/oxide_vm/src/bindings/bind_string.rs @@ -7,7 +7,10 @@ use oxide_types::object::{JsObject, PropAttributes}; use oxide_types::value::JsValue; /// 把 String 构造器与原型方法绑定到 global。 -pub fn bind_string(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@iterator` 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_string(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let string_methods = StringMethods { from_char_code: oxide_builtins::string::string_from_char_code:: as *const (), index_of: oxide_builtins::string::string_index_of:: as *const (), @@ -95,10 +98,11 @@ pub fn bind_string(core: &Arc, session: &KernelSession, global: &mut "[Symbol.iterator]", oxide_builtins::string::string_symbol_iterator:: as *const (), 0, + realm_id, ); // 捕获默认迭代器函数对象指针写入 world:String 臂覆盖判定以此做指针比较。 // 此时槽为初始数据属性(用户覆盖尚未可能),读回即默认函数本体。 - let iter_key = oxide_types::private_key::make_well_known_symbol_key(0); + 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 v = proto.get_prop_at(pos); if v.is_object() { diff --git a/crates/oxide_vm/src/bindings/bind_stubs.rs b/crates/oxide_vm/src/bindings/bind_stubs.rs index c3f95a9e..3d881e4b 100644 --- a/crates/oxide_vm/src/bindings/bind_stubs.rs +++ b/crates/oxide_vm/src/bindings/bind_stubs.rs @@ -60,7 +60,10 @@ fn set_data_property(core: &Arc, obj: &mut JsObject, si: u32, value: /// stub 的 `constructor` 与 @@toStringTag)——规范 25.1 的 %Proxy% 无 /// prototype 属性,不装;描述符均不可枚举,`prototype` 另不可写、不可配置。 /// 原型对象登记进 world 释放登记表,与 stub 对象同生死,session 收尾统一释放。 -pub fn bind_stubs(core: &Arc, session: &mut KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_stubs(core: &Arc, session: &mut KernelSession, global: &mut JsObject, realm_id: u32) { let builtin_world = Arc::get_mut(&mut session.builtin_world) .expect("BuiltinWorld must be uniquely owned during init_kernel_builtins"); let object_proto_ptr = builtin_world.object_proto.as_ptr() as *mut JsObject; @@ -92,7 +95,8 @@ pub fn bind_stubs(core: &Arc, session: &mut KernelSession, global: & PropAttributes::new(true, false, true), ); if let Some(tag_name) = tag { - let tag_key = oxide_types::private_key::make_well_known_symbol_key( + let tag_key = oxide_types::private_key::encode_symbol_key( + realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG, ); let tag_val = diff --git a/crates/oxide_vm/src/bindings/bind_symbol.rs b/crates/oxide_vm/src/bindings/bind_symbol.rs index 79997a39..a2d2009c 100644 --- a/crates/oxide_vm/src/bindings/bind_symbol.rs +++ b/crates/oxide_vm/src/bindings/bind_symbol.rs @@ -5,13 +5,16 @@ use crate::bindings::{ }; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_types::object::{JsObject, PropAttributes}; -use oxide_types::private_key::{make_well_known_symbol_key, WELL_KNOWN_SYMBOL_TO_PRIMITIVE}; +use oxide_types::private_key::{encode_symbol_key, WELL_KNOWN_SYMBOL_TO_PRIMITIVE}; use oxide_types::value::JsValue; use crate::bind_constructor; /// 把 Symbol 构造器与原型方法绑定到 global(含 `Symbol.iterator` 等 well-known symbols)。 -pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let ctor_ptr = session.builtin_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; @@ -57,8 +60,9 @@ pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut "[Symbol.toPrimitive]", oxide_builtins::symbol::symbol_to_primitive:: as *const (), 1, + realm_id, ); - let to_prim_key = make_well_known_symbol_key(WELL_KNOWN_SYMBOL_TO_PRIMITIVE); + 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) { proto.set_data_meta(pos, PropAttributes::new(false, false, true)); proto.bump_generation(); diff --git a/crates/oxide_vm/src/bindings/bind_temporal.rs b/crates/oxide_vm/src/bindings/bind_temporal.rs index c2ffc51d..466e0b6e 100644 --- a/crates/oxide_vm/src/bindings/bind_temporal.rs +++ b/crates/oxide_vm/src/bindings/bind_temporal.rs @@ -9,7 +9,10 @@ use oxide_types::object::{JsObject, PropAttributes}; use oxide_types::value::JsValue; /// 把 Temporal 命名空间及其子对象绑定到 global。 -pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let world = session.builtin_world(); let temporal_ptr = world.temporal_object.as_ptr() as *mut JsObject; let temporal = unsafe { &mut *temporal_ptr }; @@ -129,6 +132,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.Instant").0), ), PropAttributes::new(false, false, true), + realm_id, ); // Temporal.ZonedDateTime:最小构造器与三个稳定内部槽 getter。 @@ -383,6 +387,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.ZonedDateTime").0), ), PropAttributes::new(false, false, true), + realm_id, ); apply_binding_table( world, @@ -734,6 +739,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.PlainTime").0), ), PropAttributes::new(false, false, true), + realm_id, ); // Temporal.PlainDateTime:ISO 日期时间分量、拆分转换与禁止隐式原始值转换。 @@ -893,6 +899,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.PlainDateTime").0), ), PropAttributes::new(false, false, true), + realm_id, ); // Temporal.Duration:构造器、from、分量 getter 与 ISO 字符串转换。 @@ -981,6 +988,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.Duration").0), ), PropAttributes::new(false, false, true), + realm_id, ); // Temporal.PlainMonthDay:构造器、3 个分量 getter 与 toString/toJSON。 @@ -1069,6 +1077,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.PlainMonthDay").0), ), PropAttributes::new(false, false, true), + realm_id, ); // Temporal.PlainYearMonth:构造器、10 个 getter 与 toString/toJSON。 @@ -1194,6 +1203,7 @@ pub fn bind_temporal(core: &Arc, session: &KernelSession, global: &m .string_ptr(core.perm_interner().intern("Temporal.PlainYearMonth").0), ), PropAttributes::new(false, false, true), + realm_id, ); // 把子对象挂到 Temporal 命名空间对象上,再把 Temporal 挂到 global。 diff --git a/crates/oxide_vm/src/bindings/bind_typed_array.rs b/crates/oxide_vm/src/bindings/bind_typed_array.rs index 3155bedf..f585ed54 100644 --- a/crates/oxide_vm/src/bindings/bind_typed_array.rs +++ b/crates/oxide_vm/src/bindings/bind_typed_array.rs @@ -11,7 +11,10 @@ use oxide_types::value::JsValue; /// 把 `%TypedArray%` 抽象构造器的 native 实现配置为恒抛 TypeError(不可 new/不可调用), /// 设置 `length` 属性为 0,并挂载静态 `of`/`from`(具体构造器经原型链继承)。 -fn bind_typed_array_abstract_ctor(core: &Arc, session: &KernelSession) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@species` 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +fn bind_typed_array_abstract_ctor(core: &Arc, session: &KernelSession, realm_id: u32) { let ctor_ptr = session.builtin_world().typed_array_constructor.as_ptr() as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; configure_native_constructor( @@ -61,7 +64,7 @@ fn bind_typed_array_abstract_ctor(core: &Arc, session: &KernelSessio // (及派生类)沿原型链解析 @@species 得自身(具体构造器无 own 属性)。绑定站 // 与 TA 构造器后续消费面改造共用,先查槽位防重复绑定追加第二访问器槽。 let species_key = - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES); + 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() { bind_accessor_getter_key( core, @@ -112,7 +115,10 @@ macro_rules! bind_typed_array_constructor { } /// 把所有 TypedArray 家族构造器(Int8Array/Uint8Array/.../BigUint64Array)与其共享原型绑定到 global。 -pub fn bind_typed_array(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_typed_array(core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32) { let shared_proto_ptr = session.builtin_world().typed_array_proto.as_ptr() as *mut JsObject; let shared_proto = unsafe { &mut *shared_proto_ptr }; apply_binding_table( @@ -214,7 +220,7 @@ pub fn bind_typed_array(core: &Arc, session: &KernelSession, global: ); // `keys` 已由方法表独立绑定(索引流 ≠ 值流);@@iterator 与 `values` // 共享同一函数对象。 - bind_well_known_method_alias(core, shared_proto, "values", 0); + bind_well_known_method_alias(core, shared_proto, "values", 0, realm_id); // 原型访问器:视图属性(buffer/byteOffset/byteLength/length)读内部数据槽, // @@toStringTag 返回具体类型名,供 Object.prototype.toString 区分类型。 @@ -250,7 +256,7 @@ pub fn bind_typed_array(core: &Arc, session: &KernelSession, global: core, session, shared_proto, - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG), + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG), "get [Symbol.toStringTag]", oxide_builtins::typed_array::typed_array_to_string_tag_getter:: as *const (), ); @@ -352,7 +358,7 @@ pub fn bind_typed_array(core: &Arc, session: &KernelSession, global: 1, ); - bind_typed_array_abstract_ctor(core, session); + bind_typed_array_abstract_ctor(core, session, realm_id); // 把 `%TypedArray%` 抽象构造器暴露为全局 `TypedArray`(具体构造器的 [[Prototype]])。 let abstract_ctor_val = diff --git a/crates/oxide_vm/src/bindings/bind_weak.rs b/crates/oxide_vm/src/bindings/bind_weak.rs index 56cfc905..e0f3e445 100644 --- a/crates/oxide_vm/src/bindings/bind_weak.rs +++ b/crates/oxide_vm/src/bindings/bind_weak.rs @@ -48,7 +48,10 @@ fn bind_labeled_method( /// 经 `bind_constructor!` 原位安装(既有槽更新槽值,不追加新槽)。 /// - 方法 wrapper 带族名站点标签登记复用键,选择性重建时按键迁移, /// 登记表跨重建不增长。 -pub fn bind_weak_map(core: &Arc, session: &mut KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是目标所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_weak_map(core: &Arc, session: &mut KernelSession, global: &mut JsObject, realm_id: u32) { // world 唯一属主期:全程走可变引用(stub_objects 留存 + 释放登记同表)。 let world = Arc::get_mut(&mut session.builtin_world) .expect("BuiltinWorld must be uniquely owned during init_kernel_builtins"); @@ -87,7 +90,7 @@ pub fn bind_weak_map(core: &Arc, session: &mut KernelSession, global let ctor_pos = proto.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1); proto.set_data_meta(ctor_pos, PropAttributes::new(true, false, true)); let tag_key = - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG); + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG); let tag_shape = core.shape_forge().make_shape(proto.shape_id(), tag_key); proto.set_shape_id(tag_shape); proto.ensure_hash_props().push(JsValue::perm_string( diff --git a/crates/oxide_vm/src/bindings/mod.rs b/crates/oxide_vm/src/bindings/mod.rs index a09ee440..1f9aeae9 100644 --- a/crates/oxide_vm/src/bindings/mod.rs +++ b/crates/oxide_vm/src/bindings/mod.rs @@ -354,15 +354,19 @@ pub(crate) fn bind_method_alias(core: &Arc, proto: &mut JsObject, so /// 在原型上按 well-known symbol 键绑定方法(键不字符串 intern,读键经 /// `property_key_si` 的 well-known 分支映射到同一键)。 +/// +/// `realm_id` 是目标所属 realm 的编号:符号键按 (realm 编号, 局部下标) 编码, +/// realm 编号为 0 时与旧编码逐字节一致。 +#[expect(clippy::too_many_arguments)] pub(crate) fn bind_well_known_method( world: &BuiltinWorld, core: &Arc, target: &mut JsObject, well_known_id: u32, method_name: &str, - func: *const (), nargs: u8, + func: *const (), nargs: u8, realm_id: u32, ) { let shape_forge = core.shape_forge().as_ref(); let string_forge = core.perm_interner().as_ref(); // SAFETY: func 是转成 *const () 的 NativeFn 函数项指针。 let fn_ptr = unsafe { oxide_types::object::NativeFnPtr::from_raw(func) }; - let key = oxide_types::private_key::make_well_known_symbol_key(well_known_id); + let key = oxide_types::private_key::encode_symbol_key(realm_id, well_known_id); let _ = oxide_kernel::builtin::BuiltinWorld::bind_method_key_static( target, shape_forge, @@ -383,8 +387,11 @@ pub(crate) fn bind_well_known_method( /// # 注意 /// well-known 键已在位时原位更新值,不追加重复 shape 槽:初始化与重绑可多轮 /// 经过同一原型,重复槽会让 delete 只删其一、读仍命中残留槽。 +/// +/// `realm_id` 是目标所属 realm 的编号:符号键按 (realm 编号, 局部下标) 编码, +/// realm 编号为 0 时与旧编码逐字节一致。 pub(crate) fn bind_well_known_method_alias( - core: &Arc, proto: &mut JsObject, source: &str, well_known_id: u32, + core: &Arc, proto: &mut JsObject, source: &str, well_known_id: u32, realm_id: u32, ) { let shape_forge = core.shape_forge().as_ref(); let string_forge = core.perm_interner().as_ref(); @@ -393,7 +400,7 @@ pub(crate) fn bind_well_known_method_alias( return; }; let value = proto.get_prop_at(pos); - let key = oxide_types::private_key::make_well_known_symbol_key(well_known_id); + let key = oxide_types::private_key::encode_symbol_key(realm_id, well_known_id); if let Some(existing) = shape_forge.lookup_position(proto.shape_id(), key) { proto.set_prop_at(existing, value); proto.set_data_meta(existing, PropAttributes::new(true, false, true)); @@ -408,10 +415,14 @@ pub(crate) fn bind_well_known_method_alias( } /// 在对象上按 well-known symbol 键绑定数据属性。 +/// +/// `realm_id` 是目标所属 realm 的编号:符号键按 (realm 编号, 局部下标) 编码, +/// realm 编号为 0 时与旧编码逐字节一致。 pub(crate) fn bind_well_known_data_property( core: &Arc, target: &mut JsObject, well_known_id: u32, value: JsValue, attributes: PropAttributes, + realm_id: u32, ) { - let key = oxide_types::private_key::make_well_known_symbol_key(well_known_id); + let key = oxide_types::private_key::encode_symbol_key(realm_id, well_known_id); let new_shape = core.shape_forge().make_shape(target.shape_id(), key); target.set_shape_id(new_shape); let pos = target.push_prop(value); @@ -455,14 +466,17 @@ pub(crate) fn bind_iterator_proto_next( /// /// 在迭代器原型全新重建后调用(object 家族 dirty 或全量初始化);各绑定点 /// 自带幂等检查,保留原型重复经过时安全跳过。 -fn bind_iterator_protos(core: &Arc, session: &KernelSession) { +/// +/// `realm_id` 是原型所属 realm 的编号:well-known 符号键按 (realm 编号, 局部 +/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +fn bind_iterator_protos(core: &Arc, session: &KernelSession, realm_id: u32) { let world = session.builtin_world(); // %IteratorPrototype% 自身可迭代:@@iterator 返回 this,经原型链被全部 // 集合迭代器继承(it[Symbol.iterator]() === it 恒等)。 let iter_proto_ptr = world.iterator_proto.as_ptr() as *mut JsObject; let iter_proto = unsafe { &mut *iter_proto_ptr }; - let sym_iter = oxide_types::private_key::make_well_known_symbol_key(0); + 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, @@ -472,6 +486,7 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { "iterator", oxide_builtins::iterator::iterator_symbol_iterator:: as *const (), 0, + realm_id, ); } @@ -496,7 +511,7 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { ); } let sym_to_string_tag = - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG); + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG); if core .shape_forge() .lookup_position(iter_proto.shape_id(), sym_to_string_tag) @@ -516,7 +531,7 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { // %IteratorPrototype% 的 @@dispose:显式资源管理下用 return 关闭迭代器。 let dispose_id = oxide_types::private_key::WELL_KNOWN_SYMBOL_DISPOSE; - let sym_dispose = oxide_types::private_key::make_well_known_symbol_key(dispose_id); + 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, @@ -526,6 +541,7 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { "[Symbol.dispose]", oxide_builtins::iterator::iterator_dispose:: as *const (), 0, + realm_id, ); } @@ -571,7 +587,8 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { // (经 return 方法关闭迭代器)。幂等:键槽已存在时跳过。 let aiter_proto_ptr = world.async_iterator_proto.as_ptr() as *mut JsObject; let aiter_proto = unsafe { &mut *aiter_proto_ptr }; - let sym_aiter = oxide_types::private_key::make_well_known_symbol_key( + let sym_aiter = oxide_types::private_key::encode_symbol_key( + realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_ITERATOR, ); if core.shape_forge().lookup_position(aiter_proto.shape_id(), sym_aiter).is_none() { @@ -583,10 +600,11 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { "[Symbol.asyncIterator]", crate::async_generator::async_generator_symbol_async_iterator as *const (), 0, + realm_id, ); } let sym_adispose = - oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_DISPOSE); + oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_DISPOSE); if core .shape_forge() .lookup_position(aiter_proto.shape_id(), sym_adispose) @@ -600,6 +618,7 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { "[Symbol.asyncDispose]", crate::async_generator::async_iterator_async_dispose as *const (), 0, + realm_id, ); } @@ -632,7 +651,7 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { { let sf = core.perm_interner().as_ref(); let tag = JsValue::perm_string(sf.string_ptr(sf.intern("Iterator Helper").0)); - bind_well_known_data_property(core, helper_proto, 9, tag, PropAttributes::new(false, false, true)); + bind_well_known_data_property(core, helper_proto, 9, tag, PropAttributes::new(false, false, true), realm_id); } // %ArrayIteratorPrototype% 服务 Array/TA 两族;Map/Set 共用按 `__mode__` @@ -668,12 +687,15 @@ fn bind_iterator_protos(core: &Arc, session: &KernelSession) { /// /// 幂等:目标已有 tag 键槽位时跳过(dirty reset 重复经过不追加重复属性槽)。 /// `%IteratorPrototype%` / BigInt 原型的 tag 已由各家族绑定点安装,不在此列。 -fn install_to_string_tags(core: &Arc, session: &KernelSession) { +/// +/// `realm_id` 是原型所属 realm 的编号:`@@toStringTag` 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +fn install_to_string_tags(core: &Arc, session: &KernelSession, realm_id: u32) { let world = session.builtin_world(); let sf = core.perm_interner().as_ref(); let sh = core.shape_forge().as_ref(); let tag_id = oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG; - let tag_key = oxide_types::private_key::make_well_known_symbol_key(tag_id); + let tag_key = oxide_types::private_key::encode_symbol_key(realm_id, tag_id); let cases: [(*mut JsObject, &str); 14] = [ (world.map_proto.as_ptr() as *mut JsObject, "Map"), (world.array_buffer_proto.as_ptr() as *mut JsObject, "ArrayBuffer"), @@ -697,7 +719,7 @@ fn install_to_string_tags(core: &Arc, session: &KernelSession) { continue; } let tag_val = JsValue::perm_string(sf.string_ptr(sf.intern(tag).0)); - bind_well_known_data_property(core, proto, tag_id, tag_val, PropAttributes::new(false, false, true)); + bind_well_known_data_property(core, proto, tag_id, tag_val, PropAttributes::new(false, false, true), realm_id); } } @@ -946,7 +968,12 @@ fn bind_stub_globals(core: &Arc, session: &KernelSession, global: &m /// /// 在 global 对象重建(dirty reset)后调用:重新配置构造器 native 函数并重绑 /// `Object`/`Array`/`Math` 等全局名、TypedArray 家族、stub 与 `globalThis`。 -pub fn bind_global_builtin_slots(core: &Arc, session: &KernelSession, global: &mut JsObject) { +/// +/// `realm_id` 是 session 所属 realm 的编号:well-known 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn bind_global_builtin_slots( + core: &Arc, session: &KernelSession, global: &mut JsObject, realm_id: u32, +) { let world = session.builtin_world(); configure_existing_ctor( @@ -1175,10 +1202,10 @@ pub fn bind_global_builtin_slots(core: &Arc, session: &KernelSession bind_reflect_global(core, session, global); bind_iterator_global(core, session, global); - bind_disposable_stack::bind_disposable_stack(core, session, global); - bind_async_disposable_stack::bind_async_disposable_stack(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_stub_globals(core, session, global); - bind_bigint::bind_bigint(core, session, global); + bind_bigint::bind_bigint(core, session, global, realm_id); bind_global_functions(core, session, global); crate::test262_host::bind_test262_host(core, session, global); let global_this = JsValue::from_js_object(global as *mut JsObject); @@ -1187,10 +1214,15 @@ pub fn bind_global_builtin_slots(core: &Arc, session: &KernelSession /// 按脏标记重绑被污染的内置对象;`dirty` 为 `None` 时绑定全部(初始化路径)。 /// +/// `realm_id` 是 session 所属 realm 的编号:well-known 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +/// /// # 注意事项 /// 维护:新增 `BuiltinDirtySet` 分组时,须同步更新本重绑映射、`BuiltinSnapshot` 与 /// `BuiltinWorld::rebuild_with_dirty()`。 -pub fn rebind_dirty_builtins(core: &Arc, session: &mut KernelSession, dirty: Option<&BuiltinDirtySet>) { +pub fn rebind_dirty_builtins( + core: &Arc, session: &mut KernelSession, dirty: Option<&BuiltinDirtySet>, realm_id: u32, +) { let global_ptr = session.global_object().as_ptr() as *mut JsObject; let global = unsafe { &mut *global_ptr }; @@ -1198,18 +1230,18 @@ pub fn rebind_dirty_builtins(core: &Arc, session: &mut KernelSession bind_object::bind_object(core, session, global); // object 家族重建连带重建 6 个迭代器原型与两资源栈原型(其链到新 // Object.prototype),须同步安装原型方法并让保留的 global 构造器指向新原型。 - bind_iterator_protos(core, session); + bind_iterator_protos(core, session, realm_id); sync_iterator_function_prototype(core, session, global); - bind_disposable_stack::bind_disposable_stack_protos(core, session); + 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); + 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); } if dirty.map_or(true, |d| d.array) { - bind_array::bind_array(core, session, global); + bind_array::bind_array(core, session, global, realm_id); } if dirty.map_or(true, |d| d.array_buffer) { - bind_array_buffer::bind_array_buffer(core, session, global); + bind_array_buffer::bind_array_buffer(core, session, global, realm_id); } if dirty.map_or(true, |d| d.shared_array_buffer) { bind_shared_array_buffer::bind_shared_array_buffer(core, session, global); @@ -1218,13 +1250,13 @@ pub fn rebind_dirty_builtins(core: &Arc, session: &mut KernelSession bind_data_view::bind_data_view(core, session, global); } if dirty.map_or(true, |d| d.typed_array_family) { - bind_typed_array::bind_typed_array(core, session, global); + bind_typed_array::bind_typed_array(core, session, global, realm_id); } if dirty.map_or(true, |d| d.error_family) { bind_error::bind_error(core, session, global); } if dirty.map_or(true, |d| d.string) { - bind_string::bind_string(core, session, global); + bind_string::bind_string(core, session, global, realm_id); } if dirty.map_or(true, |d| d.number) { bind_number::bind_number(core, session, global); @@ -1242,51 +1274,54 @@ pub fn rebind_dirty_builtins(core: &Arc, session: &mut KernelSession bind_date::bind_date(core, session, global); } if dirty.map_or(true, |d| d.set) { - bind_set::bind_set(core, session, global); + bind_set::bind_set(core, session, global, realm_id); } if dirty.map_or(true, |d| d.map) { - bind_map::bind_map(core, session, global); + bind_map::bind_map(core, session, global, realm_id); } if dirty.map_or(true, |d| d.boolean) { bind_boolean::bind_boolean(core, session, global); } if dirty.map_or(true, |d| d.function) { - bind_function::bind_function(core, session, global); + bind_function::bind_function(core, session, global, realm_id); } if dirty.map_or(true, |d| d.regexp) { - bind_regexp::bind_regexp(core, session, global); + bind_regexp::bind_regexp(core, session, global, realm_id); } if dirty.map_or(true, |d| d.symbol_family) { - bind_symbol::bind_symbol(core, session, global); + bind_symbol::bind_symbol(core, session, global, realm_id); } if dirty.map_or(true, |d| d.temporal) { - bind_temporal::bind_temporal(core, session, global); + bind_temporal::bind_temporal(core, session, global, realm_id); } if dirty.map_or(true, |d| d.stubs) { - bind_stubs::bind_stubs(core, session, global); + bind_stubs::bind_stubs(core, session, global, realm_id); // WeakMap 真构造器面与 stub 族同脏位:原型对象经 leaked 登记表迁移, // 重绑时全局槽原位更新,不占 BuiltinWorld 槽。 - bind_weak::bind_weak_map(core, session, global); + 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); + bind_bigint::bind_bigint(core, session, global, realm_id); } if dirty.map_or(true, |d| d.console) { bind_console::bind_console(core, session, global); } // tag 目标横跨多个脏分组(Map/Set/DataView/Math/JSON/迭代器原型), // 各组各自重绑后统一补装;安装点自带幂等检查。 - install_to_string_tags(core, session); + install_to_string_tags(core, session, realm_id); } /// 完整初始化一个 session 的内置对象(全量绑定 + `globalThis` + 快照记录)。 -pub fn init_kernel_builtins(core: &Arc, session: &mut KernelSession) { - rebind_dirty_builtins(core, session, None); +/// +/// `realm_id` 是 session 所属 realm 的编号:well-known 符号键按 (realm 编号, +/// 局部下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 +pub fn init_kernel_builtins(core: &Arc, session: &mut KernelSession, realm_id: u32) { + 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); - bind_async_disposable_stack::bind_async_disposable_stack(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); bind_global_value(core, global, "globalThis", JsValue::from_js_object(global_ptr)); diff --git a/crates/oxide_vm/src/vm_support.rs b/crates/oxide_vm/src/vm_support.rs index 39a4a162..ba2b340f 100644 --- a/crates/oxide_vm/src/vm_support.rs +++ b/crates/oxide_vm/src/vm_support.rs @@ -50,7 +50,10 @@ impl Vm { pub fn new() -> Self { let core = KernelCore::new(KernelConfig::minimal()); let mut session = KernelSession::new(&core); - bindings::init_kernel_builtins(&core, &mut session); + // realm 编号在构造时分配并固化:首个 realm 编号为 0(与旧符号编码一致)。 + // 须在 builtin 绑定之前分配:绑定按 (realm 编号, 局部下标) 编码 well-known 符号键。 + let realm_id = core.alloc_realm_id(); + bindings::init_kernel_builtins(&core, &mut session, realm_id); // 在 builtin 绑定之后取 id:绑定过程已 intern "length",此处命中缓存得到 // 稳定的 id,用于运行期常见属性(如函数 length 槽)的快路径。 let length_si = core.perm_interner().intern("length").0; @@ -58,8 +61,6 @@ impl Vm { let obj_proto = P::clone(&session.builtin_world().object_proto); // 提前缓存执行期字符串 GC 初始水位(构造后 config 不再变化)。 let gc_threshold = core.config().session_gc_threshold; - // realm 编号在构造时分配并固化:首个 realm 编号为 0(与旧符号编码一致)。 - let realm_id = core.alloc_realm_id(); let mut vm = Self { regs: [JsValue::undefined(); 256], pc: 0, @@ -199,7 +200,10 @@ impl Vm { /// 复用共享 `KernelCore` 创建 VM(VM 池路径),共享 intern/shape/code 缓存。 pub fn with_kernel_core(core: Arc) -> Self { let mut session = KernelSession::new(&core); - bindings::init_kernel_builtins(&core, &mut session); + // realm 编号在构造时分配并固化:首个 realm 编号为 0(与旧符号编码一致)。 + // 须在 builtin 绑定之前分配:绑定按 (realm 编号, 局部下标) 编码 well-known 符号键。 + let realm_id = core.alloc_realm_id(); + bindings::init_kernel_builtins(&core, &mut session, realm_id); // 在 builtin 绑定之后取 id:绑定过程已 intern "length",此处命中缓存得到 // 稳定的 id,用于运行期常见属性(如函数 length 槽)的快路径。 let length_si = core.perm_interner().intern("length").0; @@ -207,8 +211,6 @@ impl Vm { let obj_proto = P::clone(&session.builtin_world().object_proto); // 提前缓存执行期字符串 GC 初始水位(构造后 config 不再变化)。 let gc_threshold = core.config().session_gc_threshold; - // realm 编号在构造时分配并固化:首个 realm 编号为 0(与旧符号编码一致)。 - let realm_id = core.alloc_realm_id(); let mut vm = Self { regs: [JsValue::undefined(); 256], pc: 0, @@ -381,12 +383,22 @@ impl Vm { } let dirty = self.realm.session.borrow_mut().selective_reset(&self.kernel_core); if dirty.any_builtin_dirty() { - bindings::rebind_dirty_builtins(&self.kernel_core, &mut self.realm.session.borrow_mut(), Some(&dirty)); + bindings::rebind_dirty_builtins( + &self.kernel_core, + &mut self.realm.session.borrow_mut(), + Some(&dirty), + self.realm_id(), + ); } if dirty.global { let global_ptr = self.realm.session.borrow().global_object().as_ptr() as *mut JsObject; let global = unsafe { &mut *global_ptr }; - bindings::bind_global_builtin_slots(&self.kernel_core, &self.realm.session.borrow_mut(), global); + bindings::bind_global_builtin_slots( + &self.kernel_core, + &self.realm.session.borrow_mut(), + global, + self.realm_id(), + ); } *self.realm .object_prototype @@ -405,7 +417,7 @@ impl Vm { #[doc(hidden)] pub fn full_reset_legacy_for_bench(&mut self) { *self.realm.session.borrow_mut() = KernelSession::new(&self.kernel_core); - bindings::init_kernel_builtins(&self.kernel_core, &mut self.realm.session.borrow_mut()); + bindings::init_kernel_builtins(&self.kernel_core, &mut self.realm.session.borrow_mut(), self.realm_id()); *self.realm .object_prototype .borrow_mut() = P::clone(&self.realm.session.borrow().builtin_world().object_proto);