From 0df0c2cb9894255777946095e5c766e1f0bc8cf3 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 7 Aug 2026 20:44:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20native=20=E6=9E=84=E9=80=A0=E5=99=A8?= =?UTF-8?q?=E5=8F=AF=E6=9E=84=E9=80=A0=E6=80=A7=E6=A0=87=E5=BF=97=EF=BC=88?= =?UTF-8?q?OBJ=5FTYPE=5FCONSTRUCTOR=EF=BC=89+=20Reflect.construct/new=20?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/reflect.rs | 5 +++++ crates/oxide_types/src/object.rs | 2 ++ crates/oxide_vm/src/bindings/mod.rs | 2 ++ crates/oxide_vm/src/vm_dispatch_misc.rs | 6 ++++++ 4 files changed, 15 insertions(+) diff --git a/crates/oxide_builtins/src/reflect.rs b/crates/oxide_builtins/src/reflect.rs index cc59aca9..317cc21a 100644 --- a/crates/oxide_builtins/src/reflect.rs +++ b/crates/oxide_builtins/src/reflect.rs @@ -42,6 +42,11 @@ pub fn reflect_construct(vm: &mut H, args: &[u8]) -> NativeResult { if new_target_ptr.is_null() || !unsafe { &*new_target_ptr }.is_function() { return type_error(vm, "Reflect.construct newTarget is not a constructor"); } + // 不可构造:箭头函数、native 方法(非构造器,OBJ_TYPE_CONSTRUCTOR 标记的除外)。 + let nt = unsafe { &*new_target_ptr }; + if nt.is_arrow() || (nt.native_fn().is_some() && nt.type_tag != oxide_types::object::JsObject::OBJ_TYPE_CONSTRUCTOR) { + return type_error(vm, "Reflect.construct newTarget is not a constructor"); + } let proto_si = vm.kernel_core().perm_interner().intern("prototype").0; let proto_val = match vm.resolve_property(unsafe { &*new_target_ptr }, proto_si) { diff --git a/crates/oxide_types/src/object.rs b/crates/oxide_types/src/object.rs index b656e011..b2791471 100644 --- a/crates/oxide_types/src/object.rs +++ b/crates/oxide_types/src/object.rs @@ -357,6 +357,8 @@ impl JsObject { pub const OBJ_TYPE_DATA_VIEW: u8 = 7; /// TypedArray 对象类型标签。 pub const OBJ_TYPE_TYPED_ARRAY: u8 = 8; + /// native 构造器(Set/Array/Object 等,可 [[Construct]]);区别于不可构造的 native 方法。 + pub const OBJ_TYPE_CONSTRUCTOR: u8 = 9; /// `is_session_epoch` 字段中的 session 标记位。 pub const SESSION_EPOCH_BIT: u8 = 0x01; /// `is_session_epoch` 字段中的 GC 标记位。 diff --git a/crates/oxide_vm/src/bindings/mod.rs b/crates/oxide_vm/src/bindings/mod.rs index 11716679..ae990172 100644 --- a/crates/oxide_vm/src/bindings/mod.rs +++ b/crates/oxide_vm/src/bindings/mod.rs @@ -74,6 +74,7 @@ macro_rules! bind_constructor { let ptr: *const () = ($ctor_fn as fn(&mut $crate::vm::Vm, &[u8]) -> oxide_runtime_api::NativeResult) as *const (); ctor.set_native_fn(Some(unsafe { oxide_types::object::NativeFnPtr::from_raw(ptr) })); ctor.set_native_arg_count($nargs); + ctor.type_tag = oxide_types::object::JsObject::OBJ_TYPE_CONSTRUCTOR; // 设置 constructor.length (Function.length = formal parameter count) let length_si = $core.perm_interner().intern("length").0; let length_shape = $core.shape_forge().make_shape(ctor.shape_id(), length_si); @@ -86,6 +87,7 @@ pub(crate) fn configure_native_constructor(ctor: &mut JsObject, native_fn: *cons // SAFETY: native_fn 始终是调用方转成 *const () 的合法 NativeFn 函数项指针。 ctor.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(native_fn) })); ctor.set_native_arg_count(arg_count); + ctor.type_tag = JsObject::OBJ_TYPE_CONSTRUCTOR; } fn configure_existing_ctor(ctor: &P, native_fn: *const (), arg_count: u8) { diff --git a/crates/oxide_vm/src/vm_dispatch_misc.rs b/crates/oxide_vm/src/vm_dispatch_misc.rs index 81559483..c9f43571 100644 --- a/crates/oxide_vm/src/vm_dispatch_misc.rs +++ b/crates/oxide_vm/src/vm_dispatch_misc.rs @@ -35,6 +35,12 @@ impl Vm { .raise_type_error("arrow functions cannot be used as constructors") .map(|_| true); } + // native 方法(非构造器)不可 new。 + if ctor_obj.native_fn().is_some() && ctor_obj.type_tag != oxide_types::object::JsObject::OBJ_TYPE_CONSTRUCTOR { + return self + .raise_type_error("object is not a constructor") + .map(|_| true); + } let ext = self.bytecode[self.pc]; self.pc += 1;