fix: 修复 harness 函数原型和 Object.assign ToObject

This commit is contained in:
爱特每羊队
2026-06-09 19:46:50 +08:00
parent e588fa4c8c
commit 16568c83fe
10 changed files with 131 additions and 16 deletions
@@ -32,6 +32,7 @@ pub fn bind_string(kernel: &Arc<OxideKernel>, global: &mut JsObject) {
normalize: crate::builtins::string::string_normalize as *const (),
match_all: crate::builtins::string::string_match_all as *const (),
replace_all: crate::builtins::string::string_replace_all as *const (),
value_of: crate::builtins::string::string_value_of as *const (),
};
kernel.builtin_world().bind_string_methods(
&string_methods,
+3 -4
View File
@@ -99,12 +99,11 @@ pub fn object_create(vm: &mut Vm, args: &[u8]) -> NativeResult {
pub fn object_assign(vm: &mut Vm, args: &[u8]) -> NativeResult {
if args.len() < 2 {
return Err(JsValue::undefined());
return Err(crate::builtins::error::create_type_error(vm, "Object.assign requires a target"));
}
let target_val = vm.reg(args[1]);
if !target_val.is_object() {
return Ok(target_val);
}
let target_val =
coercion::to_object(target_val, vm).map_err(|msg| crate::builtins::error::create_type_error(vm, msg))?;
let target_ptr = target_val.as_js_object_ptr();
if target_ptr.is_null() {
return Ok(target_val);
+27
View File
@@ -11,6 +11,33 @@ fn this_string(vm: &Vm, args: &[u8]) -> String {
coercion::to_string(vm.kernel().string_forge().as_ref(), vm.reg(args[0]))
}
fn boxed_primitive_value(this_val: JsValue) -> Option<JsValue> {
if !this_val.is_object() {
return None;
}
let ptr = this_val.as_js_object_ptr();
if ptr.is_null() {
return None;
}
let obj = unsafe { &*ptr };
let val = obj.get_prop_at(0);
if val.is_undefined() && obj.prop_count() == 0 {
None
} else {
Some(val)
}
}
pub fn string_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(args[0]);
if this_val.is_string() {
return Ok(this_val);
}
boxed_primitive_value(this_val).ok_or_else(|| {
crate::builtins::error::create_type_error(vm, "String.prototype.valueOf called on non-String object")
})
}
fn make_string_array(vm: &mut Vm, parts: &[String]) -> JsValue {
let proto = vm.kernel().builtin_world().array_proto.as_ptr() as *mut JsObject;
let n = parts.len();
+9 -1
View File
@@ -293,7 +293,15 @@ pub fn to_object(val: JsValue, vm: &mut Vm) -> Result<JsValue, &'static str> {
if val.is_null() || val.is_undefined() {
return Err("TypeError: Cannot convert null or undefined to object");
}
let proto_ptr = &*vm.object_prototype as *const JsObject as *mut JsObject;
let proto_ptr = if val.is_string() {
vm.kernel().builtin_world().string_proto.as_ptr() as *mut JsObject
} else if val.is_int() || val.is_double() {
vm.kernel().builtin_world().number_proto.as_ptr() as *mut JsObject
} else if val.is_bool() {
vm.kernel().builtin_world().boolean_proto.as_ptr() as *mut JsObject
} else {
&*vm.object_prototype as *const JsObject as *mut JsObject
};
let proto_val = JsValue::from_js_object(proto_ptr);
let obj = vm.epoch.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
let obj_val = JsValue::from_js_object(obj);
+38 -3
View File
@@ -266,7 +266,32 @@ impl Vm {
obj.set_captured_this(self.regs[254]);
}
let obj_ptr = self.epoch.alloc(obj);
JsValue::object(obj_ptr as *mut u8)
let func_val = JsValue::object(obj_ptr as *mut u8);
if !is_arrow {
let object_proto_ptr = self.kernel.builtin_world().object_proto.as_ptr() as *mut JsObject;
let prototype_obj = self
.epoch
.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto_ptr)));
let prototype_val = JsValue::from_js_object(prototype_obj);
let constructor_si = self.kernel.string_forge().intern("constructor").0;
let constructor_shape = self.kernel.shape_forge().make_shape(EMPTY_SHAPE_ID, constructor_si);
let prototype = unsafe { &mut *prototype_obj };
prototype.set_shape_id(constructor_shape);
let constructor_pos = prototype.push_prop(func_val);
prototype.set_data_meta(constructor_pos, PropAttributes::new(true, false, true));
prototype.bump_generation();
let prototype_si = self.kernel.string_forge().intern("prototype").0;
let func = unsafe { &mut *obj_ptr };
let prototype_shape = self.kernel.shape_forge().make_shape(func.shape_id(), prototype_si);
func.set_shape_id(prototype_shape);
func.ensure_hash_props().push(Box::new(prototype_val));
func.bump_generation();
}
func_val
}
fn error_text(&self, val: JsValue) -> String {
@@ -1812,8 +1837,18 @@ impl Vm {
}
if let Some(shape) = self.kernel.shape_forge().get_shape(id) {
if shape.property_name != u32::MAX && seen.insert(shape.property_name) {
let hash = self.kernel.string_forge().get_hash(shape.property_name).unwrap_or(0);
keys_vec.push(JsValue::string(shape.property_name, hash));
let enumerable = self
.kernel
.shape_forge()
.lookup_position(cur.shape_id(), shape.property_name)
.and_then(|pos| cur.prop_meta_at(pos))
.map(|meta| meta.attributes.enumerable())
.unwrap_or(PropAttributes::DEFAULT_DATA.enumerable());
if enumerable {
let hash =
self.kernel.string_forge().get_hash(shape.property_name).unwrap_or(0);
keys_vec.push(JsValue::string(shape.property_name, hash));
}
}
cursor = shape.parent;
} else {