diff --git a/crates/oxide_kernel/src/builtin/construct.rs b/crates/oxide_kernel/src/builtin/construct.rs index f1326a10..3e8a870e 100644 --- a/crates/oxide_kernel/src/builtin/construct.rs +++ b/crates/oxide_kernel/src/builtin/construct.rs @@ -241,7 +241,8 @@ fn set_proto_if_changed(obj: &P, proto: JsValue) { /// 2. 23 个非 TypedArray 构造器的 `[[Prototype]]` → Function.prototype /// (标准内置函数对象均继承 Function.prototype); /// 3. 25 个非 Object 原型的 `[[Prototype]]` → Object.prototype,另含 -/// Temporal 命名空间对象、Temporal.now 与 Console 单例; +/// Temporal 命名空间对象、Temporal.now、Console 单例与 Math/JSON +/// 命名空间对象; /// 4. %IteratorPrototype% → Object.prototype,6 个集合迭代器原型 /// → %IteratorPrototype%; /// 5. TypedArray 家族:11 个具体原型 → %TypedArray% 共享原型,11 个具体 @@ -362,6 +363,10 @@ pub(crate) fn wire_builtin_world_links(world: &BuiltinWorld) { // Console 对象(单例命名空间)继承 Object.prototype。 set_proto_if_changed(&world.console_object, obj_proto_val); + // Math / JSON 命名空间对象(非构造器)继承 Object.prototype。 + set_proto_if_changed(&world.math_object, obj_proto_val); + set_proto_if_changed(&world.json_object, obj_proto_val); + // 迭代器原型链:%IteratorPrototype% → Object.prototype;各集合迭代器原型 // → %IteratorPrototype%(next/@@iterator 方法由绑定层——oxide_builtins // 中安装方法 wrapper 的代码——安装到对应原型)。 diff --git a/crates/oxide_kernel/src/kernel/session.rs b/crates/oxide_kernel/src/kernel/session.rs index a9848f3e..dc0aee9c 100644 --- a/crates/oxide_kernel/src/kernel/session.rs +++ b/crates/oxide_kernel/src/kernel/session.rs @@ -23,8 +23,10 @@ pub struct KernelSession { } impl KernelSession { - fn new_global_object(core: &KernelCore) -> P { - let mut global_obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()); + /// 创建全局对象本体:`[[Prototype]]` 挂 Object.prototype(无代理分层 + /// 引擎的最简等价形态),并预置 NaN/undefined/Infinity 三个全局常量。 + fn new_global_object(core: &KernelCore, object_proto: JsValue) -> P { + let mut global_obj = JsObject::new_empty(EMPTY_SHAPE_ID, object_proto); let si_nan = core.perm_interner.intern("NaN").0; let si_undef = core.perm_interner.intern("undefined").0; @@ -65,7 +67,8 @@ impl KernelSession { /// 第二次及后续调用时命中缓存。 pub fn new(core: &KernelCore) -> Self { let builtin_world = Arc::new(BuiltinWorld::new(&core.perm_interner, &core.shape_forge)); - let global_object = Self::new_global_object(core); + let object_proto_val = JsValue::from_js_object(builtin_world.object_proto.as_ptr() as *mut JsObject); + let global_object = Self::new_global_object(core, object_proto_val); let builtin_snapshot = BuiltinSnapshot::new(&builtin_world, &global_object); Self { @@ -244,7 +247,10 @@ impl KernelSession { // 旧 global 的属性区在替换前释放,避免旧引用长期持有该内存。 let old_global = unsafe { &mut *(self.global_object.as_ptr() as *mut JsObject) }; old_global.release_raw_heap(); - self.global_object = Self::new_global_object(core); + // proto 取当前(可能旧)world 的 ObjectProto;object 家族脏重建后 + // 由下方收尾重指修正。 + let object_proto_val = JsValue::from_js_object(self.builtin_world.object_proto.as_ptr() as *mut JsObject); + self.global_object = Self::new_global_object(core, object_proto_val); } if dirty.any_builtin_dirty() { let old_world = self.builtin_world.clone(); @@ -263,7 +269,15 @@ impl KernelSession { // (Function/Object 4 个对象本体永久保留、属性区同批释放);原型 // 槽改写须先于释放、先于旧 world 被替换完成。 new_world.retire_replaced(&old_world); + // 保留 global 的 proto 槽重指:object 家族脏重建替换 ObjectProto, + // global 不在 BuiltinWorld 内,retire_replaced 不覆盖。 + let new_obj_proto = new_world.object_proto.as_ptr(); + let old_obj_proto = old_world.object_proto.as_ptr(); self.builtin_world = Arc::new(new_world); + if new_obj_proto != old_obj_proto { + let global = unsafe { &mut *(self.global_object.as_ptr() as *mut JsObject) }; + global.set_proto(JsValue::from_js_object(new_obj_proto as *mut JsObject)).ok(); + } } dirty } diff --git a/crates/oxide_kernel/tests/builtin_world_tests.rs b/crates/oxide_kernel/tests/builtin_world_tests.rs index 91431dde..a427ae6e 100644 --- a/crates/oxide_kernel/tests/builtin_world_tests.rs +++ b/crates/oxide_kernel/tests/builtin_world_tests.rs @@ -69,6 +69,21 @@ fn test_protos_have_null_proto() { assert!(w.symbol_proto.proto().is_object()); } +#[test] +fn test_math_json_proto_links_to_object_proto() { + let w = make_world(); + let obj_proto_ptr = w.object_proto.as_ptr() as *mut JsObject; + // Math/JSON 命名空间对象的 proto 槽应指向 Object.prototype 本体。 + assert!( + std::ptr::eq(w.math_object.proto().as_js_object_ptr(), obj_proto_ptr), + "Math namespace object should inherit Object.prototype" + ); + assert!( + std::ptr::eq(w.json_object.proto().as_js_object_ptr(), obj_proto_ptr), + "JSON namespace object should inherit Object.prototype" + ); +} + #[test] fn test_shapes_populated() { let w = make_world();