fix: defineProperty 描述符字段按 ToPropertyDescriptor 语义解析(原型链 + accessor getter)

This commit is contained in:
爱特每羊队
2026-08-08 01:39:12 +08:00
parent 3b13b111c4
commit e91d8ecaf2
2 changed files with 29 additions and 31 deletions
+14 -18
View File
@@ -247,11 +247,10 @@ pub fn object_define_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResul
let enumerable_si = vm.kernel_core().perm_interner().intern("enumerable").0; let enumerable_si = vm.kernel_core().perm_interner().intern("enumerable").0;
let configurable_si = vm.kernel_core().perm_interner().intern("configurable").0; let configurable_si = vm.kernel_core().perm_interner().intern("configurable").0;
let desc = unsafe { &*desc_ptr }; let value_field = own_field(vm, desc_val, value_si);
let value_field = own_field(vm, desc, value_si); let get_field = own_field(vm, desc_val, get_si);
let get_field = own_field(vm, desc, get_si); let set_field = own_field(vm, desc_val, set_si);
let set_field = own_field(vm, desc, set_si); let writable_field = own_field(vm, desc_val, writable_si);
let writable_field = own_field(vm, desc, writable_si);
let existing_pos = { let existing_pos = {
let obj = unsafe { &*obj_ptr }; let obj = unsafe { &*obj_ptr };
@@ -263,10 +262,10 @@ pub fn object_define_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResul
}); });
// 修改已有属性时缺省字段回填现有值,仅定义新属性时缺省才为 false。 // 修改已有属性时缺省字段回填现有值,仅定义新属性时缺省才为 false。
let enumerable = own_field(vm, desc, enumerable_si) let enumerable = own_field(vm, desc_val, enumerable_si)
.map(oxide_runtime_api::to_boolean) .map(oxide_runtime_api::to_boolean)
.unwrap_or_else(|| existing_meta.map(|m| m.attributes.enumerable()).unwrap_or(false)); .unwrap_or_else(|| existing_meta.map(|m| m.attributes.enumerable()).unwrap_or(false));
let configurable = own_field(vm, desc, configurable_si) let configurable = own_field(vm, desc_val, configurable_si)
.map(oxide_runtime_api::to_boolean) .map(oxide_runtime_api::to_boolean)
.unwrap_or_else(|| existing_meta.map(|m| m.attributes.configurable()).unwrap_or(false)); .unwrap_or_else(|| existing_meta.map(|m| m.attributes.configurable()).unwrap_or(false));
@@ -419,17 +418,14 @@ pub fn object_get_own_property_descriptor<H: VmHost>(vm: &mut H, args: &[u8]) ->
NativeResult::Ok(JsValue::from_js_object(desc)) NativeResult::Ok(JsValue::from_js_object(desc))
} }
fn own_field<H: VmHost>(vm: &H, obj: &JsObject, prop_si: u32) -> Option<JsValue> { /// 按 ToPropertyDescriptor 语义取描述符字段:沿原型链判存在性,存在时经
vm.kernel_core() /// ordinary_get 取值(触发 accessor getter,receiver 为描述符对象本身)。
.shape_forge() fn own_field<H: VmHost>(vm: &mut H, desc: JsValue, prop_si: u32) -> Option<JsValue> {
.lookup_position(obj.shape_id(), prop_si) // ordinary_get 对缺失属性返回 undefined,无法区分"不存在"与"值为
.and_then(|pos| { // undefined",故先用 resolve_property 沿原型链判 HasProperty。
if obj.prop_vec_len() > pos as usize { let obj = unsafe { &*desc.as_js_object_ptr() };
Some(obj.get_prop_at(pos)) vm.resolve_property(obj, prop_si)?;
} else { vm.ordinary_get(obj, prop_si, desc).ok()
None
}
})
} }
fn is_callable(value: JsValue) -> bool { fn is_callable(value: JsValue) -> bool {
+15 -13
View File
@@ -75,12 +75,11 @@ pub fn reflect_define_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
return type_error(vm, "Reflect.defineProperty target is not an object"); return type_error(vm, "Reflect.defineProperty target is not an object");
}; };
let desc_val = arg(vm, args, 3); let desc_val = arg(vm, args, 3);
let Some(desc_ptr) = object_ptr(desc_val) else { let Some(_) = object_ptr(desc_val) else {
return type_error(vm, "Reflect.defineProperty descriptor is not an object"); return type_error(vm, "Reflect.defineProperty descriptor is not an object");
}; };
let key_si = vm.property_key_si(arg(vm, args, 2)); let key_si = vm.property_key_si(arg(vm, args, 2));
let desc = unsafe { &*desc_ptr };
let value_si = vm.kernel_core().perm_interner().intern("value").0; let value_si = vm.kernel_core().perm_interner().intern("value").0;
let get_si = vm.kernel_core().perm_interner().intern("get").0; let get_si = vm.kernel_core().perm_interner().intern("get").0;
let set_si = vm.kernel_core().perm_interner().intern("set").0; let set_si = vm.kernel_core().perm_interner().intern("set").0;
@@ -88,14 +87,14 @@ pub fn reflect_define_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
let enumerable_si = vm.kernel_core().perm_interner().intern("enumerable").0; let enumerable_si = vm.kernel_core().perm_interner().intern("enumerable").0;
let configurable_si = vm.kernel_core().perm_interner().intern("configurable").0; let configurable_si = vm.kernel_core().perm_interner().intern("configurable").0;
let value_field = own_field(vm, desc, value_si); let value_field = own_field(vm, desc_val, value_si);
let get_field = own_field(vm, desc, get_si); let get_field = own_field(vm, desc_val, get_si);
let set_field = own_field(vm, desc, set_si); let set_field = own_field(vm, desc_val, set_si);
let writable_field = own_field(vm, desc, writable_si); let writable_field = own_field(vm, desc_val, writable_si);
let enumerable = own_field(vm, desc, enumerable_si) let enumerable = own_field(vm, desc_val, enumerable_si)
.map(oxide_runtime_api::to_boolean) .map(oxide_runtime_api::to_boolean)
.unwrap_or(false); .unwrap_or(false);
let configurable = own_field(vm, desc, configurable_si) let configurable = own_field(vm, desc_val, configurable_si)
.map(oxide_runtime_api::to_boolean) .map(oxide_runtime_api::to_boolean)
.unwrap_or(false); .unwrap_or(false);
@@ -264,11 +263,14 @@ fn array_like_elements(value: JsValue) -> Option<Vec<JsValue>> {
Some((0..obj.prop_count() as usize).map(|idx| obj.get_prop_at(idx)).collect()) Some((0..obj.prop_count() as usize).map(|idx| obj.get_prop_at(idx)).collect())
} }
fn own_field<H: VmHost>(vm: &H, obj: &JsObject, prop_si: u32) -> Option<JsValue> { /// 按 ToPropertyDescriptor 语义取描述符字段:沿原型链判存在性,存在时经
vm.kernel_core() /// ordinary_get 取值(触发 accessor getter,receiver 为描述符对象本身)。
.shape_forge() fn own_field<H: VmHost>(vm: &mut H, desc: JsValue, prop_si: u32) -> Option<JsValue> {
.lookup_position(obj.shape_id(), prop_si) // ordinary_get 对缺失属性返回 undefined,无法区分"不存在"与"值为
.and_then(|pos| (obj.prop_vec_len() > pos as usize).then(|| obj.get_prop_at(pos))) // undefined",故先用 resolve_property 沿原型链判 HasProperty。
let obj = unsafe { &*desc.as_js_object_ptr() };
vm.resolve_property(obj, prop_si)?;
vm.ordinary_get(obj, prop_si, desc).ok()
} }
fn make_string_array<H: VmHost>(vm: &mut H, parts: &[String]) -> JsValue { fn make_string_array<H: VmHost>(vm: &mut H, parts: &[String]) -> JsValue {