mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 03:01:12 +08:00
fix: 补 Error 族原型与 Math 六函数边及 Symbol 面描述符
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor};
|
||||
use crate::bindings::{apply_binding_table, bind_accessor_getter, bind_well_known_method, configure_native_constructor};
|
||||
use oxide_kernel::kernel::{KernelCore, KernelSession};
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::private_key::{make_well_known_symbol_key, WELL_KNOWN_SYMBOL_TO_PRIMITIVE};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::bind_constructor;
|
||||
@@ -45,6 +46,22 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
oxide_builtins::symbol::symbol_description_getter::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
|
||||
// [Symbol.toPrimitive] 方法:bind 默认描述符可写,规范为不可写,绑定后改 meta。
|
||||
bind_well_known_method(
|
||||
session.builtin_world(),
|
||||
core,
|
||||
proto,
|
||||
WELL_KNOWN_SYMBOL_TO_PRIMITIVE,
|
||||
"[Symbol.toPrimitive]",
|
||||
oxide_builtins::symbol::symbol_to_primitive::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
let to_prim_key = make_well_known_symbol_key(WELL_KNOWN_SYMBOL_TO_PRIMITIVE);
|
||||
if let Some(pos) = core.shape_forge().lookup_position(proto.shape_id(), to_prim_key) {
|
||||
proto.set_data_meta(pos, PropAttributes::new(false, false, true));
|
||||
proto.bump_generation();
|
||||
}
|
||||
|
||||
// well-known symbol 以符号原语绑定,下标与内建符号表(0..WELL_KNOWN_SYMBOL_COUNT)
|
||||
// 一一对应;名称表是 id/名映射的唯一来源,属性名去掉 `Symbol.` 前缀。
|
||||
for (id, full_name) in oxide_types::private_key::WELL_KNOWN_SYMBOL_NAMES.iter().enumerate() {
|
||||
@@ -60,5 +77,8 @@ fn bind_well_known_symbol(core: &Arc<KernelCore>, ctor: &mut JsObject, name: &st
|
||||
let shape_id = core.shape_forge().make_shape(ctor.shape_id(), si);
|
||||
ctor.set_shape_id(shape_id);
|
||||
ctor.ensure_hash_props().push(val);
|
||||
// well-known symbol 属性按规范 { writable:false, enumerable:false, configurable:false }。
|
||||
let pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
|
||||
ctor.set_data_meta(pos, PropAttributes::new(false, false, false));
|
||||
ctor.bump_generation();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,17 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
/// SET 路径的接收者解析:对象直取;非对象经 ToObject 自动装箱
|
||||
/// (null/undefined 抛 TypeError,其余原始值写盒后丢弃盒,与规范
|
||||
/// OrdinarySetWithOwnDescriptor 的 ToObject 基语义一致)。
|
||||
fn set_prop_base(&mut self, receiver: JsValue) -> Result<Option<*mut JsObject>, String> {
|
||||
if receiver.is_object() {
|
||||
return self.checked_object_ptr(receiver, "Cannot create property on non-object");
|
||||
}
|
||||
let boxed = coercion::to_object(receiver, self)?;
|
||||
Ok(Some(boxed.as_js_object_ptr()))
|
||||
}
|
||||
|
||||
fn private_key_from_reg(&self, reg: usize) -> u32 {
|
||||
let value = self.regs[reg];
|
||||
let local_id = if value.is_int() {
|
||||
@@ -401,7 +412,7 @@ impl Vm {
|
||||
}
|
||||
|
||||
fn dispatch_ic_set_prop(&mut self, rd: usize, a: usize, b: usize) -> Result<(), String> {
|
||||
let Some(obj_ptr) = self.checked_object_ptr(self.regs[rd], "Cannot create property on non-object")? else {
|
||||
let Some(obj_ptr) = self.set_prop_base(self.regs[rd])? else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
@@ -484,7 +495,7 @@ impl Vm {
|
||||
|
||||
fn dispatch_set_prop(&mut self, rd: usize, a: usize, b: usize) -> Result<(), String> {
|
||||
vm_trace!("SET_PROP rd={} a={} b={}", rd, a, b);
|
||||
let Some(obj_ptr) = self.checked_object_ptr(self.regs[rd], "Cannot create property on non-object")? else {
|
||||
let Some(obj_ptr) = self.set_prop_base(self.regs[rd])? else {
|
||||
return Ok(());
|
||||
};
|
||||
let prop_name_si = self.property_key_si(self.regs[b])?;
|
||||
@@ -560,7 +571,7 @@ impl Vm {
|
||||
|
||||
fn dispatch_set_prop_dynamic(&mut self, rd: usize, a: usize, b: usize) -> Result<(), String> {
|
||||
vm_trace!("SET_PROP_DYNAMIC rd={} a={} b={}", rd, a, b);
|
||||
let Some(obj_ptr) = self.checked_object_ptr(self.regs[rd], "Cannot create property on non-object")? else {
|
||||
let Some(obj_ptr) = self.set_prop_base(self.regs[rd])? else {
|
||||
return Ok(());
|
||||
};
|
||||
let prop_name_si = self.property_key_si(self.regs[a])?;
|
||||
|
||||
@@ -191,7 +191,6 @@ impl Vm {
|
||||
pub(crate) fn init_aggregate_error_intrinsics(&mut self) {
|
||||
let sf = self.kernel_core.perm_interner().as_ref();
|
||||
let sh = self.kernel_core.shape_forge().as_ref();
|
||||
let fn_proto_val = self.session.builtin_world().fn_proto_val();
|
||||
let error_proto_val =
|
||||
JsValue::from_js_object(self.session.builtin_world().error_proto.as_ptr() as *mut JsObject);
|
||||
|
||||
@@ -213,8 +212,10 @@ impl Vm {
|
||||
let msg_pos = proto.push_prop(JsValue::perm_string(sf.string_ptr(sf.intern("").0)));
|
||||
proto.set_data_meta(msg_pos, PropAttributes::new(true, false, true));
|
||||
|
||||
// %AggregateError% 构造器:proto = %Function.prototype%,length 2。
|
||||
let mut ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
|
||||
// %AggregateError% 构造器:proto = %Error%(NativeError 构造器继承 Error 构造器),length 2。
|
||||
let error_ctor_val =
|
||||
JsValue::from_js_object(self.session.builtin_world().error_constructor.as_ptr() as *mut JsObject);
|
||||
let mut ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_ctor_val));
|
||||
ctor.set_function(true);
|
||||
ctor.type_tag = JsObject::OBJ_TYPE_CONSTRUCTOR;
|
||||
// SAFETY: aggregate_error_constructor 是 NativeFn 函数项。
|
||||
@@ -1071,6 +1072,11 @@ fn aggregate_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
// SAFETY: this 是本次构造的存活对象。
|
||||
let _ = vm.define_data_property(unsafe { &mut *this }, msg_si, msg_val, PropAttributes::new(true, false, true));
|
||||
}
|
||||
// InstallErrorCause:options 为第三实参(args[3]),message 之后、errors 收集之前。
|
||||
let options = if args.len() > 3 { vm.reg(args[3]) } else { JsValue::undefined() };
|
||||
if let NativeResult::Err(e) = oxide_builtins::error::install_error_cause(vm, this, options) {
|
||||
return NativeResult::Err(e);
|
||||
}
|
||||
let errors_list = match vm.aggregate_errors_to_list(errors) {
|
||||
Ok(list) => list,
|
||||
Err(err) => return NativeResult::Err(err),
|
||||
|
||||
Reference in New Issue
Block a user