fix: 原型链直读改经 get_prototype_of 路由

This commit is contained in:
2026-10-18 12:24:10 +00:00
parent 659bb272c4
commit 89255abd17
11 changed files with 126 additions and 67 deletions
+13 -5
View File
@@ -5,7 +5,7 @@ use crate::{vm_debug, vm_trace};
use oxide_builtins::iterator::make_iterator_for_value;
use oxide_builtins::{builtins_debug, builtins_trace};
use oxide_bytecode::opcode;
use oxide_runtime_api::{to_boolean, NativeResult};
use oxide_runtime_api::{to_boolean, NativeResult, VmHost};
use oxide_types::object::{Cell, JsObject, PropAttributes};
use oxide_types::value::JsValue;
@@ -653,7 +653,9 @@ impl Vm {
return Ok(true);
}
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let super_ctor = callee_obj.proto();
// super 构造器取当前帧 callee 的 [[GetPrototypeOf]](规范 10.2.11 面):
// 代理函数对象经 getPrototypeOf trap 取基。
let super_ctor = self.get_prototype_of(callee_obj)?;
if !super_ctor.is_object() {
self.raise_error_kind("TypeError", "super constructor is not an object")?;
return Ok(true);
@@ -781,7 +783,9 @@ impl Vm {
let home_obj = unsafe { &*home_object.as_js_object_ptr() };
// 规范步序:GetSuperBase 先于 ToPropertyKey;基非对象可强转时抛
// TypeError(RequireObjectCoercible 面)。
let super_base = home_obj.proto();
// GetSuperBase 取 home 对象的 [[GetPrototypeOf]](规范 10.2.11 面):
// 代理 home 对象经 getPrototypeOf trap 取基。
let super_base = self.get_prototype_of(home_obj)?;
if !super_base.is_object() {
self.raise_type_error("Cannot convert null or undefined to object")?;
return Ok(true);
@@ -826,7 +830,9 @@ impl Vm {
let home_obj = unsafe { &*home_object.as_js_object_ptr() };
// 规范步序:GetSuperBase 先于 ToPropertyKey;基非对象可强转时抛
// TypeError(RequireObjectCoercible 面)。
let super_base = home_obj.proto();
// GetSuperBase 取 home 对象的 [[GetPrototypeOf]](规范 10.2.11 面):
// 代理 home 对象经 getPrototypeOf trap 取基。
let super_base = self.get_prototype_of(home_obj)?;
if !super_base.is_object() {
self.raise_type_error("Cannot convert null or undefined to object")?;
return Ok(true);
@@ -1158,7 +1164,9 @@ impl Vm {
return Ok(true);
}
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let super_ctor = callee_obj.proto();
// super 构造器取当前帧 callee 的 [[GetPrototypeOf]](规范 10.2.11 面):
// 代理函数对象经 getPrototypeOf trap 取基。
let super_ctor = self.get_prototype_of(callee_obj)?;
if !super_ctor.is_object() {
self.raise_error_kind("TypeError", "super constructor is not an object")?;
return Ok(true);
+18 -12
View File
@@ -1,6 +1,7 @@
use crate::{ic_debug, ic_trace, vm_trace};
use oxide_bytecode::opcode::{OpCode, IC_EXT_WORDS};
use oxide_runtime_api as coercion;
use oxide_runtime_api::VmHost;
use oxide_types::object::JsObject;
use oxide_types::private_key::{int_key_value, is_int_key, make_int_key, make_private_name_id};
use oxide_types::value::JsValue;
@@ -123,8 +124,10 @@ impl Vm {
/// 沿实例→proto 链查找私有方法/访问器槽(存于类的 home=proto)。字段槽不跨原型
/// (PrivateFieldFind 只查 own)——链上遇到字段槽(无 hole meta)即拒绝,防
/// `Object.create(instance)` 穿透读取实例字段。
fn find_private_method_slot(&self, obj: &JsObject, private_key: u32) -> Option<*mut JsObject> {
let mut proto = obj.proto();
fn find_private_method_slot(
&mut self, obj: &JsObject, private_key: u32,
) -> Result<Option<*mut JsObject>, String> {
let mut proto = self.get_prototype_of(obj)?;
let mut depth = 0usize;
while proto.is_object() && depth < MAX_PROTO_CHAIN_DEPTH {
depth += 1;
@@ -133,13 +136,13 @@ impl Vm {
// 方法/访问器槽有 hole 标记(私有方法)或 is_accessor 标记(私有 getter/setter);
// 字段槽(存实例)沿链出现说明接收者并非本类实例 → 拒绝穿透。
if proto_obj.prop_meta_at(pos).is_some_and(|m| m.is_hole() || m.is_accessor) {
return Some(proto_obj as *const JsObject as *mut JsObject);
return Ok(Some(proto_obj as *const JsObject as *mut JsObject));
}
return None;
return Ok(None);
}
proto = proto_obj.proto();
proto = self.get_prototype_of(proto_obj)?;
}
None
Ok(None)
}
/// 私有方法/访问器/静态字段访问的 brand 检查:接收者 own 的 brand 槽(构造时写入
@@ -185,7 +188,7 @@ impl Vm {
return Ok(());
}
// 方法路径:own 无槽(私有方法/访问器存于 home=proto)→ 沿链找方法槽 + brand 检查。
let Some(home_ptr) = self.find_private_method_slot(obj, private_key) else {
let Ok(Some(home_ptr)) = self.find_private_method_slot(obj, private_key) else {
return self.raise_type_error("private field brand check failed");
};
if brand_reg != 0 {
@@ -244,7 +247,7 @@ impl Vm {
return Ok(());
}
// 方法路径:own 无槽(私有方法/访问器存于 home=proto)→ 沿链找方法槽 + brand 检查。
let Some(home_ptr) = self.find_private_method_slot(obj, private_key) else {
let Ok(Some(home_ptr)) = self.find_private_method_slot(obj, private_key) else {
return self.raise_type_error("private field brand check failed");
};
if brand_reg != 0 {
@@ -465,8 +468,10 @@ impl Vm {
ic_debug!("IC_GET write-back own shape={} slot={}", obj.shape_id(), pos);
}
} else {
// 沿原型链查找真正拥有该属性的对象。
let mut cursor = obj.proto().as_js_object_ptr();
// 沿原型链查找真正拥有该属性的对象(逐层经 [[GetPrototypeOf]]
// 路由,代理层经 trap 取原型)。
let proto = self.get_prototype_of(obj)?;
let mut cursor = proto.as_js_object_ptr();
let mut depth = 1u8;
while !cursor.is_null() {
let co_ref = unsafe { &*cursor };
@@ -484,10 +489,11 @@ impl Vm {
}
break;
}
if !co_ref.proto().is_object() {
let next_proto = self.get_prototype_of(co_ref)?;
if !next_proto.is_object() {
break;
}
cursor = co_ref.proto().as_js_object_ptr();
cursor = next_proto.as_js_object_ptr();
depth += 1;
}
}