fix: delete 真正删除属性(shape 链重建 + 数组元素 hole 标记)

字节码 delete 原先只清值为 undefined,属性残留在 shape 链,hasOwnProperty/
keys/枚举仍可见。统一走共享 delete_own_property(与 Reflect.deleteProperty
一致):
- 命名属性经 shape 链重建移除,数组重建前保存并恢复元素区
- 数组下标元素标记为 hole(PropMetaEntry.hole),length 不变,
  存在性检查(resolve_property/get_own_property_slot/ordinary_get/for-in)
  判 hole,重赋值自动清除标记
- 不可配置属性统一返回 false(sloppy 语义,strict 抛错留待 emit 追踪严格模式)
- set_or_create_prop_value 数组下标键路由元素区,修复 delete 后重赋值误入
  shape 链

test262 Object +212 PASS/-102 FAIL,Array +149 PASS/-60 FAIL,无回归。
This commit is contained in:
2026-08-08 02:25:13 +08:00
parent 8f5446aa8a
commit 0b68baa802
8 changed files with 275 additions and 83 deletions
+6 -4
View File
@@ -37,9 +37,7 @@ impl Vm {
}
// native 方法(非构造器)不可 new。
if ctor_obj.native_fn().is_some() && ctor_obj.type_tag != oxide_types::object::JsObject::OBJ_TYPE_CONSTRUCTOR {
return self
.raise_type_error("object is not a constructor")
.map(|_| true);
return self.raise_type_error("object is not a constructor").map(|_| true);
}
let ext = self.bytecode[self.pc];
@@ -321,10 +319,14 @@ impl Vm {
// 数组把整型下标元素存在 prop_vec,而 prop_vec 不属于 shape 链。
// 单独枚举它们(ES:数组下标是可枚举字符串键,按升序排在其它自有键之前)。
// hole(删除标记)跳过——for-in 不枚举数组稀疏空洞。
if current.is_object() {
let arr = unsafe { &*current.as_js_object_ptr() };
if arr.is_array() {
for i in 0..arr.prop_vec_len() {
for i in 0..arr.array_prop_count {
if arr.prop_meta_at(i).is_some_and(|m| m.is_hole()) {
continue;
}
let is_enum = arr
.prop_meta_at(i)
.map(|m| m.attributes.enumerable())