fix: strict 删除非可配置属性抛错并修正数组长度

This commit is contained in:
2026-09-17 19:17:16 +00:00
parent 3de3b639d9
commit 79518ba827
5 changed files with 205 additions and 25 deletions
+31 -7
View File
@@ -649,10 +649,10 @@ impl Vm {
return Ok(false);
};
let obj = unsafe { &mut *obj_ptr };
// 统一走共享删除逻辑(与 Reflect.deleteProperty 一致);不可配置返回 false。
let deleted = oxide_builtins::object::delete_own_property(self, obj, prop_name_si);
self.regs[rd] = JsValue::bool(deleted);
Ok(false)
// 统一走共享删除逻辑(与 Reflect.deleteProperty 同源);严格模式分派见
// finish_member_delete。
let outcome = oxide_builtins::object::delete_own_property_outcome(self, obj, prop_name_si);
self.finish_member_delete(rd, outcome)
}
pub(crate) fn dispatch_delete_prop_dynamic(&mut self, rd: usize, b: usize) -> Result<bool, String> {
@@ -667,9 +667,33 @@ impl Vm {
return Ok(false);
};
let obj = unsafe { &mut *obj_ptr };
// 统一走共享删除逻辑(与 Reflect.deleteProperty 一致);不可配置返回 false。
let deleted = oxide_builtins::object::delete_own_property(self, obj, prop_name_si);
self.regs[rd] = JsValue::bool(deleted);
// 统一走共享删除逻辑(与 Reflect.deleteProperty 同源);严格模式分派见
// finish_member_delete。
let outcome = oxide_builtins::object::delete_own_property_outcome(self, obj, prop_name_si);
self.finish_member_delete(rd, outcome)
}
/// 成员形 delete 的结果分派:不可配置属性在严格模式抛 TypeError(规范要求
/// delete 运算符对 [[Delete]] 返回 false 的引用抛错),其余情形把「是否删除
/// 成功」写入 `rd`。
///
/// # 步骤
/// 1. 不可配置且当前上下文严格:抛 TypeError,返回 `Ok(true)` 令调用方重取 pc
/// 2. 否则按三态投影布尔结果写 `rd`(`Missing`/`Deleted` 为 true)
///
/// # 边界与前提
/// - 严格性取 `current_strict()`(覆盖帧栈顶 / inline 基线 / 顶层脚本三形态)
///
/// # 副作用
/// - 抛错路径经 `unwind` 改写 pc / 异常通道;成功路径写 `regs[rd]`
fn finish_member_delete(
&mut self, rd: usize, outcome: oxide_builtins::object::DeleteOutcome,
) -> Result<bool, String> {
if outcome == oxide_builtins::object::DeleteOutcome::NonConfigurable && self.current_strict() {
self.raise_type_error("Cannot delete property")?;
return Ok(true);
}
self.regs[rd] = JsValue::bool(outcome != oxide_builtins::object::DeleteOutcome::NonConfigurable);
Ok(false)
}
+13 -3
View File
@@ -117,19 +117,24 @@ impl Vm {
/// true。
///
/// # 步骤
/// 1. null/undefined 基抛 TypeError(调用方经 `?` 传播异常)
/// 1. null/undefined 基抛 TypeError 并早返回(异常已展开,不再写结果槽)
/// 2. 字符串基按下标键区间判自身属性;非字符串基恒真
/// 3. 布尔结果写 `rd` 槽(与对象基臂同槽位)
/// 3. 严格模式下删除失败(字符串下标/length 不可配置)抛 TypeError
/// 4. 布尔结果写 `rd` 槽(与对象基臂同槽位)
///
/// # 边界与前提
/// - 调用点已证基非对象;对象基走既有对象臂,不进本函数
/// - 字符串长度口径按 UTF-16 码元(与字符串自身属性面一致);非规范数字串
/// 键(前导零等)与 symbol 键走"无自身属性"面
///
/// # 副作用
/// - 抛错路径经 `unwind` 改写 pc / 异常通道;成功路径写 `regs[rd]`
pub(crate) fn delete_prop_non_object_base(
&mut self, base: JsValue, rd: usize, key_si: u32,
) -> Result<bool, String> {
if base.is_null() || base.is_undefined() {
self.raise_error_kind("TypeError", "delete on non-object")?;
self.raise_type_error("delete on non-object")?;
return Ok(true);
}
let deleted = if base.is_string() {
let len = unsafe { (*base.as_string_ptr()).units().len() };
@@ -141,6 +146,11 @@ impl Vm {
} else {
true
};
// 删除失败即命中不可配置自身属性,严格模式下 delete 运算符须抛 TypeError。
if !deleted && self.current_strict() {
self.raise_type_error("Cannot delete property")?;
return Ok(true);
}
self.regs[rd] = JsValue::bool(deleted);
Ok(false)
}