fix: native 构造器可构造性标志(OBJ_TYPE_CONSTRUCTOR)+ Reflect.construct/new 校验

This commit is contained in:
爱特每羊队
2026-08-07 20:44:04 +08:00
parent fec6b68ecb
commit cbb139e956
4 changed files with 15 additions and 0 deletions
+5
View File
@@ -42,6 +42,11 @@ pub fn reflect_construct<H: VmHost>(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) {
+2
View File
@@ -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 标记位。
+2
View File
@@ -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<JsObject>, native_fn: *const (), arg_count: u8) {
+6
View File
@@ -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;