mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: TA 删除自身串键重建排除哨兵元素键防形状链物化
This commit is contained in:
@@ -419,8 +419,14 @@ pub fn delete_own_property_outcome<H: VmHost>(vm: &mut H, obj: &mut JsObject, ke
|
||||
|
||||
let retained: Vec<(u32, JsValue, Option<PropMetaEntry>)> = all_keys
|
||||
.into_iter()
|
||||
// 数组元素区由下方独立保存/恢复,此处只重建命名属性(元素键绝对下标 < 元素数)。
|
||||
.filter(|(_, pos)| *pos != delete_pos && !(obj.is_array() && *pos < obj.array_prop_count))
|
||||
// 数组元素区由下方独立保存/恢复,此处只重建命名属性(元素键绝对下标 <
|
||||
// 元素数);TA 元素键(0..live 长)元素住 buffer 不占形状链,同样排除出
|
||||
// 重建,防经空 meta 取值 undefined 物化成 shape 链真 own 属性。
|
||||
.filter(|(si, pos)| {
|
||||
*pos != delete_pos
|
||||
&& !(obj.is_array() && *pos < obj.array_prop_count)
|
||||
&& !(obj.is_typed_array_obj() && is_int_key(*si))
|
||||
})
|
||||
.map(|(si, pos)| (si, obj.get_prop_at(pos), obj.prop_meta_at(pos)))
|
||||
.collect();
|
||||
|
||||
|
||||
@@ -2039,9 +2039,61 @@ fn ta_keys_int_index_2pow32_boundary() {
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"(function () { var ks1 = Object.keys({ a: 1, '4294967295': 2 }); \
|
||||
if (ks1.join(',') !== '4294967295,a') return false; \
|
||||
var ks2 = Object.keys({ b: 1, '4294967296': 2 }); \
|
||||
return ks2.join(',') === 'b,4294967296'; })()",
|
||||
if (ks1.join(',') !== '4294967295,a') return false; \
|
||||
var ks2 = Object.keys({ b: 1, '4294967296': 2 }); \
|
||||
return ks2.join(',') === 'b,4294967296'; })()",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ta_ownkeys_stable_after_delete_str_prop() {
|
||||
// 删 own 串键后枚举键集稳定:元素键住 buffer 不占形状链,删除重建命名属性
|
||||
// 不得把元素键物化为形状节点——ownKeys/keys/gOPN 均无重复整数键。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"(function () { var ta = new Uint8Array([1, 2]); \
|
||||
ta.foo = 1; \
|
||||
if (!delete ta.foo) return false; \
|
||||
if (Reflect.ownKeys(ta).join(',') !== '0,1') return false; \
|
||||
if (Object.keys(ta).join(',') !== '0,1') return false; \
|
||||
return Object.getOwnPropertyNames(ta).join(',') === '0,1'; })()",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ta_gopd_no_phantom_after_delete_str_prop() {
|
||||
// 删 own 串键后元素位描述符不变(value + w/e/c 全真)、被删键无残留
|
||||
// 幻影 own 属性、元素值不动。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"(function () { var ta = new Uint8Array([1, 2]); \
|
||||
ta.foo = 1; delete ta.foo; \
|
||||
var d = Object.getOwnPropertyDescriptor(ta, '0'); \
|
||||
if (!d || d.value !== 1 || d.writable !== true \
|
||||
|| d.enumerable !== true || d.configurable !== true) return false; \
|
||||
if (Object.getOwnPropertyDescriptor(ta, 'foo') !== undefined) return false; \
|
||||
return ta[0] === 1 && ta[1] === 2 && ta.foo === undefined; })()",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ta_for_in_stable_after_delete_str_prop() {
|
||||
// 删 own 串键后 for-in 出元素键升序 + 无重复、无被删键残留。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"(function () { var ta = new Uint8Array([1, 2]); \
|
||||
ta.foo = 1; delete ta.foo; \
|
||||
var ks = []; for (var k in ta) ks.push(k); \
|
||||
return ks.length === 2 && ks[0] === '0' && ks[1] === '1'; })()",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
|
||||
Reference in New Issue
Block a user