mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: Math/JSON/全局对象原型链挂 Object.prototype
This commit is contained in:
@@ -241,7 +241,8 @@ fn set_proto_if_changed(obj: &P<JsObject>, 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 的代码——安装到对应原型)。
|
||||
|
||||
@@ -23,8 +23,10 @@ pub struct KernelSession {
|
||||
}
|
||||
|
||||
impl KernelSession {
|
||||
fn new_global_object(core: &KernelCore) -> P<JsObject> {
|
||||
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<JsObject> {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user