From 265fb6adbf48ce2b5bae958f6d785f4c2b1326c3 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 7 Aug 2026 19:52:35 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Object()=20=E5=AF=B9=E5=8E=9F=E5=A7=8B?= =?UTF-8?q?=E5=80=BC=E5=88=9B=E5=BB=BA=20boxed=20=E5=AF=B9=E8=B1=A1=20+=20?= =?UTF-8?q?String=20=E6=96=B9=E6=B3=95=20this=20=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/object.rs | 39 +++++++++++++++++++++++++++-- crates/oxide_builtins/src/string.rs | 5 ++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/crates/oxide_builtins/src/object.rs b/crates/oxide_builtins/src/object.rs index c9d21761..522d6fcb 100644 --- a/crates/oxide_builtins/src/object.rs +++ b/crates/oxide_builtins/src/object.rs @@ -55,8 +55,42 @@ pub(crate) fn walk_own_keys(vm: &H, obj: &JsObject) -> Vec<(u32, u32) } /// JS `Object()` 构造逻辑:创建空对象(prototype 为 null,由 VM 补装内置原型)。 -pub fn object_constructor(vm: &mut H, _args: &[u8]) -> NativeResult { - let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); +pub fn object_constructor(vm: &mut H, args: &[u8]) -> NativeResult { + let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; + let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject; + // 对象参数原样返回;原始值参数创建对应 boxed 对象(规范 ToObject)。 + if val.is_object() { + return NativeResult::Ok(val); + } + if val.is_null() || val.is_undefined() { + let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto))); + return NativeResult::Ok(JsValue::from_js_object(obj)); + } + if val.is_int() || val.is_double() { + let proto = vm.session().builtin_world().number_proto.as_ptr() as *mut JsObject; + let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto))); + let obj_ref = unsafe { &mut *obj }; + obj_ref.type_tag = JsObject::OBJ_TYPE_NUMBER_OBJ; + obj_ref.set_prop_at(0, val); + return NativeResult::Ok(JsValue::from_js_object(obj)); + } + if val.is_string() { + let proto = vm.session().builtin_world().string_proto.as_ptr() as *mut JsObject; + let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto))); + let obj_ref = unsafe { &mut *obj }; + obj_ref.type_tag = JsObject::OBJ_TYPE_STRING_OBJ; + obj_ref.set_prop_at(0, val); + return NativeResult::Ok(JsValue::from_js_object(obj)); + } + if val.is_bool() { + let proto = vm.session().builtin_world().boolean_proto.as_ptr() as *mut JsObject; + let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto))); + let obj_ref = unsafe { &mut *obj }; + obj_ref.type_tag = JsObject::OBJ_TYPE_BOOLEAN_OBJ; + obj_ref.set_prop_at(0, val); + return NativeResult::Ok(JsValue::from_js_object(obj)); + } + let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto))); NativeResult::Ok(JsValue::from_js_object(obj)) } @@ -849,3 +883,4 @@ pub fn object_values(vm: &mut H, args: &[u8]) -> NativeResult { } NativeResult::Ok(JsValue::from_js_object(arr)) } + diff --git a/crates/oxide_builtins/src/string.rs b/crates/oxide_builtins/src/string.rs index b3f6c415..33f226e4 100644 --- a/crates/oxide_builtins/src/string.rs +++ b/crates/oxide_builtins/src/string.rs @@ -8,12 +8,13 @@ use oxide_runtime_api::{NativeResult, VmHost}; use crate::builtins_debug; use crate::builtins_error; -fn this_string(vm: &H, args: &[u8]) -> String { +fn this_string(vm: &mut H, args: &[u8]) -> String { let this_val = vm.reg(args[0]); if this_val.is_null() || this_val.is_undefined() { String::new() // caller should check and throw TypeError } else { - oxide_runtime_api::to_string(this_val) + // 对象 this 须经 ToString 完整转换(boxed Number/String 等取内部原始值)。 + oxide_runtime_api::to_string_full(this_val, vm).unwrap_or_else(|_| String::new()) } }