feat: async/await 语法支持(AWAIT 帧快照挂起/恢复 + 微任务驱动 + AsyncFunction intrinsics)

This commit is contained in:
爱特每羊队
2026-08-09 22:02:15 +08:00
parent dcbe3d9320
commit 0d9e6eabc9
28 changed files with 1055 additions and 28 deletions
+4
View File
@@ -70,6 +70,8 @@ pub struct CompiledModule {
pub needs_home_object: bool,
/// 是否为生成器函数体(`function*`):调用返回迭代器对象,body 挂起/恢复执行。
pub is_generator: bool,
/// 是否为异步函数体(`async function` / async 箭头):调用返回 promise,body 挂起/恢复执行。
pub is_async: bool,
pub upvalue_captures: Vec<UpvalueCapture>,
pub cells_needed: u8,
/// 全局扁平模块 id:编译末端 flatten 阶段分配(顶层 0,子模块 DFS 递增)。
@@ -96,6 +98,7 @@ impl CompiledModule {
is_derived_constructor: false,
needs_home_object: false,
is_generator: false,
is_async: false,
upvalue_captures: Vec::new(),
cells_needed: 0,
flat_id: 0,
@@ -127,6 +130,7 @@ impl Clone for CompiledModule {
is_derived_constructor: self.is_derived_constructor,
needs_home_object: self.needs_home_object,
is_generator: self.is_generator,
is_async: self.is_async,
upvalue_captures: self.upvalue_captures.clone(),
cells_needed: self.cells_needed,
flat_id: self.flat_id,
+2
View File
@@ -203,6 +203,8 @@ define_opcodes! {
SUSPEND_BODY = 0x77 => "SUSPEND_BODY",
// `yield*` 委托:rd=内层可迭代对象;委托完成值经 reg 0 交付(与 YIELD 同协议)。
YIELD_STAR = 0x78 => "YIELD_STAR",
// `await`:rd=被等待的值(PromiseResolve 包装);挂起异步帧,恢复值经 reg 0 交付。
AWAIT = 0x79 => "AWAIT",
// ── 位运算 (0x80-0x8F) ──
BIT_AND = 0x80 => "BIT_AND",
+30 -12
View File
@@ -98,18 +98,36 @@ impl Emitter {
.map(|c| ("@@class_brand", *c))
.into_iter()
.collect();
let mut method_module = self.compile_function_body_with_field_hooks(
&param_names,
body_stmts,
ctx,
false,
self_binding,
FunctionBodyContext::ClassElement,
None::<fn(&Emitter, &mut CompileCtx) -> Result<(), String>>,
false,
&[],
&extra_uv,
)?;
let method_value = method.value.as_ref();
let mut method_module = if method_value.r#async {
self.compile_function_body_with_field_hooks_gen(
&param_names,
body_stmts,
ctx,
false,
self_binding,
FunctionBodyContext::ClassElement,
None::<fn(&Emitter, &mut CompileCtx) -> Result<(), String>>,
false,
&[],
&extra_uv,
false,
true,
)?
} else {
self.compile_function_body_with_field_hooks(
&param_names,
body_stmts,
ctx,
false,
self_binding,
FunctionBodyContext::ClassElement,
None::<fn(&Emitter, &mut CompileCtx) -> Result<(), String>>,
false,
&[],
&extra_uv,
)?
};
ctx.in_instance_method = saved_instance;
ctx.in_static_method = saved_static;
// 访问器函数名带 "get "/"set " 前缀(SetFunctionName 语义),普通方法裸属性名。
+6
View File
@@ -579,6 +579,11 @@ impl Emitter {
self.collect_capture_names_expr(a, ref_set, shadow, out);
}
}
// await 表达式:被等待的值里引用的父变量须纳入捕获(与 yield 同因——
// 异步体挂起恢复后寄存器已被覆盖,只能经 cell 读取)。
Expression::AwaitExpression(ae) => {
self.collect_capture_names_expr(&ae.argument, ref_set, shadow, out);
}
Expression::ChainExpression(c) => self.collect_capture_names_chain(&c.expression, ref_set, shadow, out),
_ => {}
}
@@ -891,6 +896,7 @@ impl Emitter {
self.collect_captured_expr(a, own, out);
}
}
Expression::AwaitExpression(ae) => self.collect_captured_expr(&ae.argument, own, out),
Expression::ChainExpression(c) => self.collect_captured_chain(&c.expression, own, out),
_ => {}
}
+31 -5
View File
@@ -163,6 +163,8 @@ pub struct CompileCtx {
pub(crate) in_static_method: bool,
/// 本函数是否为生成器函数体(`function*`),`assemble_ir` 回写到 IR。
pub(crate) is_generator: bool,
/// 本函数是否为异步函数体(`async function` / async 箭头),`assemble_ir` 回写到 IR。
pub(crate) is_async: bool,
pub(crate) static_block_this_reg: Option<u8>,
pub(crate) field_buffer: Option<FieldBuffer>,
/// 类构造器模块中 `@@field_keys` upvalue 下标(实例字段 computed key 数组)。
@@ -265,6 +267,7 @@ impl CompileCtx {
in_instance_method: false,
in_static_method: false,
is_generator: false,
is_async: false,
static_block_this_reg: None,
field_buffer: None,
field_keys_uv: None,
@@ -607,6 +610,7 @@ impl CompileCtx {
is_derived_constructor: false,
needs_home_object: false,
is_generator: self.is_generator,
is_async: self.is_async,
captured_this_const_idx: 0,
function_name: None,
function_length: self.function_length,
@@ -705,19 +709,36 @@ impl Emitter {
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
is_expression_body: bool, is_arrow: bool,
) -> Result<IRFunction, String> {
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, is_expression_body, is_arrow, false)
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, is_expression_body, is_arrow, false, false)
}
/// 编译函数体并显式指定生成器标志(`function*` 走此入口)。
pub(crate) fn compile_generator_body<'a>(
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
) -> Result<IRFunction, String> {
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true)
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, false)
}
/// 编译异步函数体(`async function` / async 箭头走此入口):`is_async` 使
/// `assemble_ir` 标记模块,VM 调用时按异步函数协议执行。
pub(crate) fn compile_async_body<'a>(
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
is_expression_body: bool, is_arrow: bool,
) -> Result<IRFunction, String> {
self.compile_function_body_with_flags(
param_specs,
body_stmts,
parent_ctx,
is_expression_body,
is_arrow,
false,
true,
)
}
fn compile_function_body_with_flags<'a>(
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
is_expression_body: bool, is_arrow: bool, is_generator: bool,
is_expression_body: bool, is_arrow: bool, is_generator: bool, is_async: bool,
) -> Result<IRFunction, String> {
let body_context = if is_arrow {
FunctionBodyContext::Arrow
@@ -732,6 +753,7 @@ impl Emitter {
&[],
body_context,
is_generator,
is_async,
)
}
@@ -739,7 +761,7 @@ impl Emitter {
pub(crate) fn compile_function_body_with_bindings_gen<'a>(
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext,
is_generator: bool,
is_generator: bool, is_async: bool,
) -> Result<IRFunction, String> {
self.compile_function_body_with_field_hooks_gen(
param_specs,
@@ -753,6 +775,7 @@ impl Emitter {
&[],
&[],
is_generator,
is_async,
)
}
@@ -785,6 +808,7 @@ impl Emitter {
extra_capture_exprs,
extra_upvalue_names,
false,
false,
)
}
@@ -793,13 +817,14 @@ impl Emitter {
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext,
mut emit_fields: Option<E>, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>],
extra_upvalue_names: &[(&str, u8)], is_generator: bool,
extra_upvalue_names: &[(&str, u8)], is_generator: bool, is_async: bool,
) -> Result<IRFunction, String>
where
E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>,
{
let mut ctx = CompileCtx::new();
ctx.is_generator = is_generator;
ctx.is_async = is_async;
// length = 第一个带默认值形参之前的形参数(解构默认与标识符默认同规则);
// rest 参数不在 param_specs 中(独立字段),天然不计入。
@@ -1158,6 +1183,7 @@ impl Emitter {
| Expression::NewExpression(_) => self.emit_function_domain(expr, ctx),
Expression::Identifier(ident) => self.emit_identifier_expression(ident, ctx),
Expression::YieldExpression(ye) => self.emit_yield_expression(ye, ctx),
Expression::AwaitExpression(ae) => self.emit_await_expression(ae, ctx),
Expression::CallExpression(_) => self.emit_call_domain(expr, ctx),
Expression::ThisExpression(_) => self.emit_this_expression(ctx),
Expression::SequenceExpression(seq) => self.emit_sequence_expression(seq, ctx),
+21
View File
@@ -0,0 +1,21 @@
//! `await` 表达式 emit:求值被等待的值后发 `AWAIT` 指令,结果经 reg 0 交付。
use crate::{CompileCtx, Emitter};
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::AwaitExpression;
impl Emitter {
pub(crate) fn emit_await_expression(
&self, ae: &AwaitExpression, ctx: &mut CompileCtx,
) -> Result<u32, String> {
// 求值被等待的值(`await undefined` 时求值 undefined)。
let value_reg = self.emit_expression(&ae.argument, ctx)?;
ctx.inst(Inst::await_expr(Operand::Reg(value_reg)));
// promise settle 后恢复值经 reg 0 交付(与 YIELD/CALL 同协议)。
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::None, Operand::None));
Ok(result_reg)
}
}
+7 -1
View File
@@ -41,7 +41,11 @@ impl Emitter {
let body_stmts = &arrow.body.statements;
let is_expr_body = arrow.expression;
let mut sub_module = self.compile_function_body(&param_names, body_stmts, ctx, is_expr_body, true)?;
let mut sub_module = if arrow.r#async {
self.compile_async_body(&param_names, body_stmts, ctx, is_expr_body, true)?
} else {
self.compile_function_body(&param_names, body_stmts, ctx, is_expr_body, true)?
};
sub_module.is_arrow = true;
ctx.nested.push(sub_module);
@@ -78,6 +82,8 @@ impl Emitter {
let mut sub_module = if fe.generator {
self.compile_generator_body(&param_names, body_stmts, ctx)?
} else if fe.r#async {
self.compile_async_body(&param_names, body_stmts, ctx, false, false)?
} else {
self.compile_function_body(&param_names, body_stmts, ctx, false, false)?
};
+1
View File
@@ -7,6 +7,7 @@ use crate::{CompileCtx, Emitter};
use oxide_parser::Expression;
pub mod assignment;
pub mod await_expr;
pub mod call;
pub mod function;
pub mod identifier;
+6
View File
@@ -216,6 +216,12 @@ impl Emitter {
self.pre_scan_builtin_chain(&chain.expression, ctx);
}
Expression::ParenthesizedExpression(p) => self.pre_scan_builtin_expr(&p.expression, ctx),
Expression::YieldExpression(ye) => {
if let Some(a) = &ye.argument {
self.pre_scan_builtin_expr(a, ctx);
}
}
Expression::AwaitExpression(ae) => self.pre_scan_builtin_expr(&ae.argument, ctx),
Expression::ArrowFunctionExpression(_)
| Expression::FunctionExpression(_)
| Expression::ClassExpression(_) => {}
@@ -35,6 +35,8 @@ impl Emitter {
let body_stmts: &[Statement] = if let Some(body) = &fd.body { &body.statements } else { &[] };
let mut sub_module = if fd.generator {
self.compile_generator_body(&param_names, body_stmts, ctx)?
} else if fd.r#async {
self.compile_async_body(&param_names, body_stmts, ctx, false, false)?
} else {
self.compile_function_body(&param_names, body_stmts, ctx, false, false)?
};
+7 -3
View File
@@ -20,7 +20,7 @@ impl Inst {
// CALL 系:结果隐式写 reg 0,rd 是 callee 的 use
OpCode::CALL | OpCode::CALL_NATIVE | OpCode::CALL_SPREAD => Some(0),
// YIELD/YIELD_STAR:恢复时 next(v) 的 v / 委托完成值经 reg 0 交付(与 CALL 同协议)
OpCode::YIELD | OpCode::YIELD_STAR => Some(0),
OpCode::YIELD | OpCode::YIELD_STAR | OpCode::AWAIT => Some(0),
// GET_PROP 系:结果写 a/b 槽而非 rd
OpCode::GET_PROP | OpCode::IC_GET_PROP => reg_of(&self.a),
OpCode::GET_PROP_DYNAMIC => reg_of(&self.b),
@@ -228,8 +228,12 @@ impl Inst {
}
// HALT:隐式读 reg 0(顶层返回值)
OpCode::HALT => uses.push(0),
// RETURN/THROW/YIELD/YIELD_STAR:读 rd(None→0)
OpCode::RETURN | OpCode::THROW | OpCode::YIELD | OpCode::YIELD_STAR => push_operand(&mut uses, &self.rd),
// RETURN/THROW/YIELD/YIELD_STAR/AWAIT:读 rd(None→0)
OpCode::RETURN
| OpCode::THROW
| OpCode::YIELD
| OpCode::YIELD_STAR
| OpCode::AWAIT => push_operand(&mut uses, &self.rd),
// 加载族:a 槽是 Const/Imm 立即数,无寄存器 use
OpCode::LOAD_CONST
| OpCode::CREATE_CLOSURE
+6
View File
@@ -284,6 +284,12 @@ impl Inst {
Self::new(OpCode::SUSPEND_BODY, Operand::None, Operand::None, Operand::None)
}
/// `await` 让出:`rd` 为被等待的值(运行时 PromiseResolve 包装);异步帧挂起,
/// promise settle 后恢复,值经 reg 0 交付(与 YIELD 同协议)。
pub fn await_expr(src: Operand) -> Self {
Self::new(OpCode::AWAIT, src, Operand::None, Operand::None)
}
// ── 跳转族:label 放 b 槽,offset 计算是 lowering 职责 ──
/// 无条件跳转。label 放 b 槽,offset 由 lowering 回填。
+3
View File
@@ -52,6 +52,8 @@ pub struct IRFunction {
pub needs_home_object: bool,
/// 是否为生成器函数体(`function*`)。
pub is_generator: bool,
/// 是否为异步函数体(`async function` / async 箭头)。
pub is_async: bool,
pub captured_this_const_idx: u16,
pub function_name: Option<String>,
/// 函数 `length` 属性值:第一个带默认值/解构默认的形参之前的形参数(rest 不计)。
@@ -83,6 +85,7 @@ impl IRFunction {
is_derived_constructor: false,
needs_home_object: false,
is_generator: false,
is_async: false,
captured_this_const_idx: 0,
function_name: None,
function_length: 0,
+1
View File
@@ -90,6 +90,7 @@ pub fn lower(f: &IRFunction) -> Result<CompiledModule, String> {
is_derived_constructor: f.is_derived_constructor,
needs_home_object: f.needs_home_object,
is_generator: f.is_generator,
is_async: f.is_async,
upvalue_captures: f.upvalue_captures.clone(),
cells_needed: f.cells_needed,
flat_id: 0,
-1
View File
@@ -401,7 +401,6 @@ fn is_skipped(meta: &TestMeta) -> Option<String> {
let excluded_features = [
"Proxy",
"BigInt",
"async-functions",
"Intl",
"Temporal",
"module",
+7
View File
@@ -402,6 +402,8 @@ impl JsObject {
pub const OBJ_TYPE_GENERATOR: u8 = 10;
/// Promise 对象:状态盒(Pending/Fulfilled/Rejected + reactions)存于 `native_data`。
pub const OBJ_TYPE_PROMISE: u8 = 11;
/// 异步函数执行上下文(隐藏对象):`AsyncState` 快照存于 `native_data`。
pub const OBJ_TYPE_ASYNC: u8 = 12;
/// `is_session_epoch` 字段中的 session 标记位。
pub const SESSION_EPOCH_BIT: u8 = 0x01;
/// `is_session_epoch` 字段中的 GC 标记位。
@@ -457,6 +459,11 @@ impl JsObject {
pub fn is_promise_obj(&self) -> bool {
self.type_tag == Self::OBJ_TYPE_PROMISE
}
/// 是否异步函数执行上下文对象。
#[inline]
pub fn is_async_obj(&self) -> bool {
self.type_tag == Self::OBJ_TYPE_ASYNC
}
/// 构造无属性、可扩展的空对象(`new Object()` 的基础对象)。
pub fn new_empty(shape_id: ShapeId, proto: JsValue) -> Self {
+706
View File
@@ -0,0 +1,706 @@
//! 异步函数运行时:异步帧快照挂起/恢复 + 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 std::sync::Arc;
use oxide_bytecode::opcode;
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_runtime_api::{to_boolean, NativeResult};
use oxide_types::mem::P;
use oxide_types::object::{Cell, JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use crate::vm::{CallFrame, Completion, ForInIter, FrameContinuation, TryHandler, 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,
// ── 挂起时的执行上下文 ──
pub regs: Box<[JsValue; 256]>,
pub pc: usize,
pub bytecode: Vec<opcode::Instr>,
/// 异步模块 flat_id(恢复时重激活 immutables)。
pub sub_idx: u32,
pub active_reg_limit: u8,
pub root_reg_limit: u8,
/// 异步帧(压入时由 push_bytecode_frame 构造,挂起时弹出存此)。
pub frame: Option<CallFrame>,
pub spill_stack: Vec<JsValue>,
pub save_stack: Vec<JsValue>,
pub cell_stack: Vec<Vec<*mut Cell>>,
pub try_stack: Vec<TryHandler>,
pub for_in_iters: Vec<*mut ForInIter<'static>>,
pub for_of_iters: Vec<JsValue>,
pub last_for_of_result: JsValue,
pub saved_bytecode_stack: Vec<Vec<opcode::Instr>>,
pub saved_immutables_stack: Vec<*const [JsValue]>,
/// 在途异常/完成(异常展开穿越 await 挂起时保留,恢复后继续展开)。
pub exception_value: Option<JsValue>,
pub pending_exception: Option<JsValue>,
pub pending_error_kind: Option<&'static str>,
pub pending_completion: Option<Completion>,
}
/// 一次 await 恢复的注入模式。
#[derive(Debug, Clone, Copy)]
pub(crate) enum AsyncResumeMode {
/// 普通恢复:fulfilled 值作为 `await` 表达式结果(写 reg 0)。
Next(JsValue),
/// 拒绝恢复:在挂起点抛错(可被 catch/finally 捕获)。
Throw(JsValue),
}
/// 异步上下文对象上存 capability 闭包的属性名(await 恢复闭包定位上下文用)。
const ASYNC_CTX_PROP: &str = "__oxide_async_ctx__";
/// 恢复闭包上区分 reject 角色的属性名。
const ASYNC_REJECT_PROP: &str = "__oxide_async_reject__";
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.session.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,
regs: Box::new([JsValue::undefined(); 256]),
pc: 0,
bytecode: Vec::new(),
sub_idx: 0,
active_reg_limit: 0,
root_reg_limit: 0,
frame: None,
spill_stack: Vec::new(),
save_stack: Vec::new(),
cell_stack: Vec::new(),
try_stack: Vec::new(),
for_in_iters: Vec::new(),
for_of_iters: Vec::new(),
last_for_of_result: JsValue::undefined(),
saved_bytecode_stack: Vec::new(),
saved_immutables_stack: Vec::new(),
exception_value: None,
pending_exception: None,
pending_error_kind: None,
pending_completion: None,
});
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();
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
self.async_dispatch = true;
self.async_context = Some(ctx_val);
self.native_call_depth += 1;
self.regs = [JsValue::undefined(); 256];
self.pc = 0;
self.bytecode = Vec::new();
self.active_reg_limit = 1;
self.root_reg_limit = 1;
self.try_stack.clear();
self.iters.for_in_iters.clear();
self.iters.for_of_iters.clear();
self.iters.last_for_of_result = JsValue::undefined();
self.spill_stack.clear();
self.save_stack.clear();
self.saved_bytecode_stack.clear();
self.saved_immutables_stack.clear();
self.cell_stack.clear();
self.inline_callee = None;
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.push_bytecode_frame(
callee,
this_value,
&args,
None,
None,
JsValue::undefined(),
FrameContinuation::None,
);
unsafe { (*state_ptr).args = args };
if let Err(e) = push_res {
self.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err(e);
}
unsafe { (*state_ptr).phase = AsyncPhase::Running };
let result = self.dispatch();
self.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
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_error(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();
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
self.async_dispatch = true;
self.async_context = Some(ctx_val);
self.native_call_depth += 1;
{
let state = unsafe { &mut *state_ptr };
self.regs = *state.regs;
self.pc = state.pc;
self.bytecode = std::mem::take(&mut state.bytecode);
let subs = Arc::clone(&self.sub_modules);
if (state.sub_idx as usize) < subs.len() {
self.activate_immutables(state.sub_idx as usize, &subs[state.sub_idx as usize].constants);
} else {
// 挂起状态跨 run:sub_modules 已重建,无法恢复(与生成器同限制)。
self.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async function suspended across runs is no longer valid".into());
}
self.active_reg_limit = state.active_reg_limit;
self.root_reg_limit = state.root_reg_limit;
self.frames.clear();
if let Some(frame) = state.frame.take() {
self.frames.push(frame);
}
self.spill_stack = std::mem::take(&mut state.spill_stack);
self.save_stack = std::mem::take(&mut state.save_stack);
self.cell_stack = std::mem::take(&mut state.cell_stack);
self.try_stack = std::mem::take(&mut state.try_stack);
self.iters.for_in_iters = std::mem::take(&mut state.for_in_iters);
self.iters.for_of_iters = std::mem::take(&mut state.for_of_iters);
self.iters.last_for_of_result = state.last_for_of_result;
self.saved_bytecode_stack = std::mem::take(&mut state.saved_bytecode_stack);
self.saved_immutables_stack = std::mem::take(&mut state.saved_immutables_stack);
self.exception_value = state.exception_value.take();
self.pending_exception = state.pending_exception.take();
self.pending_error_kind = state.pending_error_kind.take();
self.pending_completion = state.pending_completion.take();
self.inline_callee = None;
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.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
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.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
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_error(self, &e));
self.finish_async(state_ptr, Err(exc))?;
self.restore_inline_state(saved);
Ok(())
}
}
}
/// 结算异步函数:正常结束 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 时直接复用,否则建新 promise 并 PromiseResolve。
/// - 经 `perform_promise_then` 登记 fulfill/reject 恢复反应(微任务入队)。
pub(crate) fn dispatch_await(&mut self, rd: usize) -> Result<(), String> {
let ctx = match self.async_context {
Some(c) => c,
None => return Err("AWAIT executed outside async function".into()),
};
let value = self.regs[rd];
let promise = if self.is_promise_value(value) {
value
} else {
let (p, _, _) = self.new_promise_capability();
let _ = self.resolve_promise(p, value);
p
};
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.session.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)
}
/// 把当前 VM 执行状态(异步 body 刚在嵌套 dispatch 中让出)快照进状态盒。
///
/// 异步帧弹出存 `frame`,其余栈段整段搬入(嵌套循环期间这些栈只含异步数据)。
fn snapshot_async(&mut self, state: &mut AsyncState) -> Result<(), String> {
let frame = self
.frames
.pop()
.ok_or_else(|| "async frame missing on await".to_string())?;
state.frame = Some(frame);
state.regs = Box::new(self.regs);
state.pc = self.pc;
state.bytecode = std::mem::take(&mut self.bytecode);
state.sub_idx = if state.callee.is_object() {
unsafe { (*state.callee.as_js_object_ptr()).sub_module_index() }
} else {
0
};
state.active_reg_limit = self.active_reg_limit;
state.root_reg_limit = self.root_reg_limit;
state.spill_stack = std::mem::take(&mut self.spill_stack);
state.save_stack = std::mem::take(&mut self.save_stack);
state.cell_stack = std::mem::take(&mut self.cell_stack);
state.try_stack = std::mem::take(&mut self.try_stack);
state.for_in_iters = std::mem::take(&mut self.iters.for_in_iters);
state.for_of_iters = std::mem::take(&mut self.iters.for_of_iters);
state.last_for_of_result = self.iters.last_for_of_result;
state.saved_bytecode_stack = std::mem::take(&mut self.saved_bytecode_stack);
state.saved_immutables_stack = std::mem::take(&mut self.saved_immutables_stack);
state.exception_value = self.exception_value.take();
state.pending_exception = self.pending_exception.take();
state.pending_error_kind = self.pending_error_kind.take();
state.pending_completion = self.pending_completion.take();
state.phase = AsyncPhase::Suspended;
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)
.map_or(false, 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_error(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.session.builtin_world().fn_proto_val();
// %AsyncFunction% 构造器:proto = Function.prototype,调用抛错(动态创建未实现)。
let mut af_ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
af_ctor.set_function(true);
af_ctor.set_native_arg_count(1);
// SAFETY: async_function_stub 是 NativeFn 函数项。
af_ctor.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(async_function_stub as *const ()) }));
// %AsyncFunction.prototype%:proto = Function.prototype,constructor = %AsyncFunction%。
let mut af_proto = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto_val));
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 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 ppos = af_ctor.push_prop(JsValue::from_js_object(af_proto.as_mut() as *mut JsObject));
af_ctor.set_data_meta(ppos, PropAttributes::new(false, false, false));
// af_proto.constructor = %AsyncFunction%(构造器对象泄漏持有,与 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(Box::into_raw(af_ctor)));
af_proto.set_data_meta(cpos, PropAttributes::new(false, false, true));
// af_proto[Symbol.toStringTag] = "AsyncFunction"(数据属性,w/e/c = false/false/true)。
let tag_si = sf.intern("@@toStringTag").0;
let tag_shape = sh.make_shape(af_proto.shape_id(), tag_si);
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));
vm.async_function_proto = P::new(*af_proto);
}
/// `%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",
))
}
// ── session GC 支撑:状态快照中的 JsValues 作为异步上下文对象边追踪 ──
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 只在 reset(无执行状态)时运行。
Some(unsafe { &mut *ptr })
}
}
/// 异步状态内所有对象引用的扁平列表(GC mark 边)。
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();
let push = |v: JsValue, edges: &mut Vec<JsValue>| {
if v.is_object() {
edges.push(v);
}
};
push(state.callee, &mut edges);
edges.extend(state.args.iter().copied().filter(|v| v.is_object()));
push(state.result, &mut edges);
push(state.promise, &mut edges);
push(state.resolve, &mut edges);
push(state.reject, &mut edges);
edges.extend(state.regs.iter().copied().filter(|v| v.is_object()));
if let Some(frame) = &state.frame {
push(frame.saved_this, &mut edges);
push(frame.saved_new_target, &mut edges);
push(frame.callee, &mut edges);
if let Some(ct) = frame.constructed_this {
push(ct, &mut edges);
}
}
edges.extend(state.spill_stack.iter().copied().filter(|v| v.is_object()));
edges.extend(state.save_stack.iter().copied().filter(|v| v.is_object()));
for cells in &state.cell_stack {
for &cell_ptr in cells {
if cell_ptr.is_null() {
continue;
}
// SAFETY: cell 由 session_epoch 分配,本 session 内指针有效。
let cell = unsafe { &*cell_ptr };
push(cell.value, &mut edges);
}
}
edges.extend(state.for_of_iters.iter().copied().filter(|v| v.is_object()));
push(state.last_for_of_result, &mut edges);
edges
}
/// 用转发函数重写状态快照中的所有 JsValue(session GC 移动式清扫 / promote 用)。
pub(crate) fn rewrite_async_native(obj: &JsObject, mut rewrite: impl FnMut(JsValue) -> JsValue) {
let Some(state) = async_state_mut(obj) else {
return;
};
state.callee = rewrite(state.callee);
for v in &mut state.args {
*v = rewrite(*v);
}
state.result = rewrite(state.result);
state.promise = rewrite(state.promise);
state.resolve = rewrite(state.resolve);
state.reject = rewrite(state.reject);
for v in state.regs.iter_mut() {
*v = rewrite(*v);
}
if let Some(frame) = &mut state.frame {
frame.saved_this = rewrite(frame.saved_this);
frame.saved_new_target = rewrite(frame.saved_new_target);
frame.callee = rewrite(frame.callee);
frame.constructed_this = frame.constructed_this.map(&mut rewrite);
}
for v in &mut state.spill_stack {
*v = rewrite(*v);
}
for v in &mut state.save_stack {
*v = rewrite(*v);
}
for cells in &mut state.cell_stack {
for &mut cell_ptr in cells.iter_mut() {
if cell_ptr.is_null() {
continue;
}
// SAFETY: cell 由 session_epoch 分配,本 session 内指针有效。
let cell = unsafe { &mut *cell_ptr };
cell.value = rewrite(cell.value);
}
}
for v in &mut state.for_of_iters {
*v = rewrite(*v);
}
state.last_for_of_result = rewrite(state.last_for_of_result);
}
/// 深拷贝状态盒到新对象(promote / sweep 用):新对象持独立 Box,源盒可安全释放。
pub(crate) fn clone_async_native_with_rewrite(
old: &JsObject, new: &mut JsObject, mut rewrite: impl FnMut(JsValue) -> JsValue,
) {
let Some(state) = async_state_mut(old) else {
return;
};
let cloned = AsyncState {
phase: state.phase,
callee: rewrite(state.callee),
args: state.args.iter().copied().map(&mut rewrite).collect(),
this_value: state.this_value,
result: rewrite(state.result),
promise: rewrite(state.promise),
resolve: rewrite(state.resolve),
reject: rewrite(state.reject),
regs: Box::new({
let mut regs = [JsValue::undefined(); 256];
for (i, v) in state.regs.iter().enumerate() {
regs[i] = rewrite(*v);
}
regs
}),
pc: state.pc,
bytecode: state.bytecode.clone(),
sub_idx: state.sub_idx,
active_reg_limit: state.active_reg_limit,
root_reg_limit: state.root_reg_limit,
frame: state.frame.as_ref().map(|f| CallFrame {
return_addr: f.return_addr,
function_name: f.function_name,
caller_reg_limit: f.caller_reg_limit,
saved_reg_offset: f.saved_reg_offset,
spill_offset: f.spill_offset,
arguments_base: f.arguments_base,
arguments_count: f.arguments_count,
saved_this: rewrite(f.saved_this),
saved_new_target: rewrite(f.saved_new_target),
callee: rewrite(f.callee),
construct_result_reg: f.construct_result_reg,
constructed_this: f.constructed_this.map(&mut rewrite),
is_derived_constructor: f.is_derived_constructor,
continuation: f.continuation,
}),
spill_stack: state.spill_stack.iter().copied().map(&mut rewrite).collect(),
save_stack: state.save_stack.iter().copied().map(&mut rewrite).collect(),
cell_stack: state.cell_stack.clone(),
try_stack: state.try_stack.clone(),
for_in_iters: state.for_in_iters.clone(),
for_of_iters: state.for_of_iters.iter().copied().map(&mut rewrite).collect(),
last_for_of_result: rewrite(state.last_for_of_result),
saved_bytecode_stack: state.saved_bytecode_stack.clone(),
saved_immutables_stack: state.saved_immutables_stack.clone(),
exception_value: state.exception_value.map(&mut rewrite),
pending_exception: state.pending_exception.map(&mut rewrite),
pending_error_kind: state.pending_error_kind,
pending_completion: state.pending_completion,
};
new.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
}
/// 释放异步状态盒(对象被 GC 回收时),返回释放字节数。
pub(crate) fn drop_async_native(obj: &JsObject) -> u64 {
if !obj.is_async_obj() {
return 0;
}
let ptr = obj.native_data() as *mut AsyncState;
if ptr.is_null() {
return 0;
}
// SAFETY: 指针来自 create_async_context 的 Box::into_raw,只在 GC 回收时释放一次。
let state = unsafe { Box::from_raw(ptr) };
std::mem::size_of::<AsyncState>() as u64
+ state.bytecode.len() as u64 * std::mem::size_of::<u32>() as u64
+ state.spill_stack.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
+ state.save_stack.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
+ state.args.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
}
+12
View File
@@ -748,6 +748,12 @@ impl Vm {
self.regs[0] = gen;
return Ok(false);
}
// 异步函数调用返回 capability promise,立即同步执行 body 到首个 await。
if sub_idx < self.sub_modules.len() && self.sub_modules[sub_idx].is_async {
let promise = self.create_async_object(callee, this_value, &args)?;
self.regs[0] = promise;
return Ok(false);
}
self.push_bytecode_frame(
callee,
this_value,
@@ -840,6 +846,12 @@ impl Vm {
{
return self.raise_type_error("g is not a constructor").map(|_| true);
}
// 异步函数不是构造器:`new f()` 抛 TypeError。
if (ctor_obj.sub_module_index() as usize) < self.sub_modules.len()
&& self.sub_modules[ctor_obj.sub_module_index() as usize].is_async
{
return self.raise_type_error("g is not a constructor").map(|_| true);
}
if self.frames.len() >= self.kernel_core.config.max_call_depth {
return Err(self.error_message_text("RangeError", "Maximum call stack size exceeded"));
}
+1
View File
@@ -9,6 +9,7 @@
/// 内置对象绑定模块:向 session 的 global 对象安装 Object/Array/... 及各原型。
pub mod bindings;
mod async_func;
mod dispatch;
mod generator;
mod ic_helper;
+4 -4
View File
@@ -97,7 +97,7 @@ impl Vm {
/// 新建 Promise 能力 `(promise, resolve, reject)`:resolve/reject 为携带
/// 目标 promise 的 native 闭包,同时写入状态盒供 thenable 委托取用。
fn new_promise_capability(&mut self) -> (JsValue, JsValue, JsValue) {
pub(crate) fn new_promise_capability(&mut self) -> (JsValue, JsValue, JsValue) {
let promise = self.create_promise_object();
let resolve = self.make_resolve_reject_fn(promise, false);
let reject = self.make_resolve_reject_fn(promise, true);
@@ -222,7 +222,7 @@ impl Vm {
}
/// 是否原生 Promise 对象。
fn is_promise_value(&self, v: JsValue) -> bool {
pub(crate) fn is_promise_value(&self, v: JsValue) -> bool {
v.is_object() && {
let ptr = v.as_js_object_ptr();
!ptr.is_null() && unsafe { &*ptr }.is_promise_obj()
@@ -349,7 +349,7 @@ impl Vm {
}
/// `PerformPromiseThen` 核心:注册 fulfill/reject 两条反应;已 settle 则直接入队。
fn perform_promise_then(
pub(crate) fn perform_promise_then(
&mut self, this_val: JsValue, on_fulfilled: JsValue, on_rejected: JsValue,
) -> Result<JsValue, JsValue> {
if !self.is_promise_value(this_val) {
@@ -746,7 +746,7 @@ impl Vm {
/// 给 native 函数对象补 `length`/`name` 数据属性(length 先于 name,符合
/// CreateBuiltinFunction 属性顺序)。
fn add_fn_name_length(&mut self, obj: &mut JsObject, name: &str, length: u8) {
pub(crate) fn add_fn_name_length(&mut self, obj: &mut JsObject, name: &str, length: u8) {
let attrs = PropAttributes::new(false, false, true);
let sh = self.kernel_core.shape_forge().as_ref();
let sf = self.kernel_core.perm_interner().as_ref();
+5
View File
@@ -75,6 +75,11 @@ impl Vm {
crate::promise::clone_promise_native_with_rewrite(src_ref, dst_ref, |value| {
self.promote_value_if_epoch_object(value, forwarding)
});
} else if src_ref.is_async_obj() {
// 异步状态盒深拷贝到新对象:源盒随 epoch 释放,互不共享。
crate::async_func::clone_async_native_with_rewrite(src_ref, dst_ref, |value| {
self.promote_value_if_epoch_object(value, forwarding)
});
}
dst
}
+15
View File
@@ -95,6 +95,9 @@ impl SessionGc {
if obj.is_promise_obj() {
edges.extend(crate::promise::promise_native_edges(obj));
}
if obj.is_async_obj() {
edges.extend(crate::async_func::async_native_edges(obj));
}
// 遍历 upvalue cell 中的对象引用。
for cell_ptr in obj.upvalues_slice() {
if cell_ptr.is_null() {
@@ -164,6 +167,13 @@ impl SessionGc {
}
}
}
if obj.is_async_obj() {
for value in crate::async_func::async_native_edges(obj) {
if value.is_string() {
live.insert(value.as_string_ptr_mut());
}
}
}
}
pub(crate) fn mark(&mut self, vm: &Vm) {
@@ -275,6 +285,7 @@ impl SessionGc {
freed_bytes += data_view::drop_data_view_native(obj);
freed_bytes += crate::generator::drop_generator_native(obj);
freed_bytes += crate::promise::drop_promise_native(obj);
freed_bytes += crate::async_func::drop_async_native(obj);
freed_bytes
}
@@ -333,6 +344,8 @@ impl SessionGc {
data_view::clone_data_view_native_with_rewrite(old_ref, new_ref, |value| value);
} else if old_ref.is_promise_obj() {
crate::promise::clone_promise_native_with_rewrite(old_ref, new_ref, |value| value);
} else if old_ref.is_async_obj() {
crate::async_func::clone_async_native_with_rewrite(old_ref, new_ref, |value| value);
}
forwarding.insert(old_ptr, new_ptr);
freed_bytes += Self::drop_session_object_heap_data(old_ptr);
@@ -366,6 +379,8 @@ impl SessionGc {
crate::generator::rewrite_generator_native(obj, |value| rewrite_forwarded_value(value, &forwarding));
} else if obj.is_promise_obj() {
crate::promise::rewrite_promise_native(obj, |value| rewrite_forwarded_value(value, &forwarding));
} else if obj.is_async_obj() {
crate::async_func::rewrite_async_native(obj, |value| rewrite_forwarded_value(value, &forwarding));
}
}
+19
View File
@@ -138,6 +138,7 @@ pub struct ForInIter<'bump> {
}
/// try/catch/finally 处理记录,异常展开时用于定位跳转目标与清理范围。
#[derive(Debug, Clone, Copy)]
pub struct TryHandler {
pub catch_pc: Option<usize>,
pub finally_pc: Option<usize>,
@@ -249,6 +250,8 @@ pub struct Vm {
pub promise_constructor: P<JsObject>,
/// `%Promise.prototype%`:Promise 实例的原型(then/catch/finally 方法挂此)。
pub promise_proto: P<JsObject>,
/// `%AsyncFunction.prototype%`:异步函数对象的原型(`constructor` 指向 `%AsyncFunction%`)。
pub async_function_proto: P<JsObject>,
/// 微任务队列(Promise reactions / thenable 委托),`run()` 末尾 FIFO drain。
pub(crate) job_queue: VecDeque<crate::promise::Microtask>,
pub math_rng_state: u64,
@@ -302,6 +305,15 @@ pub struct Vm {
pub(crate) generator_init_step: bool,
/// 参数初始化步中已越过 body 起点标记的信号(`initialize_generator` 消费后复位)。
pub(crate) generator_body_started: bool,
/// 当前正在执行的异步函数上下文对象(`OBJ_TYPE_ASYNC`,持有 AsyncState 快照)。
/// AWAIT dispatch 据此登记恢复反应;跨嵌套 async 调用保存/恢复。
pub(crate) async_context: Option<JsValue>,
/// 异步体 `dispatch()` 让出时的信号:AWAIT 置 true,恢复方(async 内嵌 dispatch
/// 循环)取走并快照挂起状态。false = 正常返回/异常。
pub(crate) async_suspended: bool,
/// 当前是否处于异步函数内嵌 dispatch 循环:异步帧弹出且 frames 清空时,
/// `do_return` 据此把结果交付给恢复方(与 generator_dispatch 同语义)。
pub(crate) async_dispatch: bool,
/// 分组保存 session arena / GC 簿记状态。
pub(crate) gc_state: GcState,
/// 分组保存 `Symbol` intern 状态。
@@ -1551,6 +1563,13 @@ impl Vm {
}
}
OpCode::AWAIT => {
// 异步帧挂起:登记恢复反应后内嵌 dispatch 返回,恢复方快照挂起状态。
self.dispatch_await(rd)?;
self.profiling.set_instruction_count(steps);
return Ok(JsValue::undefined());
}
_ => {
return Err(format!("opcode {op} not yet implemented"));
}
+8 -2
View File
@@ -41,6 +41,12 @@ impl Vm {
self.regs[0] = gen;
return Ok(false);
}
// 异步函数调用返回 capability promise,立即同步执行 body 到首个 await。
if sub_idx < self.sub_modules.len() && self.sub_modules[sub_idx].is_async {
let promise = self.create_async_object(callee, self.regs[this_reg as usize], &args)?;
self.regs[0] = promise;
return Ok(false);
}
self.push_bytecode_frame(
callee,
self.regs[this_reg as usize],
@@ -327,8 +333,8 @@ impl Vm {
}
}
}
// 生成器内嵌 dispatch:帧全部弹出后把结果交付恢复方,而非继续执行。
if self.frames.is_empty() && self.generator_dispatch {
// 生成器/异步内嵌 dispatch:帧全部弹出后把结果交付恢复方,而非继续执行。
if self.frames.is_empty() && (self.generator_dispatch || self.async_dispatch) {
return Ok(Some(result));
}
Ok(None)
+4
View File
@@ -99,6 +99,10 @@ impl Vm {
if self.sub_modules[sub_idx].is_generator {
return self.raise_type_error("g is not a constructor").map(|_| true);
}
// 异步函数不是构造器:`new f()` 抛 TypeError。
if self.sub_modules[sub_idx].is_async {
return self.raise_type_error("g is not a constructor").map(|_| true);
}
if self.frames.len() >= self.kernel_core.config.max_call_depth {
return Err(self.error_message_text("RangeError", "Maximum call stack size exceeded"));
+4
View File
@@ -116,6 +116,10 @@ impl Vm {
if self.sub_modules[sub_idx].is_generator {
return self.create_generator_object(callee, receiver, args);
}
// 异步函数调用返回 capability promise,立即同步执行 body 到首个 await。
if self.sub_modules[sub_idx].is_async {
return self.create_async_object(callee, receiver, args);
}
self.native_call_depth += 1;
let subs = Arc::clone(&self.sub_modules);
+25
View File
@@ -37,6 +37,7 @@ impl Vm {
generator_function_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
promise_constructor: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
promise_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
async_function_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
job_queue: VecDeque::new(),
math_rng_state: 0,
sub_modules: Arc::new(Vec::new()),
@@ -62,6 +63,9 @@ impl Vm {
generator_dispatch: false,
generator_init_step: false,
generator_body_started: false,
async_context: None,
async_suspended: false,
async_dispatch: false,
gc_state: GcState {
session_epoch: bumpalo::Bump::new(),
session_gc: crate::session_gc::SessionGc::new(),
@@ -91,6 +95,7 @@ impl Vm {
};
vm.init_generator_intrinsics();
vm.init_promise_intrinsics();
vm.init_async_intrinsics();
// Promise 全局绑定发生在快照采集之后,重录快照避免首次 full_reset 误判脏。
vm.session.record_snapshot();
vm_info!("Vm created");
@@ -117,6 +122,7 @@ impl Vm {
generator_function_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
promise_constructor: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
promise_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
async_function_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
job_queue: VecDeque::new(),
math_rng_state: 0,
sub_modules: Arc::new(Vec::new()),
@@ -142,6 +148,9 @@ impl Vm {
generator_dispatch: false,
generator_init_step: false,
generator_body_started: false,
async_context: None,
async_suspended: false,
async_dispatch: false,
gc_state: GcState {
session_epoch: bumpalo::Bump::new(),
session_gc: crate::session_gc::SessionGc::new(),
@@ -171,6 +180,7 @@ impl Vm {
};
vm.init_generator_intrinsics();
vm.init_promise_intrinsics();
vm.init_async_intrinsics();
// Promise 全局绑定发生在快照采集之后,重录快照避免首次 full_reset 误判脏。
vm.session.record_snapshot();
vm_info!("Vm created (pool)");
@@ -185,6 +195,13 @@ impl Vm {
crate::generator::init_generator_intrinsics(self);
}
/// 初始化/重建异步函数内建对象(`%AsyncFunction.prototype%`)。
///
/// 在 VM 创建与 `full_reset`(session 重建)后调用。
pub(crate) fn init_async_intrinsics(&mut self) {
crate::async_func::init_async_intrinsics(self);
}
/// 全量隔离重置:仅重建被污染的内置对象与 global,并清空所有执行状态与内存。
///
/// 用于在多次 JS 执行之间达到完全隔离:session 内未被污染的 builtin 保留原指针。
@@ -201,6 +218,7 @@ impl Vm {
self.object_prototype = P::clone(&self.session.builtin_world().object_proto);
self.init_generator_intrinsics();
self.init_promise_intrinsics();
self.init_async_intrinsics();
// 快照须在 Promise 全局绑定之后采集:绑定会修改 global 世代。
self.session.record_snapshot();
self.clear_full_reset_state();
@@ -215,6 +233,7 @@ impl Vm {
self.object_prototype = P::clone(&self.session.builtin_world().object_proto);
self.init_generator_intrinsics();
self.init_promise_intrinsics();
self.init_async_intrinsics();
self.session.record_snapshot();
self.clear_full_reset_state();
}
@@ -274,6 +293,9 @@ impl Vm {
self.generator_dispatch = false;
self.generator_init_step = false;
self.generator_body_started = false;
self.async_context = None;
self.async_suspended = false;
self.async_dispatch = false;
self.native_call_depth = 0;
// 微任务队列是执行期状态:跨 run 不保留。
self.job_queue.clear();
@@ -343,8 +365,11 @@ impl Vm {
// 生成器函数对象:原型为 %GeneratorFunction.prototype%(constructor 链解析到
// "GeneratorFunction"),且不像普通函数那样拥有 `prototype` 属性。
let is_generator = self.sub_modules.get(sub_idx as usize).map(|m| m.is_generator).unwrap_or(false);
let is_async = self.sub_modules.get(sub_idx as usize).map(|m| m.is_async).unwrap_or(false);
let proto_val = if is_generator {
JsValue::from_js_object(self.generator_function_proto.as_ptr() as *mut JsObject)
} else if is_async {
JsValue::from_js_object(self.async_function_proto.as_ptr() as *mut JsObject)
} else {
JsValue::from_js_object(self.session.builtin_world().function_proto.as_ptr() as *mut JsObject)
};
+118
View File
@@ -0,0 +1,118 @@
//! async/await 运行时测试:异步函数调用返回 promise、await 恢复、reject 进 catch、
//! 多 await 顺序、嵌套 async、微任务执行序。
use oxide_compiler::compiler::Compiler;
use oxide_parser::Allocator;
use oxide_vm::promise::promise_settled_value;
use oxide_vm::vm::Vm;
/// 执行源码并格式化顶层结果;Promise 结果取其 drain 后的 settled 值。
fn eval(source: &str) -> String {
let allocator = Allocator::default();
let program = match oxide_parser::parse(&allocator, source) {
Ok(p) => p,
Err(e) => return format!("parse error: {}", e[0].message),
};
let module = match Compiler::new().compile(&program) {
Ok(m) => m,
Err(e) => return format!("compile error: {e}"),
};
let mut vm = Vm::new();
match vm.run(&module) {
Ok(result) => format_value(&vm, result),
Err(e) => format!("vm error: {e}"),
}
}
fn format_value(vm: &Vm, val: oxide_vm::JsValue) -> String {
if val.is_string() {
format!("\"{}\"", vm.lookup_str(val).unwrap_or_default())
} else if val.is_object() {
let obj = unsafe { &*val.as_js_object_ptr() };
if obj.is_promise_obj() {
match promise_settled_value(obj) {
Some((true, v)) => format_value(vm, v),
Some((false, v)) => format!("<rejected {}>", format_value(vm, v)),
None => "<pending>".to_string(),
}
} else if obj.is_array() {
format!("[array]")
} else {
"[object]".to_string()
}
} else {
format!("{val}")
}
}
#[test]
fn async_returns_immediate_value() {
assert_eq!(eval("async function f(){ return 42 } f()"), "42");
}
#[test]
fn async_await_primitive() {
assert_eq!(eval("async function f(){ var v = await 10; return v*2 } f()"), "20");
}
#[test]
fn async_await_resolved_promise() {
assert_eq!(eval("async function f(){ var v = await Promise.resolve(5); return v+1 } f()"), "6");
}
#[test]
fn async_await_reject_into_catch() {
assert_eq!(
eval("async function f(){ try { await Promise.reject('e') } catch(e) { return 'caught:'+e } } f()"),
"\"caught:e\""
);
}
#[test]
fn async_multiple_awaits_in_order() {
assert_eq!(eval("async function f(){ var x = await 1; x += await 2; return x } f()"), "3");
}
#[test]
fn async_await_return_promise() {
assert_eq!(eval("async function f(){ return await Promise.resolve(7) } f()"), "7");
}
#[test]
fn async_nested_calls() {
assert_eq!(eval("async function g(){ return 2 } async function f(){ return await g() + 3 } f()"), "5");
}
#[test]
fn async_arrow_in_then() {
assert_eq!(eval("Promise.resolve().then(async ()=>{ return 9 }).then(v=>v)"), "9");
}
#[test]
fn async_execution_order_suspends_immediately() {
// await 挂起 body;当前同步代码先跑完,body 恢复在微任务 drain 阶段。
assert_eq!(
eval("var order=[]; async function f(){ order.push(1); await 0; order.push(2) } f(); order.push(0); Promise.resolve().then(function(){ return order.join(',') })"),
"\"1,0,2\""
);
}
#[test]
fn async_throw_rejects_promise() {
assert_eq!(eval("async function f(){ throw 'boom' } f()"), "<rejected \"boom\">");
}
#[test]
fn async_is_not_constructor() {
assert!(eval("new (async function(){})").starts_with("vm error") || eval("new (async function(){})").contains("not a constructor"));
}
#[test]
fn async_constructor_name() {
assert_eq!(eval("async function f(){}; f.constructor.name"), "\"AsyncFunction\"");
}
#[test]
fn async_class_method() {
assert_eq!(eval("class A { async m(){ return await 7 } } new A().m()"), "7");
}