fix: 大数组索引写降级命名属性并扩展逻辑长度

This commit is contained in:
2026-09-29 13:05:37 +00:00
parent 0c4fed0373
commit f70de8cb43
6 changed files with 366 additions and 45 deletions
+1 -1
View File
@@ -282,7 +282,7 @@ pub(crate) fn check_array_create_len<H: VmHost>(vm: &mut H, n: usize) -> Result<
pub(crate) fn array_length_arg<H: VmHost>(vm: &mut H, value: JsValue) -> Result<usize, JsValue> {
let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN);
if !n.is_finite() || n < 0.0 || n.fract() != 0.0 || n > MAX_DENSE_PROPS as f64 {
if !n.is_finite() || n < 0.0 || n.fract() != 0.0 || n > u32::MAX as f64 {
return Err(crate::error::create_range_error(vm, "Invalid array length"));
}
Ok(n as usize)
+3 -2
View File
@@ -27,8 +27,9 @@ pub fn array_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
};
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, proto_val, n, vm.epoch().bump()));
// 数值长度分支建 n 个空洞而非 present-undefined:`in`、for-in、
// Object.keys 按缺失处理,元素 Get 落原型链。
for i in 0..n {
// Object.keys 按缺失处理,元素 Get 落原型链。物理区以稠密上限
// 钳位(越界索引无物理槽,逻辑长度已覆盖)。
for i in 0..n.min(MAX_DENSE_PROPS) {
unsafe {
(*arr).mark_hole_at(i);
}
+7 -5
View File
@@ -319,15 +319,17 @@ pub enum DeleteOutcome {
/// 删除对象自身属性并返回三态结果(字节码 delete 与 Reflect.deleteProperty 共用)。
///
/// 数组下标键在元素区(shape 链外),标记为 hole(值 undefined + hole meta),
/// length 不变;数组 length 虚拟属性与命名属性经 shape 链处理。仅对象自身属性
/// 参与删除判定,原型链属性不影响结果。
/// 数组下标键在元素区内时标记为 hole(值 undefined + hole meta),length 不变;
/// 越出元素区的大索引是命名属性(shape 链),落穿 shape 链查删。数组 length
/// 虚拟属性与命名属性经 shape 链处理。仅对象自身属性参与删除判定,原型链属性
/// 不影响结果。
///
/// # 步骤
/// 1. TA 数值键:界内索引返回 `NonConfigurable`(元素零修改);数字无效键
/// 返回 `Missing`;非数字串 / symbol 键落下方普通路径
/// 2. 数组 length 虚拟属性:不可配置,返回 `NonConfigurable`
/// 3. 数组下标元素:检查 configurable,`mark_hole_at` 标记为 hole
/// 3. 数组下标元素:检查 configurable,`mark_hole_at` 标记为 hole;大索引
/// 越出元素区落穿命名属性路径
/// 4. 命名属性:walk_own_keys 定位槽位,不可配置返回 `NonConfigurable`
/// 5. 数组先保存元素区(值 + meta),重建命名属性后恢复元素区
///
@@ -376,7 +378,7 @@ pub fn delete_own_property_outcome<H: VmHost>(vm: &mut H, obj: &mut JsObject, ke
obj.bump_generation();
return DeleteOutcome::Deleted;
}
return DeleteOutcome::Missing;
// 大索引越出元素区时是命名属性(shape 链),落穿下方查删路径。
}
// 非下标键:length 是虚拟属性(无 shape 槽、不在元素区),但描述符声明
// configurable:false,删除恒失败。