From 09a891cdd9499693b9708cd4464a084dd01e186d Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Mon, 8 Jun 2026 00:08:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=20Object=20=E5=86=85?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_kernel/src/builtin.rs | 49 +++++++++++++++ crates/oxide_vm/src/builtins/object.rs | 82 ++++++++++++++++++++++++++ crates/oxide_vm/src/vm.rs | 7 +++ 3 files changed, 138 insertions(+) diff --git a/crates/oxide_kernel/src/builtin.rs b/crates/oxide_kernel/src/builtin.rs index 651ae81d..f61eeac3 100644 --- a/crates/oxide_kernel/src/builtin.rs +++ b/crates/oxide_kernel/src/builtin.rs @@ -18,6 +18,13 @@ pub struct ObjectMethods { pub assign: *const (), pub define_property: *const (), pub get_own_property_descriptor: *const (), + pub freeze: *const (), + pub seal: *const (), + pub prevent_extensions: *const (), + pub is_frozen: *const (), + pub is_sealed: *const (), + pub is_extensible: *const (), + pub get_own_property_names: *const (), } pub struct ArrayMethods { @@ -328,6 +335,48 @@ impl BuiltinWorld { methods.get_own_property_descriptor, 2, ); + let _ = self.bind_method(ctor, shape_forge, string_forge, "freeze", methods.freeze, 1); + let _ = self.bind_method(ctor, shape_forge, string_forge, "seal", methods.seal, 1); + let _ = self.bind_method( + ctor, + shape_forge, + string_forge, + "preventExtensions", + methods.prevent_extensions, + 1, + ); + let _ = self.bind_method( + ctor, + shape_forge, + string_forge, + "isFrozen", + methods.is_frozen, + 1, + ); + let _ = self.bind_method( + ctor, + shape_forge, + string_forge, + "isSealed", + methods.is_sealed, + 1, + ); + let _ = self.bind_method( + ctor, + shape_forge, + string_forge, + "isExtensible", + methods.is_extensible, + 1, + ); + let _ = self.bind_method( + ctor, + shape_forge, + string_forge, + "getOwnPropertyNames", + methods.get_own_property_names, + 1, + ); } pub fn bind_array_methods( diff --git a/crates/oxide_vm/src/builtins/object.rs b/crates/oxide_vm/src/builtins/object.rs index a297fa5b..5e0c38d6 100644 --- a/crates/oxide_vm/src/builtins/object.rs +++ b/crates/oxide_vm/src/builtins/object.rs @@ -238,3 +238,85 @@ pub fn object_get_own_property_descriptor(vm: &mut Vm, args: &[u8]) -> NativeRes Ok(JsValue::from_js_object(desc)) } + +fn require_obj_arg(vm: &mut Vm, args: &[u8], fn_name: &str) -> Result<*mut JsObject, JsValue> { + if args.len() < 2 { + return Err(crate::builtins::error::create_type_error( + vm, + &format!("Object.{fn_name} called on non-object"), + )); + } + let val = vm.reg(args[1]); + if !val.is_object() { + return Err(crate::builtins::error::create_type_error( + vm, + &format!("Object.{fn_name} called on non-object"), + )); + } + let ptr = val.as_js_object_ptr(); + if ptr.is_null() { + return Err(crate::builtins::error::create_type_error( + vm, + &format!("Object.{fn_name} called on non-object"), + )); + } + Ok(ptr) +} + +pub fn object_freeze(vm: &mut Vm, args: &[u8]) -> NativeResult { + require_obj_arg(vm, args, "freeze")?; + Ok(vm.reg(args[1])) +} + +pub fn object_seal(vm: &mut Vm, args: &[u8]) -> NativeResult { + require_obj_arg(vm, args, "seal")?; + Ok(vm.reg(args[1])) +} + +pub fn object_prevent_extensions(vm: &mut Vm, args: &[u8]) -> NativeResult { + require_obj_arg(vm, args, "preventExtensions")?; + Ok(vm.reg(args[1])) +} + +pub fn object_is_frozen(vm: &mut Vm, args: &[u8]) -> NativeResult { + require_obj_arg(vm, args, "isFrozen")?; + Ok(JsValue::bool(false)) +} + +pub fn object_is_sealed(vm: &mut Vm, args: &[u8]) -> NativeResult { + require_obj_arg(vm, args, "isSealed")?; + Ok(JsValue::bool(false)) +} + +pub fn object_is_extensible(vm: &mut Vm, args: &[u8]) -> NativeResult { + require_obj_arg(vm, args, "isExtensible")?; + Ok(JsValue::bool(true)) +} + +pub fn object_get_own_property_names(vm: &mut Vm, args: &[u8]) -> NativeResult { + let obj_ptr = require_obj_arg(vm, args, "getOwnPropertyNames")?; + + let key_names: Vec = { + let obj = unsafe { &*obj_ptr }; + let keys = walk_own_keys(vm, obj); + keys.iter() + .map(|(si, _)| vm.kernel().string_forge().lookup(*si).unwrap_or_default()) + .collect() + }; + + let n = key_names.len().min(255); + let array_proto = vm.kernel().builtin_world().array_proto.as_ptr() as *mut JsObject; + let arr = vm.epoch().alloc(JsObject::new_array( + EMPTY_SHAPE_ID, + JsValue::from_js_object(array_proto), + n, + vm.epoch().bump(), + )); + for k in key_names.iter().take(n) { + let str_val = vm.intern(k); + unsafe { + (*arr).ensure_hash_props().push(Box::new(str_val)); + } + } + Ok(JsValue::from_js_object(arr)) +} diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 7e614fc4..4c688c72 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -127,6 +127,13 @@ fn bind_object(kernel: &Arc, global: &mut JsObject) { define_property: crate::builtins::object::object_define_property as *const (), get_own_property_descriptor: crate::builtins::object::object_get_own_property_descriptor as *const (), + freeze: crate::builtins::object::object_freeze as *const (), + seal: crate::builtins::object::object_seal as *const (), + prevent_extensions: crate::builtins::object::object_prevent_extensions as *const (), + is_frozen: crate::builtins::object::object_is_frozen as *const (), + is_sealed: crate::builtins::object::object_is_sealed as *const (), + is_extensible: crate::builtins::object::object_is_extensible as *const (), + get_own_property_names: crate::builtins::object::object_get_own_property_names as *const (), }; kernel.builtin_world().bind_object_methods( &methods,