fix: defineProperty 描述符字段按 ToPropertyDescriptor 语义解析(原型链 + accessor getter)
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user