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
+33 -6
View File
@@ -19,7 +19,34 @@ fn invoke_target<H: VmHost>(vm: &mut H, target_val: JsValue, this_val: JsValue,
/// 实参转单元序列后经 `source_escape` 源码域转义再动态编译。
/// 编译成功返回函数对象,语法错误抛 SyntaxError,实参 ToPrimitive 失败抛 TypeError。
pub fn function_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
let arg_regs = &args[1..];
dynamic_function_core(vm, &args[1..], false, false)
}
/// `GeneratorFunction(...)` / `new GeneratorFunction(...)` 构造器:动态编译
/// 一个匿名生成器函数(`function*` 形态)。
pub fn generator_function_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
dynamic_function_core(vm, &args[1..], true, false)
}
/// `AsyncFunction(...)` / `new AsyncFunction(...)` 构造器:动态编译一个匿名
/// 异步函数(`async function` 形态)。
pub fn async_function_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
dynamic_function_core(vm, &args[1..], false, true)
}
/// `AsyncGeneratorFunction(...)` / `new AsyncGeneratorFunction(...)` 构造器:
/// 动态编译一个匿名异步生成器函数(`async function*` 形态)。
pub fn async_generator_function_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
dynamic_function_core(vm, &args[1..], true, true)
}
/// 四个动态函数构造器的公共体:除最后一个实参为函数体外,其余实参为形参名;
/// 无实参时函数体为空串。实参转单元序列后经 `source_escape` 源码域转义再
/// 动态编译(`is_generator` / `is_async` 决定 wrap 源码函数形态)。
/// 编译成功返回函数对象,语法错误抛 SyntaxError,实参 ToPrimitive 失败抛 TypeError。
fn dynamic_function_core<H: VmHost>(
vm: &mut H, arg_regs: &[u8], is_generator: bool, is_async: bool,
) -> NativeResult {
let (param_regs, body_reg) = if arg_regs.is_empty() {
(vec![], None)
} else {
@@ -44,7 +71,7 @@ pub fn function_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
None => String::new(),
};
match vm.create_dynamic_function(&params, &body) {
match vm.create_dynamic_function(&params, &body, is_generator, is_async) {
Ok(func) => NativeResult::Ok(func),
Err(msg) => NativeResult::Err(crate::error::create_syntax_error(vm, &msg)),
}
@@ -344,9 +371,9 @@ fn bound_restricted_thrower<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult
/// %ThrowTypeError%:Function.prototype 的 caller/arguments 受限访问器共用。
///
/// 按接收者严格性分流:严格函数对象与 native 函数(含 Function.prototype 本身)
/// 的 get/set 一律抛 TypeError;非严格函数对象读不抛、返回 undefined(写不抛、
/// 丢弃写入),与规范"非严格函数 caller 可读"的残面一致。
/// 按接收者受限性分流:严格函数对象与生成器 / 异步 / 异步生成器函数对象
/// 的 get/set 一律抛 TypeError;非严格普通函数对象读不抛、返回 undefined
/// (写不抛、丢弃写入),与规范"非严格函数 caller 可读"的残面一致。
pub fn function_restricted_thrower<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
let obj = match vm.checked_object_ptr(this_val, "restricted property access") {
@@ -354,7 +381,7 @@ pub fn function_restricted_thrower<H: VmHost>(vm: &mut H, args: &[u8]) -> Native
Ok(None) => return NativeResult::Err(crate::error::create_type_error(vm, "restricted property access")),
Err(e) => return NativeResult::Err(crate::error::create_type_error(vm, &e)),
};
if !vm.function_is_strict(unsafe { &*obj }) {
if !vm.function_is_restricted(unsafe { &*obj }) {
return NativeResult::Ok(JsValue::undefined());
}
NativeResult::Err(crate::error::create_type_error(vm, "restricted property access"))
+12 -3
View File
@@ -224,6 +224,9 @@ pub trait VmHost {
/// 函数对象是否为严格模式函数(经子模块 `is_strict` 判定);native 函数
/// (无子模块)视为严格。供 caller/arguments 受限访问器按严格性分流抛错。
fn function_is_strict(&self, obj: &JsObject) -> bool;
/// caller/arguments 访问是否受限:严格函数对象,或生成器 / 异步 /
/// 异步生成器函数对象([[Prototype]] 为三个动态函数原型之一)。
fn function_is_restricted(&self, obj: &JsObject) -> bool;
fn promote_if_needed_for_write_ptr(&mut self, target_ptr: *mut JsObject, value: JsValue) -> JsValue;
fn step_rng(&mut self);
fn math_rng_value(&self) -> f64;
@@ -234,9 +237,15 @@ pub trait VmHost {
/// - 仅在同一 VM 世代的字节码帧执行期读取:native 调用不压 `cell_stack`,故
/// builtin 内读到的是调用方模块帧;`cell_idx` 越界或槽为空返回 `None`。
fn module_frame_cell(&self, cell_idx: u32) -> Option<*mut Cell>;
/// 动态编译一个函数体(`Function` 构造器用):把参数列表与函数体编译为可调用
/// 函数对象。编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_function(&mut self, params: &[String], body: &str) -> Result<JsValue, String>;
/// 动态编译一个函数体(`Function` / `GeneratorFunction` / `AsyncFunction` /
/// `AsyncGeneratorFunction` 构造器用):把参数列表与函数体编译为可调用
/// 函数对象。`is_generator` / `is_async` 决定 wrap 源码的函数形态
/// (`function` / `function*` / `async function` / `async function*`),
/// 函数对象原型与 `prototype` 属性面按编译标志自动分流。
/// 编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_function(
&mut self, params: &[String], body: &str, is_generator: bool, is_async: bool,
) -> Result<JsValue, String>;
/// 动态编译脚本(`eval` 字符串模式):按脚本模式编译,var/函数声明落全局对象。
/// 编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_script(&mut self, code: &str) -> Result<JsValue, String>;
+41 -20
View File
@@ -399,28 +399,42 @@ pub(crate) fn init_async_intrinsics(vm: &mut Vm) {
let sh = vm.kernel_core.shape_forge().as_ref();
let fn_proto_val = vm.session.builtin_world().fn_proto_val();
// %AsyncFunction% 占位构造器:proto = Function.prototype,调用抛错(动态
// 创建未实现)。选择性重建复用:前轮占位构造器按键迁移(prototype 槽在
// 下方 P 槽换入后重指新原型),不再每轮新建对象。
// %AsyncFunction% 构造器:proto = Function.prototype,动态编译异步函数。
// 选择性重建复用:前轮构造器按键迁移(prototype 槽在下方 P 槽换入后重指
// 新原型),不再每轮新建对象。
let af_ctor_label = sf.intern("AsyncFunctionCtor").0;
let af_reuse_key = oxide_kernel::builtin::FnWrapperKey::new(0, af_ctor_label, 0, 0);
// SAFETY: async_function_stub 是 NativeFn 函数项。
let af_stub_ptr = unsafe { NativeFnPtr::from_raw(async_function_stub as *const ()) };
let (af_ctor_ptr, af_ctor_is_new) = match vm.session.builtin_world().find_fn_wrapper(af_reuse_key, af_stub_ptr, 1) {
// SAFETY: async_function_constructor 是 NativeFn 函数项。
let af_ctor_fn_ptr = unsafe {
NativeFnPtr::from_raw(oxide_builtins::function::async_function_constructor::<Vm> as *const ())
};
let (af_ctor_ptr, af_ctor_is_new) = match vm.session.builtin_world().find_fn_wrapper(af_reuse_key, af_ctor_fn_ptr, 1) {
Some(ptr) => (ptr, false),
None => {
let mut af_ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
// [[Prototype]] = Function 构造器本体(与 Function 构造器同链,
// `Object.getPrototypeOf(AsyncFunction) === Function` 语义)。
let fn_ctor_val =
JsValue::from_js_object(vm.session.builtin_world().function_constructor.as_ptr() as *mut JsObject);
let mut af_ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_ctor_val));
af_ctor.set_function(true);
af_ctor.set_native_arg_count(1);
af_ctor.set_native_fn(Some(af_stub_ptr));
af_ctor.set_native_fn(Some(af_ctor_fn_ptr));
// 构造器 tag:IsConstructor 判定与 new 表达式派发据此放行。
af_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);
af_ctor.set_shape_id(length_shape);
let name_si = sf.intern("name").0;
let ctor_shape = sh.make_shape(af_ctor.shape_id(), name_si);
af_ctor.set_shape_id(ctor_shape);
let npos = af_ctor.push_prop(JsValue::perm_string(sf.string_ptr(sf.intern("AsyncFunction").0)));
af_ctor.set_data_meta(npos, PropAttributes::new(false, false, true));
let name_shape = sh.make_shape(af_ctor.shape_id(), name_si);
af_ctor.set_shape_id(name_shape);
let proto_si = sf.intern("prototype").0;
let ctor_shape2 = sh.make_shape(af_ctor.shape_id(), proto_si);
af_ctor.set_shape_id(ctor_shape2);
let proto_shape = sh.make_shape(af_ctor.shape_id(), proto_si);
af_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(af_ctor.shape_id(), tag_key);
af_ctor.set_shape_id(tag_shape);
let af_ctor_ptr = Box::into_raw(af_ctor);
// 登记进 world 释放表(带复用键):session 收尾统一释放构造器本体与属性区。
vm.session.builtin_world().track_fn_wrapper(af_ctor_ptr, af_reuse_key);
@@ -445,26 +459,33 @@ pub(crate) fn init_async_intrinsics(vm: &mut Vm) {
af_proto.set_data_meta(tag_pos, PropAttributes::new(false, false, true));
// proto 本体只存在于 P 槽(Arc 副本,原 Box 随函数结束释放):装入 P 槽后再把
// 构造器 prototype 属性指向 P 槽实例,使其与动态异步函数使用的 [[Prototype]]
// 同一对象,保证 `AsyncFunction.prototype === (async () => {}).__proto__`。
// 构造器 length/name/prototype/@@toStringTag 属性(按形状序)指向 P 槽实例,
// 使其与动态异步函数使用的 [[Prototype]] 同一对象,保证
// `AsyncFunction.prototype === (async () => {}).__proto__`。
// 复用构造器 prototype 槽原位改指新 P 原型(旧原型已随 P 换出释放)。
Vm::swap_intrinsic_proto(&mut vm.async_function_proto, *af_proto);
// SAFETY: af_ctor_ptr 为 Box 原分配(已登记释放表、生命周期覆盖 session),本 Vm 独占。
unsafe {
let ctor_mut = &mut *af_ctor_ptr;
let proto_val = JsValue::from_js_object(vm.async_function_proto.as_ptr() as *mut JsObject);
let name_val = JsValue::perm_string(sf.string_ptr(sf.intern("AsyncFunction").0));
if af_ctor_is_new {
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 if let Some(pos) = sh.lookup_position(ctor_mut.shape_id(), sf.intern("prototype").0) {
ctor_mut.set_prop_at(pos, proto_val);
}
}
}
/// `%AsyncFunction%` 占位:动态异步函数创建未实现,调用抛错。
fn async_function_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
NativeResult::Err(oxide_builtins::error::create_type_error(vm, "AsyncFunction constructor is not supported"))
// 绑定 global:按规范 AsyncFunction 不是全局绑定(is-not-a-global 语义),
// 仅经 `async function` 实例的 constructor 链可达。
}
// ── session GC 支撑:状态快照中的 JsValues 作为异步上下文对象边追踪 ──
+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 作为异步生成器对象边追踪 ──
+53 -24
View File
@@ -766,27 +766,40 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
// %GeneratorFunction.prototype%:proto = Function.prototype,constructor = %GeneratorFunction%。
let mut gf_proto = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
// %GeneratorFunction% 占位构造器:动态生成器函数创建未实现,调用抛
// TypeError。选择性重建复用:前轮占位构造器按键迁移(prototype 槽在
// 下方 P 槽换入后重指新原型),不再每轮新建对象。
// %GeneratorFunction% 构造器:proto = Function.prototype,动态编译生成器
// 函数。选择性重建复用:前轮构造器按键迁移(prototype 槽在下方 P 槽换入后
// 重指新原型),不再每轮新建对象。
let gf_ctor_label = sf.intern("GeneratorFunctionCtor").0;
let gf_reuse_key = oxide_kernel::builtin::FnWrapperKey::new(0, gf_ctor_label, 0, 0);
// SAFETY: generator_function_stub 是 NativeFn 函数项。
let gf_stub_ptr = unsafe { NativeFnPtr::from_raw(generator_function_stub as *const ()) };
let (gf_ctor_ptr, gf_ctor_is_new) = match world.find_fn_wrapper(gf_reuse_key, gf_stub_ptr, 1) {
// SAFETY: generator_function_constructor 是 NativeFn 函数项。
let gf_ctor_fn_ptr = unsafe {
NativeFnPtr::from_raw(
oxide_builtins::function::generator_function_constructor::<Vm> as *const (),
)
};
let (gf_ctor_ptr, gf_ctor_is_new) = match world.find_fn_wrapper(gf_reuse_key, gf_ctor_fn_ptr, 1) {
Some(ptr) => (ptr, false),
None => {
let mut gf_ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
gf_ctor.set_function(true);
gf_ctor.set_native_arg_count(1);
gf_ctor.set_native_fn(Some(gf_stub_ptr));
// prototype/name 属性(构造器形状 [prototype, name])。
let proto_si = sf.intern("prototype").0;
let ctor_shape = sh.make_shape(EMPTY_SHAPE_ID, proto_si);
gf_ctor.set_shape_id(ctor_shape);
gf_ctor.set_native_fn(Some(gf_ctor_fn_ptr));
// 构造器 tag:IsConstructor 判定与 new 表达式派发据此放行。
gf_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);
gf_ctor.set_shape_id(length_shape);
let name_si = sf.intern("name").0;
let name_shape = sh.make_shape(gf_ctor.shape_id(), name_si);
gf_ctor.set_shape_id(name_shape);
let proto_si = sf.intern("prototype").0;
let proto_shape = sh.make_shape(gf_ctor.shape_id(), proto_si);
gf_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(gf_ctor.shape_id(), tag_key);
gf_ctor.set_shape_id(tag_shape);
let gf_ctor_ptr = Box::into_raw(gf_ctor);
// 登记进 world 释放表(带复用键):session 收尾统一释放构造器本体与属性区。
world.track_fn_wrapper(gf_ctor_ptr, gf_reuse_key);
@@ -804,7 +817,7 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
let proto2_shape = sh.make_shape(gf_proto.shape_id(), proto2_si);
gf_proto.set_shape_id(proto2_shape);
let ppos2 = gf_proto.push_prop(JsValue::from_js_object(vm.generator_proto.as_ptr() as *mut JsObject));
gf_proto.set_data_meta(ppos2, oxide_types::object::PropAttributes::new(false, false, false));
gf_proto.set_data_meta(ppos2, oxide_types::object::PropAttributes::new(false, false, true));
// gf_proto[Symbol.toStringTag] = "GeneratorFunction"(数据属性,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);
@@ -814,9 +827,9 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
gf_proto.set_data_meta(tag2_pos, oxide_types::object::PropAttributes::new(false, false, true));
// proto 本体只存在于 P 槽(Arc 副本,原 Box 随函数结束释放):装入 P 槽后再写
// 构造器 prototype/name 属性(按模板序 prototype 在前),prototype 指向 P 槽实例,
// 使其与动态生成器函数使用的 [[Prototype]] 同一对象。复用构造器槽位已填充,
// prototype 原位改指新 P 原型(旧原型已随 P 换出释放)。
// 构造器 length/name/prototype/@@toStringTag 属性(按形状序),prototype 指向
// P 槽实例,使其与动态生成器函数使用的 [[Prototype]] 同一对象。复用构造器槽位
// 已填充,prototype 原位改指新 P 原型(旧原型已随 P 换出释放)。
Vm::swap_intrinsic_proto(&mut vm.generator_function_proto, *gf_proto);
// SAFETY: gf_ctor_ptr 为 Box 原分配(已登记释放表、生命周期覆盖 session),本 Vm 独占。
unsafe {
@@ -824,10 +837,15 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
let proto_val = JsValue::from_js_object(vm.generator_function_proto.as_ptr() as *mut JsObject);
let name_val = JsValue::perm_string(sf.string_ptr(sf.intern("GeneratorFunction").0));
if gf_ctor_is_new {
let ppos = ctor_mut.push_prop(proto_val);
ctor_mut.set_data_meta(ppos, oxide_types::object::PropAttributes::new(false, false, false));
let lpos = ctor_mut.push_prop(JsValue::int(1));
ctor_mut.set_data_meta(lpos, oxide_types::object::PropAttributes::new(false, false, true));
let npos = ctor_mut.push_prop(name_val);
ctor_mut.set_data_meta(npos, oxide_types::object::PropAttributes::new(false, false, true));
let ppos = ctor_mut.push_prop(proto_val);
ctor_mut.set_data_meta(ppos, oxide_types::object::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, oxide_types::object::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) {
@@ -839,14 +857,25 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
}
}
}
}
/// `%GeneratorFunction%` 占位:动态生成器函数创建未实现,调用抛错。
fn generator_function_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
NativeResult::Err(oxide_builtins::error::create_type_error(
vm,
"GeneratorFunction constructor is not supported",
))
// 绑定 global:GeneratorFunction 槽已存在则原位更新(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("GeneratorFunction").0;
let ctor_val = JsValue::from_js_object(gf_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, oxide_types::object::PropAttributes::new(true, false, true));
global.bump_generation();
}
}
// ── session GC 支撑:状态快照中的 JsValues 作为生成器对象边追踪 ──
+16 -3
View File
@@ -19,7 +19,9 @@ impl Vm {
/// 原样透传。
///
/// # 步骤
/// 1. wrap 源码 `function anonymous(p...) { body }`,parse + compile。
/// 1. wrap 源码 `{prefix} anonymous(p...) { body }`(prefix 按生成器 /
/// 异步标志取 `function` / `function*` / `async function` /
/// `async function*`),parse + compile。
/// 2. 取 `sub_modules[0]`(匿名函数模块),把其子树 flat_id 重编号到平表末尾
/// 并重写子树内每条 `CREATE_CLOSURE` 的 imm16。
/// 3. 同步扩容当前代际的常量缓存,建函数对象并设置 name/length。
@@ -33,12 +35,23 @@ impl Vm {
///
/// # 副作用
/// - 扩展当前代际平表(`tables[current_gen]`)与常量缓存。
pub fn create_dynamic_function(&mut self, params: &[String], body: &str) -> Result<JsValue, String> {
pub fn create_dynamic_function(
&mut self, params: &[String], body: &str, is_generator: bool, is_async: bool,
) -> Result<JsValue, String> {
// wrap 源码:body 两端换行防止以行注释结尾吞掉右花括号;形参串后补
// 换行,使形参以 HTML 注释(`<!--`/`-->`)结尾时注释在行末终止、
// 右括号不被吞(规范按形参串与体串各自独立解析,此处以换行等价)。
// 函数形态按生成器 / 异步标志分流,编译标志(is_generator / is_async)
// 由 emit 层从 AST 读回,函数对象原型与 prototype 属性面随之自动分流。
let prefix = if is_async {
if is_generator { "async function*" } else { "async function" }
} else if is_generator {
"function*"
} else {
"function"
};
let params_str = params.join(", ");
let source = format!("function anonymous({params_str}\n) {{\n{body}\n}}");
let source = format!("{prefix} anonymous({params_str}\n) {{\n{body}\n}}");
let allocator = oxide_parser::Allocator::default();
let program = oxide_parser::parse(&allocator, &source)
+19 -2
View File
@@ -179,6 +179,21 @@ impl oxide_runtime_api::VmHost for Vm {
// 按严格处理(受限访问器对其抛错)。
self.callee_module(obj).map(|m| m.is_strict).unwrap_or(true)
}
fn function_is_restricted(&self, obj: &JsObject) -> bool {
// 严格函数对象,或 [[Prototype]] 为三个动态函数原型之一(生成器 /
// 异步 / 异步生成器函数):caller/arguments 访问一律受限。
if self.function_is_strict(obj) {
return true;
}
let proto = obj.proto();
if !proto.is_object() {
return false;
}
let p = proto.as_js_object_ptr();
p == self.generator_function_proto.as_ptr() as *mut JsObject
|| p == self.async_function_proto.as_ptr() as *mut JsObject
|| p == self.async_generator_function_proto.as_ptr() as *mut JsObject
}
fn promote_if_needed_for_write_ptr(&mut self, target_ptr: *mut JsObject, value: JsValue) -> JsValue {
self.promote_if_needed_for_write_ptr(target_ptr, value)
}
@@ -201,8 +216,10 @@ impl oxide_runtime_api::VmHost for Vm {
.and_then(|cells| cells.get(cell_idx as usize).copied())
.filter(|p| !p.is_null())
}
fn create_dynamic_function(&mut self, params: &[String], body: &str) -> Result<JsValue, String> {
self.create_dynamic_function(params, body)
fn create_dynamic_function(
&mut self, params: &[String], body: &str, is_generator: bool, is_async: bool,
) -> Result<JsValue, String> {
self.create_dynamic_function(params, body, is_generator, is_async)
}
fn create_dynamic_script(&mut self, code: &str) -> Result<JsValue, String> {
self.create_dynamic_script(code)
+2 -1
View File
@@ -781,8 +781,9 @@ impl Vm {
+ crate::session_gc::SessionGc::object_heap_data_bytes(unsafe { &*obj_ptr }) as usize;
let func_val = JsValue::object(obj_ptr as *mut u8);
if !is_arrow {
if !is_arrow && !(is_async && !is_generator) {
// 原型对象自身的 [[Prototype]]:生成器为 %GeneratorPrototype%,普通函数为 Object.prototype。
// 纯异步函数(非生成器)无 `prototype` 属性:规范不为其建 prototype 子对象。
let proto_of_proto = if is_async_generator {
JsValue::from_js_object(self.async_generator_proto.as_ptr() as *mut JsObject)
} else if is_generator {