mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
810 lines
38 KiB
Rust
810 lines
38 KiB
Rust
//! 异步函数运行时:异步帧快照挂起/恢复 + 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
|
||
}
|