feat: freeze/seal/preventExtensions 写路径拦截(逐属性 meta + extensible 检查)

freeze/seal 逐属性改写 meta(数据属性 writable/configurable=false,
访问器 configurable=false,含数组元素区),使 has_prop_meta() 恒 true,
IC 直写路径自动失效;ordinary_set/create_named_prop_fast/
set_or_create_prop_value/define_* 增补 extensible/frozen 检查,
SET_ELEM 直写入口回落 ordinary_set 或拒绝新元素。

引擎未实现 strict 标志,赋值失败统一 raise_type_error(sloppy 静默留待后续)。
This commit is contained in:
2026-08-15 20:55:20 +08:00
parent 0e32d663ce
commit a1c86a9335
4 changed files with 307 additions and 10 deletions
+14 -1
View File
@@ -2,7 +2,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_types::object::JsObject;
use oxide_types::private_key::{int_key_value, is_int_key, make_private_name_id};
use oxide_types::private_key::{int_key_value, is_int_key, make_int_key, make_private_name_id};
use oxide_types::value::JsValue;
use crate::ic_helper::{self, ic_get_hit, ic_set_hit};
@@ -606,6 +606,19 @@ impl Vm {
};
let value = self.promote_if_needed_for_write_ptr(obj_ptr, self.regs[b]);
let obj = unsafe { &mut *obj_ptr };
// 有属性 meta(freeze/seal 逐属性写 meta 后恒 true,含 accessor 元素/描述符
// 元素):回落 ordinary_set 走完整 writable/accessor/extensible 检查,防止
// 直写绕过冻结语义。
if obj.has_prop_meta() {
let si = make_int_key(idx);
return self.ordinary_set_dispatch(obj, si, value, self.regs[rd]);
}
// 无 meta 快路径:不可扩展对象禁止新增元素(越界下标);已有元素直写不受限
// (无 meta 即默认可写)。
if !obj.is_extensible() && idx >= obj.array_prop_count {
self.raise_type_error("object is not extensible")?;
return Ok(());
}
obj.set_prop_at(idx, value);
Ok(())
}