Files
OxideJS-New/crates/oxide_vm/src/async_func.rs
T

810 lines
38 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 异步函数运行时:异步帧快照挂起/恢复 + await 微任务驱动。
//!
//! 策略:`async function` 调用返回 capability promise(状态存 `AsyncState`),
//! body 立即同步执行到第一个 `AWAIT`(与 generator 的惰性不同)。`await` 求值
//! 被等待值、PromiseResolve 包装后登记恢复反应;promise settle 后微任务经
//! `Vm::async_context` 驱动的嵌套 dispatch 恢复异步帧,执行到下一个
//! `AWAIT`/`RETURN`/异常。挂起快照/恢复机械复用 generator 的 regs/pc/bytecode/
//! spill/save/try/cell 栈段搬运。`AWAIT` 经 `Vm::async_suspended` 信号让内嵌
//! dispatch 返回,恢复方据此快照挂起状态。
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_runtime_api::{to_boolean, NativeResult};
use oxide_types::object::{Cell, JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use crate::vm::{Completion, Vm};
/// 异步函数执行阶段。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum AsyncPhase {
/// 尚未开始执行(调用时压帧前)。
New,
/// 正在执行(body 运行在嵌套 dispatch 循环中)。
Running,
/// 已在 `await` 挂起。
Suspended,
/// 已正常返回 / 异常结束。
Completed,
}
/// 异步函数挂起时的完整执行上下文快照 + capability。
///
/// 存在异步上下文对象 `native_data`(`Box`),跨 await 微任务存活;其中所有
/// `JsValue` 由 session GC 经上下文对象边追踪(见 `session_gc`)。
pub(crate) struct AsyncState {
pub phase: AsyncPhase,
/// 异步函数对象(首次执行时压帧用)。
pub callee: JsValue,
/// 首次调用实参。
pub args: Vec<JsValue>,
/// 首次调用时的方法接收者(`obj.g()` 的 `obj`),压帧时作 `this` 绑定。
pub this_value: JsValue,
/// 完成后返回值。
pub result: JsValue,
/// 调用返回给调用方的 capability promise。
pub promise: JsValue,
/// capability 上的 resolve/reject 闭包(完成时结算用)。
pub resolve: JsValue,
pub reject: JsValue,
/// 挂起时的执行上下文(regs/pc/bytecode/各栈段/迭代器/在途异常)。
pub suspended: crate::suspended::SuspendedFrame,
}
/// 一次 await 恢复的注入模式。
#[derive(Debug, Clone, Copy)]
pub(crate) enum AsyncResumeMode {
/// 普通恢复:fulfilled 值作为 `await` 表达式结果(写 reg 0)。
Next(JsValue),
/// 拒绝恢复:在挂起点抛错(可被 catch/finally 捕获)。
Throw(JsValue),
}
/// 异步上下文对象上存 capability 闭包的属性名(await 恢复闭包定位上下文用)。
pub(crate) const ASYNC_CTX_PROP: &str = "__oxide_async_ctx__";
/// 恢复闭包上区分 reject 角色的属性名。
const ASYNC_REJECT_PROP: &str = "__oxide_async_reject__";
/// 逃出关闭结算闭包上存 return() promise 的属性名(陈旧防御校验用)。
pub(crate) const ASYNC_ESCAPE_PROMISE_PROP: &str = "__oxide_async_escape_promise__";
impl Vm {
/// 调用异步函数返回的 capability promise:创建上下文对象 + 状态盒,立即压帧
/// 同步执行 body 到第一个 AWAIT/RETURN/异常,返回 pending promise。
///
/// # 副作用
/// - 上下文对象状态从 `New` 转为 `Running`;AWAIT 挂起后转为 `Suspended`。
/// - 参数默认值副作用、body 到首个 await 的同步执行在调用时刻完成。
pub(crate) fn create_async_object(
&mut self, callee: JsValue, this_value: JsValue, args: &[JsValue],
) -> Result<JsValue, String> {
let (promise, resolve, reject) = self.new_promise_capability();
let ctx_val = self.create_async_context(callee, this_value, args, promise, resolve, reject);
self.start_async(ctx_val)?;
Ok(promise)
}
/// 分配异步上下文对象(`OBJ_TYPE_ASYNC`),AsyncState 状态盒挂 `native_data`。
fn create_async_context(
&mut self, callee: JsValue, this_value: JsValue, args: &[JsValue], promise: JsValue, resolve: JsValue,
reject: JsValue,
) -> JsValue {
let proto_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
let obj = unsafe { &mut *ptr };
obj.type_tag = JsObject::OBJ_TYPE_ASYNC;
let state = Box::new(AsyncState {
phase: AsyncPhase::New,
callee,
args: args.to_vec(),
this_value,
result: JsValue::undefined(),
promise,
resolve,
reject,
suspended: crate::suspended::SuspendedFrame::new_empty(),
});
obj.set_native_data(Box::into_raw(state) as *mut u8);
JsValue::from_js_object(ptr)
}
/// 取出异步上下文对象的状态指针(调用方须先校验 `is_async_obj`)。
fn async_state_ptr(&self, ctx_val: JsValue) -> *mut AsyncState {
unsafe { (*ctx_val.as_js_object_ptr()).native_data() as *mut AsyncState }
}
/// 首次启动异步体:压入异步帧并在嵌套 dispatch 中执行到第一个 AWAIT/RETURN/异常。
///
/// # 步骤
/// 1. 用 `InlineSyncState` 保存调用方 VM 状态,清空 VM 后压入异步帧。
/// 2. 嵌套 `dispatch()` 运行 body;AWAIT 置 `async_suspended` 使 dispatch 返回。
/// 3. 挂起则快照;完成则 resolve capability;异常则 reject。恢复调用方状态。
fn start_async(&mut self, ctx_val: JsValue) -> Result<(), String> {
let state_ptr = self.async_state_ptr(ctx_val);
let saved = self.save_inline_state(256);
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
self.async_dispatch = true;
// 普通异步函数执行期间 AWAIT 走普通异步恢复路径:屏蔽外层异步生成器上下文。
self.async_gen_dispatch = false;
self.async_context = Some(ctx_val);
self.native_call_depth += 1;
let callee = unsafe { (*state_ptr).callee };
let this_value = unsafe { (*state_ptr).this_value };
let args = unsafe { std::mem::take(&mut (*state_ptr).args) };
let push_res = self.prepare_execution_initial(callee, this_value, &args);
unsafe { (*state_ptr).args = args };
if let Err(e) = push_res {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err(e);
}
unsafe { (*state_ptr).phase = AsyncPhase::Running };
let result = self.dispatch();
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
if std::mem::take(&mut self.async_suspended) {
let state = unsafe { &mut *state_ptr };
self.snapshot_async(state)?;
self.restore_inline_state(saved);
return Ok(());
}
match result {
Ok(value) => {
self.finish_async(state_ptr, Ok(value))?;
self.restore_inline_state(saved);
Ok(())
}
Err(e) => {
let exc = self
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_from_text(self, &e));
self.finish_async(state_ptr, Err(exc))?;
self.restore_inline_state(saved);
Ok(())
}
}
}
/// 恢复异步体一步执行:`await` 的 promise settle 后由恢复闭包调用。
///
/// # 步骤
/// 1. 用 `InlineSyncState` 保存调用方 VM 状态,把挂起快照灌回 VM。
/// 2. 注入 await 结果(fulfilled 写 reg 0 / rejected 注入异常并展开)。
/// 3. 嵌套 `dispatch()` 运行 body 到下一个 AWAIT/RETURN/异常。
/// 4. 挂起则快照新状态;完成/异常则结算 capability。恢复调用方状态。
pub(crate) fn resume_async(&mut self, ctx_val: JsValue, mode: AsyncResumeMode) -> Result<(), String> {
let state_ptr = self.async_state_ptr(ctx_val);
let saved = self.save_inline_state(256);
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
self.async_dispatch = true;
// 普通异步函数执行期间 AWAIT 走普通异步恢复路径:屏蔽外层异步生成器上下文。
self.async_gen_dispatch = false;
self.async_context = Some(ctx_val);
self.native_call_depth += 1;
{
let state = unsafe { &mut *state_ptr };
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
// callee 记录的表代际已被回收(跨 run 且无存活函数引用),无法恢复。
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async function suspended across runs is no longer valid".into());
}
state.phase = AsyncPhase::Running;
}
// 注入 await 结果:fulfilled 写 reg 0;rejected 恢复异常上下文并展开。
if let AsyncResumeMode::Throw(exc) = mode {
self.exception_value = Some(exc);
self.pending_error_kind = Some(self.thrown_error_kind(exc));
if self.unwind().is_err() {
// 异常逃逸出异步帧(无 catch/finally):结算为 reject。
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
let thrown = self.last_uncaught_value.take().unwrap_or(exc);
self.finish_async(state_ptr, Err(thrown))?;
self.restore_inline_state(saved);
return Ok(());
}
} else if let AsyncResumeMode::Next(value) = mode {
self.regs[0] = value;
}
let result = self.dispatch();
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
if std::mem::take(&mut self.async_suspended) {
let state = unsafe { &mut *state_ptr };
self.snapshot_async(state)?;
self.restore_inline_state(saved);
return Ok(());
}
match result {
Ok(value) => {
self.finish_async(state_ptr, Ok(value))?;
self.restore_inline_state(saved);
Ok(())
}
Err(e) => {
let exc = self
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_from_text(self, &e));
self.finish_async(state_ptr, Err(exc))?;
self.restore_inline_state(saved);
Ok(())
}
}
}
/// 恢复嵌套 dispatch 覆盖的 async 上下文标志(含外层异步生成器上下文)。
fn restore_async_flags(
&mut self, prev_ctx: Option<JsValue>, prev_dispatch: bool, prev_gen_ctx: Option<JsValue>,
prev_gen_dispatch: bool,
) {
self.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
self.async_gen_dispatch = prev_gen_dispatch;
self.async_gen_context = prev_gen_ctx;
}
/// 结算异步函数:正常结束 resolve capability,异常结束 reject capability。
fn finish_async(&mut self, state_ptr: *mut AsyncState, outcome: Result<JsValue, JsValue>) -> Result<(), String> {
let (promise, value) = {
let state = unsafe { &mut *state_ptr };
state.phase = AsyncPhase::Completed;
match &outcome {
Ok(v) => {
state.result = *v;
(state.promise, *v)
}
Err(e) => {
state.result = JsValue::undefined();
(state.promise, *e)
}
}
};
match outcome {
Ok(_) => {
let _ = self.resolve_promise(promise, value);
}
Err(_) => {
let _ = self.reject_promise(promise, value);
}
}
Ok(())
}
/// `await` dispatch:PromiseResolve 包装被等待值、登记恢复反应,置挂起信号。
///
/// # 副作用
/// - 被等待值经 `promise_resolve` 包装(含 `constructor` 查询与 thenable 委托)。
/// - 经 `perform_promise_then` 登记 fulfill/reject 恢复反应(微任务入队)。
/// - 异步生成器内(`async_gen_dispatch`)登记异步生成器恢复闭包并置
/// `async_gen_suspended`;普通异步函数走 `async_suspended`。
pub(crate) fn dispatch_await(&mut self, rd: usize) -> Result<(), String> {
let value = self.regs[rd];
self.perform_await(value)
}
/// await 核心:PromiseResolve 包装被等待值、登记恢复反应,置挂起信号。
///
/// # 副作用
/// - 被等待值经 `promise_resolve` 包装:原生 Promise 按其 `constructor`
/// 查询决定直接复用或重包装,thenable 委托结算;包装失败(constructor
/// getter / 结算抛错)时构造 rejected promise 承接异常。
/// - 经 `perform_promise_then` 登记 fulfill/reject 恢复反应(微任务入队)。
/// - 异步生成器内(`async_gen_dispatch`)登记异步生成器恢复闭包并置
/// `async_gen_suspended`;普通异步函数走 `async_suspended`。
pub(crate) fn perform_await(&mut self, value: JsValue) -> Result<(), String> {
let ctx = match self.async_context {
Some(c) => c,
None => return Err("AWAIT executed outside async function".into()),
};
let promise = match self.promise_resolve(value) {
Ok(p) => p,
Err(exc) => {
let (p, _, _) = self.new_promise_capability();
let _ = self.reject_promise(p, exc);
p
}
};
if self.async_gen_dispatch {
let fulfill_fn = self.make_async_gen_await_resume_fn(ctx, false);
let reject_fn = self.make_async_gen_await_resume_fn(ctx, true);
let _ = self.perform_promise_then(promise, fulfill_fn, reject_fn);
self.async_gen_suspended = true;
return Ok(());
}
let fulfill_fn = self.make_async_await_resume_fn(ctx, false);
let reject_fn = self.make_async_await_resume_fn(ctx, true);
let _ = self.perform_promise_then(promise, fulfill_fn, reject_fn);
self.async_suspended = true;
Ok(())
}
/// 构造 await 恢复闭包:携带目标异步上下文对象,区分 fulfill/reject 角色。
fn make_async_await_resume_fn(&mut self, ctx: JsValue, reject_role: bool) -> JsValue {
let fn_proto = self.realm.session.borrow().builtin_world().fn_proto_val();
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto);
func.set_function(true);
// SAFETY: async_await_resume_closure 是 NativeFn 函数项。
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(async_await_resume_closure as *const ()) }));
func.set_native_arg_count(1);
let ptr = self.alloc_object(func);
let obj = unsafe { &mut *ptr };
let ctx_si = self.kernel_core.perm_interner().intern(ASYNC_CTX_PROP).0;
self.set_or_create_prop_value(obj, ctx_si, ctx);
let role_si = self.kernel_core.perm_interner().intern(ASYNC_REJECT_PROP).0;
self.set_or_create_prop_value(obj, role_si, JsValue::bool(reject_role));
self.add_fn_name_length(obj, "", 1);
JsValue::from_js_object(ptr)
}
/// 构造逃出关闭结算闭包:携带目标异步上下文对象与 return() promise,区分
/// fulfill/reject 角色。
pub(crate) fn make_async_escape_close_fn(&mut self, ctx: JsValue, promise: JsValue, reject_role: bool) -> JsValue {
let fn_proto = self.realm.session.borrow().builtin_world().fn_proto_val();
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto);
func.set_function(true);
// SAFETY: async_escape_close_closure 是 NativeFn 函数项。
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(async_escape_close_closure as *const ()) }));
func.set_native_arg_count(1);
let ptr = self.alloc_object(func);
let obj = unsafe { &mut *ptr };
let ctx_si = self.kernel_core.perm_interner().intern(ASYNC_CTX_PROP).0;
self.set_or_create_prop_value(obj, ctx_si, ctx);
let role_si = self.kernel_core.perm_interner().intern(ASYNC_REJECT_PROP).0;
self.set_or_create_prop_value(obj, role_si, JsValue::bool(reject_role));
let promise_si = self.kernel_core.perm_interner().intern(ASYNC_ESCAPE_PROMISE_PROP).0;
self.set_or_create_prop_value(obj, promise_si, promise);
self.add_fn_name_length(obj, "", 1);
JsValue::from_js_object(ptr)
}
/// 把当前 VM 执行状态(异步 body 刚在嵌套 dispatch 中让出)快照进状态盒。
///
/// 异步帧弹出存 `suspended.frame`,其余栈段整段搬入(嵌套循环期间这些栈
/// 只含异步数据)。
fn snapshot_async(&mut self, state: &mut AsyncState) -> Result<(), String> {
state.suspended.save_from(self, state.callee)?;
state.phase = AsyncPhase::Suspended;
Ok(())
}
/// 恢复逃出 for-await-of 的异步函数:return() 的 promise 结算后继续关闭剩余
/// 条目并执行完成。
///
/// # 步骤
/// 1. 陈旧防御:状态盒 pending_async_escape.close_promise 须与本闭包 promise
/// 匹配,不匹配则不处理(防同一 promise 被双结算)。
/// 2. 把挂起快照灌回 VM,取出完成与剩余待关条目并清除 pending_async_escape。
/// 3. 多层逃出:remaining 非空时逐层关闭(每层一轮结算),空了才执行完成。
/// 4. 执行完成:Return 走 do_return,Break/Continue 跳转 target_pc 续 dispatch。
/// 5. 再挂起则快照新状态;完成/异常则结算 capability。恢复调用方状态。
///
/// # 边界与前提
/// - 关闭 promise 拒绝时(reject 角色),拒绝值替代在途完成:抛拒绝原因,
/// 外围 catch/finally 接管;无处理器时异步函数以拒绝原因拒绝。
fn resume_async_escape(
&mut self, ctx: JsValue, promise: JsValue, is_reject: bool, value: JsValue,
) -> Result<(), String> {
let state_ptr = self.async_state_ptr(ctx);
let saved = self.save_inline_state(256);
// 清上一轮多层关闭残留的挂起信号(多层逐层结算每轮清零,防陈旧信号误消费)。
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
self.async_dispatch = true;
self.async_gen_dispatch = false;
self.async_context = Some(ctx);
self.native_call_depth += 1;
{
let state = unsafe { &mut *state_ptr };
// 陈旧防御:close_promise 须匹配,陈旧闭包不处理。
let is_stale = !matches!(
state.suspended.pending_async_escape.as_ref(),
Some(p) if p.close_promise == promise
);
if is_stale {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async function suspended across runs is no longer valid".into());
}
state.phase = AsyncPhase::Running;
}
// 取出完成与剩余待关条目并清除 pending_async_escape。
let (completion, mut remaining) = match self.pending_async_escape.take() {
Some(p) => (p.completion, p.remaining),
// 陈旧防御已早退,正常路径此处必为 Some;防御性兜底。
None => return Ok(()),
};
// 多层逃出:remaining 非空时逐层关闭(每层一轮结算),空了才执行完成
// (或抛拒绝原因)。挂起信号由 register 置位,快照后返回续下一轮结算;
// 该信号由下一轮结算闭包消费、不经派发循环,须先清防陈旧信号泄漏进
// 另一上下文的 dispatch。
while let Some(next_iter) = remaining.first().cloned() {
remaining.remove(0);
match self.register_async_escape_close(next_iter, completion, remaining.clone()) {
Ok(true) => {
self.async_suspended = false;
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
Ok(false) => continue,
Err(e) => return Err(e),
}
}
// 关闭拒绝:拒绝值替代在途完成。抛拒绝原因,外围 catch/finally 接管;
// 无处理器时异步函数以拒绝原因拒绝。
if is_reject {
self.exception_value = Some(value);
self.pending_error_kind = Some(self.thrown_error_kind(value));
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(value);
self.finish_async(state_ptr, Err(exc))?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
let result = self.dispatch();
// 处理器体内再挂起(await):快照新状态后退出。
if std::mem::take(&mut self.async_suspended) {
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
match result {
Ok(value) => self.finish_async(state_ptr, Ok(value))?,
Err(e) => {
let exc = self
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_from_text(self, &e));
self.finish_async(state_ptr, Err(exc))?;
}
}
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
// remaining 已空,执行完成。
match completion {
Completion::Return { value: ret_val, .. } => {
let result = self.do_return(ret_val)?;
if let Some(result) = result {
self.finish_async(state_ptr, Ok(result))?;
}
}
Completion::Break { target_pc, .. } | Completion::Continue { target_pc, .. } => {
self.pc = target_pc;
let result = self.dispatch();
// 完成跳转后 body 继续执行到下一个 await/return/异常。
if std::mem::take(&mut self.async_suspended) {
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
match result {
Ok(value) => self.finish_async(state_ptr, Ok(value))?,
Err(e) => {
let exc = self
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_from_text(self, &e));
self.finish_async(state_ptr, Err(exc))?;
}
}
}
}
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
Ok(())
}
}
/// await 恢复闭包:读自身 prop 的异步上下文与角色,恢复异步帧继续执行。
fn async_await_resume_closure(vm: &mut Vm, args: &[u8]) -> NativeResult {
let callee = vm.reg(254);
if !callee.is_object() {
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "await resume handler is invalid"));
}
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let ctx_si = vm.kernel_core.perm_interner().intern(ASYNC_CTX_PROP).0;
let ctx = vm.resolve_property(callee_obj, ctx_si).unwrap_or(JsValue::undefined());
let role_si = vm.kernel_core.perm_interner().intern(ASYNC_REJECT_PROP).0;
let is_reject = vm.resolve_property(callee_obj, role_si).is_some_and(to_boolean);
let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
let mode = if is_reject {
AsyncResumeMode::Throw(value)
} else {
AsyncResumeMode::Next(value)
};
match vm.resume_async(ctx, mode) {
Ok(()) => NativeResult::Ok(JsValue::undefined()),
Err(e) => NativeResult::Err(oxide_builtins::error::create_from_text(vm, &e)),
}
}
/// 逃出关闭结算闭包:读自身 prop 的异步上下文、return() promise 与角色,恢复挂起
/// 帧并执行完成。
fn async_escape_close_closure(vm: &mut Vm, args: &[u8]) -> NativeResult {
let callee = vm.reg(254);
if !callee.is_object() {
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "escape close handler is invalid"));
}
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let ctx_si = vm.kernel_core.perm_interner().intern(ASYNC_CTX_PROP).0;
let ctx = vm.resolve_property(callee_obj, ctx_si).unwrap_or(JsValue::undefined());
let role_si = vm.kernel_core.perm_interner().intern(ASYNC_REJECT_PROP).0;
let is_reject = vm.resolve_property(callee_obj, role_si).is_some_and(to_boolean);
let promise_si = vm.kernel_core.perm_interner().intern(ASYNC_ESCAPE_PROMISE_PROP).0;
let promise = vm.resolve_property(callee_obj, promise_si).unwrap_or(JsValue::undefined());
let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
match vm.resume_async_escape(ctx, promise, is_reject, value) {
Ok(()) => NativeResult::Ok(JsValue::undefined()),
Err(e) => NativeResult::Err(oxide_builtins::error::create_from_text(vm, &e)),
}
}
/// 初始化/重建异步函数内建对象:`%AsyncFunction.prototype%`(+ 占位 `%AsyncFunction%`)。
///
/// 异步函数对象的 [[Prototype]] 指向此原型(`f.constructor.name` → "AsyncFunction")。
/// 动态 `AsyncFunction` 构造器创建未实现,调用抛 TypeError。
pub(crate) fn init_async_intrinsics(vm: &mut Vm) {
let sf = vm.kernel_core.perm_interner().as_ref();
let sh = vm.kernel_core.shape_forge().as_ref();
let fn_proto_val = vm.realm.session.borrow().builtin_world().fn_proto_val();
// %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_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
.realm
.session
.borrow()
.builtin_world()
.find_fn_wrapper(af_reuse_key, af_ctor_fn_ptr, 1)
{
Some(ptr) => (ptr, false),
None => {
// [[Prototype]] = Function 构造器本体(与 Function 构造器同链,
// `Object.getPrototypeOf(AsyncFunction) === Function` 语义)。
let fn_ctor_val = JsValue::from_js_object(
vm.realm.session.borrow().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_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 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 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::encode_symbol_key(
vm.realm_id(),
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.realm
.session
.borrow()
.builtin_world()
.track_fn_wrapper(af_ctor_ptr, af_reuse_key);
(af_ctor_ptr, true)
}
};
// %AsyncFunction.prototype%:proto = Function.prototype,constructor = %AsyncFunction%。
let mut af_proto = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
// af_proto.constructor = %AsyncFunction%(构造器登记进 world 释放表,与 builtin 方法 wrapper 同生命周期)。
let ctor_si = sf.intern("constructor").0;
let pshape = sh.make_shape(af_proto.shape_id(), ctor_si);
af_proto.set_shape_id(pshape);
let cpos = af_proto.push_prop(JsValue::from_js_object(af_ctor_ptr));
af_proto.set_data_meta(cpos, PropAttributes::new(false, false, true));
// af_proto[Symbol.toStringTag] = "AsyncFunction"(数据属性,w/e/c = false/false/true)。
let tag_key = oxide_types::private_key::encode_symbol_key(
vm.realm_id(),
oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG,
);
let tag_shape = sh.make_shape(af_proto.shape_id(), tag_key);
af_proto.set_shape_id(tag_shape);
let tag_pos = af_proto.push_prop(JsValue::perm_string(sf.string_ptr(sf.intern("AsyncFunction").0)));
af_proto.set_data_meta(tag_pos, PropAttributes::new(false, false, true));
// proto 本体只存在于 P 槽(Arc 副本,原 Box 随函数结束释放):装入 P 槽后再把
// 构造器 length/name/prototype/@@toStringTag 属性(按形状序)指向 P 槽实例,
// 使其与动态异步函数使用的 [[Prototype]] 同一对象,保证
// `AsyncFunction.prototype === (async () => {}).__proto__`。
// 复用构造器 prototype 槽原位改指新 P 原型(旧原型已随 P 换出释放)。
Vm::swap_intrinsic_proto(&mut vm.realm.async_function_proto.borrow_mut(), *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.realm.async_function_proto.borrow().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);
}
}
// 绑定 global:按规范 AsyncFunction 不是全局绑定(is-not-a-global 语义),
// 仅经 `async function` 实例的 constructor 链可达。
}
// ── session GC 支撑:状态快照中的 JsValues 作为异步上下文对象边追踪 ──
#[expect(clippy::mut_from_ref)]
fn async_state_mut(obj: &JsObject) -> Option<&mut AsyncState> {
let ptr = obj.native_data() as *mut AsyncState;
if ptr.is_null() {
None
} else {
// SAFETY: native_data 在 create_async_context 中由 Box::into_raw 分配,
// 生命周期与异步上下文对象一致;GC 路径(mark 边收集)只读状态盒。
Some(unsafe { &mut *ptr })
}
}
/// 异步状态内全部引用边的扁平列表(GC mark 边):对象/字符串/BigInt 均产出,
/// 消费侧按值类型分发到对象栈与存活集。
pub(crate) fn async_native_edges(obj: &JsObject) -> Vec<JsValue> {
let Some(state) = async_state_mut(obj) else {
return Vec::new();
};
let mut edges = Vec::new();
edges.push(state.callee);
edges.extend(state.args.iter().copied());
edges.push(state.result);
edges.push(state.promise);
edges.push(state.resolve);
edges.push(state.reject);
state.suspended.for_each_value(|v| edges.push(v));
edges
}
/// 异步状态内所有 session 字符串的扁平列表(GC mark 字符串边)。
pub(crate) fn async_native_string_edges(obj: &JsObject) -> Vec<*mut oxide_types::object::JsString> {
let Some(state) = async_state_mut(obj) else {
return Vec::new();
};
let mut out = Vec::new();
let push_str = |v: JsValue, out: &mut Vec<*mut oxide_types::object::JsString>| {
if v.is_string() {
out.push(v.as_string_ptr_mut());
}
};
push_str(state.callee, &mut out);
for &v in &state.args {
push_str(v, &mut out);
}
push_str(state.result, &mut out);
push_str(state.promise, &mut out);
push_str(state.resolve, &mut out);
push_str(state.reject, &mut out);
state.suspended.for_each_value(|v| {
if v.is_string() {
out.push(v.as_string_ptr_mut());
}
});
out
}
/// 异步挂起帧 cell_stack 的 cell 指针扁平列表(GC mark cell 边)。
/// 与 `async_native_string_edges` 经同一字段清单(`suspended.cell_stack`)
/// 产出,cell 指针不经对象图、须独立入存活集。
pub(crate) fn async_native_cell_edges(obj: &JsObject) -> Vec<*mut Cell> {
let Some(state) = async_state_mut(obj) else {
return Vec::new();
};
let mut out = Vec::new();
for cells in &state.suspended.cell_stack {
for &cell_ptr in cells {
if !cell_ptr.is_null() {
out.push(cell_ptr);
}
}
}
out
}
/// 只读核算异步状态盒字节(不释放),供 GC 账目核算。
pub(crate) fn async_native_size(obj: &JsObject) -> u64 {
if !obj.is_async_obj() {
return 0;
}
let ptr = obj.native_data() as *mut AsyncState;
if ptr.is_null() {
return 0;
}
unsafe {
std::mem::size_of::<AsyncState>() as u64
+ (*ptr).suspended.heap_bytes()
+ (*ptr).args.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
}
}
/// 释放异步状态盒(对象被 GC 回收时),返回释放字节数。
pub(crate) fn drop_async_native(obj: &JsObject) -> u64 {
let bytes = async_native_size(obj);
if bytes == 0 {
return 0;
}
let ptr = obj.native_data() as *mut AsyncState;
// SAFETY: ptr 非空(async_native_size 已验证),Box::from_raw 恰好释放一次。
let state = unsafe { Box::from_raw(ptr) };
drop(state);
bytes
}