mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: ArraySetLength 收缩遇不可配置元素静默失败、ToPrimitive 异常透传与既有属性描述符缺省回填
- arr.length 收缩时若 [newLen, oldLen) 内存在不可配置元素,整个收缩失败且不做任何修改(sloppy 赋值静默 no-op),不再抛错或截断 - length 赋值 ToPrimitive(valueOf/toString)抛错时按主 dispatch 约定直接返回,避免二次抛 RangeError 覆盖原异常(S15.4.5.1_A1.3_T2) - Object.defineProperty/defineProperties/create 对已有属性省略描述符字段时保持现有属性值(无显式 meta 按 DEFAULT_DATA 回填),修复 toReversed/toSorted/toSpliced/with length-decreased-while-iterating
This commit is contained in:
@@ -506,9 +506,14 @@ fn define_from_descriptor<H: VmHost>(
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
vm.get_own_property_slot(obj, key_si)
|
||||
};
|
||||
let existing_meta = existing_pos.and_then(|pos| {
|
||||
let existing_meta = existing_pos.map(|pos| {
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
obj.prop_meta_at(pos)
|
||||
// 已有属性无显式 meta(普通数据属性/数组元素)时按默认属性回填:
|
||||
// 描述符缺省字段保持现有值(writable/enumerable/configurable 均 true),
|
||||
// 而非按新属性处理为 false(Object.defineProperty 省略字段不改已有属性)。
|
||||
obj.prop_meta_at(pos).unwrap_or_else(|| {
|
||||
oxide_types::object::PropMetaEntry::data(PropAttributes::DEFAULT_DATA)
|
||||
})
|
||||
});
|
||||
|
||||
// 修改已有属性时缺省字段回填现有值,仅定义新属性时缺省才为 false。
|
||||
|
||||
@@ -182,7 +182,14 @@ impl Vm {
|
||||
// prop_count/迭代/内置方法看到的长度不一致。
|
||||
let length_si = self.kernel_core.perm_interner().intern("length").0;
|
||||
if obj.is_array() && prop_name_si == length_si {
|
||||
let pc_before = self.pc;
|
||||
let number_len = self.coerce_number_bounded(val)?;
|
||||
// ToPrimitive 抛错(valueOf/toString throw)已被 unwind 定向到外围 catch 时
|
||||
// pc 指向 catch 入口:主 dispatch 约定异常后 opcode 不得继续 raise,直接
|
||||
// 返回由 dispatch 继续执行 catch,避免二次抛错覆盖原异常。
|
||||
if self.pc != pc_before {
|
||||
return Ok(());
|
||||
}
|
||||
let raw_new_len = if number_len == 0.0 || !number_len.is_finite() {
|
||||
0
|
||||
} else {
|
||||
@@ -192,7 +199,19 @@ impl Vm {
|
||||
if raw_new_len as f64 != number_len {
|
||||
return self.raise_error_kind("RangeError", "Invalid array length");
|
||||
}
|
||||
let old_logical = obj.logical_len() as usize;
|
||||
let old_count = obj.array_prop_count as usize;
|
||||
// ArraySetLength:收缩时若 [newLen, oldLen) 内存在不可配置元素,整个收缩
|
||||
// 失败且不做任何修改(sloppy 赋值静默失败;VM 未实现 strict 标志,统一按 no-op)。
|
||||
if raw_new_len < old_logical {
|
||||
for idx in raw_new_len..old_count {
|
||||
if let Some(meta) = obj.prop_meta_at(idx) {
|
||||
if !meta.attributes.configurable() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dense storage caps at MAX_DENSE_PROPS; larger lengths stay at the cap.
|
||||
let new_len_u = raw_new_len.min(oxide_types::object::MAX_DENSE_PROPS);
|
||||
obj.set_prop_count(new_len_u);
|
||||
|
||||
Reference in New Issue
Block a user