feat: 补齐动态函数构造器族与原型对象

This commit is contained in:
2026-09-24 22:36:54 +00:00
parent 2dc119874d
commit 2920c77148
8 changed files with 224 additions and 78 deletions
+48 -19
View File
@@ -930,22 +930,35 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
// 槽在下方 P 槽换入后重指新原型),不再每轮新建对象。
let agf_ctor_label = sf.intern("AsyncGeneratorFunctionCtor").0;
let agf_reuse_key = oxide_kernel::builtin::FnWrapperKey::new(0, agf_ctor_label, 0, 0);
// SAFETY: async_generator_function_stub 是 NativeFn 函数项。
let agf_stub_ptr = unsafe { NativeFnPtr::from_raw(async_generator_function_stub as *const ()) };
let (agf_ctor_ptr, agf_ctor_is_new) = match world.find_fn_wrapper(agf_reuse_key, agf_stub_ptr, 1) {
// SAFETY: async_generator_function_constructor 是 NativeFn 函数项。
let agf_ctor_fn_ptr = unsafe {
NativeFnPtr::from_raw(
oxide_builtins::function::async_generator_function_constructor::<Vm> as *const (),
)
};
let (agf_ctor_ptr, agf_ctor_is_new) = match world.find_fn_wrapper(agf_reuse_key, agf_ctor_fn_ptr, 1) {
Some(ptr) => (ptr, false),
None => {
let mut agf_ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
agf_ctor.set_function(true);
agf_ctor.set_native_arg_count(1);
agf_ctor.set_native_fn(Some(agf_stub_ptr));
// prototype/name 属性(构造器形状 [prototype, name])。
let proto_si = sf.intern("prototype").0;
let ctor_shape = sh.make_shape(EMPTY_SHAPE_ID, proto_si);
agf_ctor.set_shape_id(ctor_shape);
agf_ctor.set_native_fn(Some(agf_ctor_fn_ptr));
// 构造器 tag:IsConstructor 判定与 new 表达式派发据此放行。
agf_ctor.type_tag = JsObject::OBJ_TYPE_CONSTRUCTOR;
// 自身属性序:length、name、prototype、@@toStringTag(CreateBuiltinFunction 序)。
let length_si = sf.intern("length").0;
let length_shape = sh.make_shape(EMPTY_SHAPE_ID, length_si);
agf_ctor.set_shape_id(length_shape);
let name_si = sf.intern("name").0;
let name_shape = sh.make_shape(agf_ctor.shape_id(), name_si);
agf_ctor.set_shape_id(name_shape);
let proto_si = sf.intern("prototype").0;
let proto_shape = sh.make_shape(agf_ctor.shape_id(), proto_si);
agf_ctor.set_shape_id(proto_shape);
let tag_key =
oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG);
let tag_shape = sh.make_shape(agf_ctor.shape_id(), tag_key);
agf_ctor.set_shape_id(tag_shape);
let agf_ctor_ptr = Box::into_raw(agf_ctor);
// 登记进 world 释放表(带复用键):session 收尾统一释放构造器本体与属性区。
world.track_fn_wrapper(agf_ctor_ptr, agf_reuse_key);
@@ -964,7 +977,7 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
let proto2_shape = sh.make_shape(agf_proto.shape_id(), proto2_si);
agf_proto.set_shape_id(proto2_shape);
let ppos2 = agf_proto.push_prop(JsValue::from_js_object(vm.async_generator_proto.as_ptr() as *mut JsObject));
agf_proto.set_data_meta(ppos2, PropAttributes::new(false, false, false));
agf_proto.set_data_meta(ppos2, PropAttributes::new(false, false, true));
// agf_proto[Symbol.toStringTag] = "AsyncGeneratorFunction"(数据属性,w/e/c = false/false/true)。
let tag2_key =
oxide_types::private_key::make_well_known_symbol_key(oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG);
@@ -974,7 +987,7 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
agf_proto.set_data_meta(tag2_pos, PropAttributes::new(false, false, true));
// proto 本体只存在于 P 槽(Arc 副本,原 Box 随函数结束释放):装入 P 槽后再写
// 构造器 prototype/name 属性(按模板序 prototype 在前),prototype 指向 P 槽实例,
// 构造器 length/name/prototype/@@toStringTag 属性(按形状序),prototype 指向 P 槽实例,
// 使其与动态异步生成器函数使用的 [[Prototype]] 同一对象。复用构造器槽位已填充,
// prototype 原位改指新 P 原型(旧原型已随 P 换出释放)。
Vm::swap_intrinsic_proto(&mut vm.async_generator_function_proto, *agf_proto);
@@ -984,10 +997,15 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
let proto_val = JsValue::from_js_object(vm.async_generator_function_proto.as_ptr() as *mut JsObject);
let name_val = JsValue::perm_string(sf.string_ptr(sf.intern("AsyncGeneratorFunction").0));
if agf_ctor_is_new {
let ppos = ctor_mut.push_prop(proto_val);
ctor_mut.set_data_meta(ppos, PropAttributes::new(false, false, false));
let lpos = ctor_mut.push_prop(JsValue::int(1));
ctor_mut.set_data_meta(lpos, PropAttributes::new(false, false, true));
let npos = ctor_mut.push_prop(name_val);
ctor_mut.set_data_meta(npos, PropAttributes::new(false, false, true));
let ppos = ctor_mut.push_prop(proto_val);
ctor_mut.set_data_meta(ppos, PropAttributes::new(false, false, false));
let tag_val = JsValue::perm_string(sf.string_ptr(sf.intern("Function").0));
let tpos = ctor_mut.push_prop(tag_val);
ctor_mut.set_data_meta(tpos, PropAttributes::new(false, false, true));
} else {
let si_prototype = sf.intern("prototype").0;
if let Some(pos) = sh.lookup_position(ctor_mut.shape_id(), si_prototype) {
@@ -999,14 +1017,25 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
}
}
}
}
/// `%AsyncGeneratorFunction%` 占位:动态异步生成器函数创建未实现,调用抛错。
fn async_generator_function_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
NativeResult::Err(oxide_builtins::error::create_type_error(
vm,
"AsyncGeneratorFunction constructor is not supported",
))
// 绑定 global:AsyncGeneratorFunction 槽已存在则原位更新(full_reset 未重建
// global 时旧槽指向已弃 ctor),不存在则开新槽。
let global_ptr = vm.session.global_object().as_ptr() as *mut JsObject;
// SAFETY: global 由 session 持有存活整个 session;本函数内只改其 shape/属性区,
// 期间无 reset 或对象搬移。
let global = unsafe { &mut *global_ptr };
let si = sf.intern("AsyncGeneratorFunction").0;
let ctor_val = JsValue::from_js_object(agf_ctor_ptr);
if let Some(pos) = sh.lookup_position(global.shape_id(), si) {
global.set_prop_at(pos, ctor_val);
} else {
let shape = sh.make_shape(global.shape_id(), si);
global.set_shape_id(shape);
let pos = global.push_prop(ctor_val);
// global 数据属性:writable:true、enumerable:false、configurable:true。
global.set_data_meta(pos, PropAttributes::new(true, false, true));
global.bump_generation();
}
}
// ── session GC 支撑:状态快照中的 JsValues 作为异步生成器对象边追踪 ──