mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 11:11:11 +08:00
feat: for-await-of 逃出关闭异步 await return() 结算后恢复帧
This commit is contained in:
@@ -385,10 +385,21 @@ impl Vm {
|
||||
|
||||
OpCode::BREAK => {
|
||||
self.dispatch_break(instr)?;
|
||||
// 逃出 for-await-of 的异步关闭可能经 await 挂起(return() 的
|
||||
// promise),挂起时须像 AWAIT 一样让内嵌 dispatch 返回,由恢复方
|
||||
// 快照状态。
|
||||
if self.async_suspended || self.async_gen_suspended {
|
||||
self.profiling.set_instruction_count(steps);
|
||||
return Ok(JsValue::undefined());
|
||||
}
|
||||
}
|
||||
|
||||
OpCode::CONTINUE => {
|
||||
self.dispatch_continue(instr)?;
|
||||
if self.async_suspended || self.async_gen_suspended {
|
||||
self.profiling.set_instruction_count(steps);
|
||||
return Ok(JsValue::undefined());
|
||||
}
|
||||
}
|
||||
|
||||
OpCode::JMP_IF_FALSE => {
|
||||
@@ -550,7 +561,15 @@ impl Vm {
|
||||
|
||||
OpCode::RETURN => match self.dispatch_return(instr) {
|
||||
Ok(Some(result)) => return Ok(result),
|
||||
Ok(None) => {}
|
||||
Ok(None) => {
|
||||
// 逃出 for-await-of 的异步关闭可能经 await 挂起(return() 的
|
||||
// promise),挂起时须像 AWAIT 一样让内嵌 dispatch 返回,由恢复
|
||||
// 方快照状态。
|
||||
if self.async_suspended || self.async_gen_suspended {
|
||||
self.profiling.set_instruction_count(steps);
|
||||
return Ok(JsValue::undefined());
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
},
|
||||
|
||||
@@ -815,7 +834,15 @@ impl Vm {
|
||||
|
||||
OpCode::TRY_FINALLY_END => match self.dispatch_try_finally_end() {
|
||||
Ok(Some(result)) => return Ok(result),
|
||||
Ok(None) => {}
|
||||
Ok(None) => {
|
||||
// 逃出 for-await-of 的异步关闭可能经 await 挂起(return() 的
|
||||
// promise),挂起时须像 AWAIT 一样让内嵌 dispatch 返回,由恢复
|
||||
// 方快照状态。
|
||||
if self.async_suspended || self.async_gen_suspended {
|
||||
self.profiling.set_instruction_count(steps);
|
||||
return Ok(JsValue::undefined());
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
},
|
||||
|
||||
|
||||
@@ -62,6 +62,16 @@ impl Vm {
|
||||
f(self.delegated_iterator.unwrap_or(JsValue::undefined()));
|
||||
f(self.async_context.unwrap_or(JsValue::undefined()));
|
||||
f(self.async_gen_context.unwrap_or(JsValue::undefined()));
|
||||
// 在途异步逃出的 promise/完成值/剩余迭代器都是 GC 根。
|
||||
if let Some(pend) = &self.pending_async_escape {
|
||||
f(pend.close_promise);
|
||||
if let Completion::Return { value, .. } = pend.completion {
|
||||
f(value);
|
||||
}
|
||||
for &v in &pend.remaining {
|
||||
f(v);
|
||||
}
|
||||
}
|
||||
f(self.inline_callee.unwrap_or(JsValue::undefined()));
|
||||
// 标签模板对象缓存:命中的模板对象是 GC 根(未根 → sweep 搬移/回收悬垂)。
|
||||
for &cached in self.template_objects.values() {
|
||||
@@ -148,6 +158,28 @@ impl Vm {
|
||||
self.delegated_iterator = self.delegated_iterator.map(&mut rewrite);
|
||||
self.async_context = self.async_context.map(&mut rewrite);
|
||||
self.async_gen_context = self.async_gen_context.map(&mut rewrite);
|
||||
// 在途异步逃出的 promise/完成值/剩余迭代器随 sweep 重写(与 mark 段一一对应)。
|
||||
self.pending_async_escape = self.pending_async_escape.as_mut().map(|pend| {
|
||||
let completion = match pend.completion {
|
||||
Completion::Return {
|
||||
value,
|
||||
remaining_finally,
|
||||
for_of_count,
|
||||
for_in_count,
|
||||
} => Completion::Return {
|
||||
value: rewrite(value),
|
||||
remaining_finally,
|
||||
for_of_count,
|
||||
for_in_count,
|
||||
},
|
||||
other => other,
|
||||
};
|
||||
super::PendingAsyncEscape {
|
||||
close_promise: rewrite(pend.close_promise),
|
||||
completion,
|
||||
remaining: pend.remaining.iter().copied().map(&mut rewrite).collect(),
|
||||
}
|
||||
});
|
||||
self.inline_callee = self.inline_callee.map(&mut rewrite);
|
||||
for entry in &mut self.iters.for_of_iters {
|
||||
entry.iterator = rewrite(entry.iterator);
|
||||
|
||||
@@ -145,6 +145,18 @@ pub(crate) fn format_error_message(name: &str, msg: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// 逃出 for-await-of 的异步关闭在途状态:return() 的 promise 挂起等待结算,
|
||||
/// 结算闭包(微任务)恢复挂起帧后继续关闭剩余条目并执行完成。
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PendingAsyncEscape {
|
||||
/// 正在等待的 return() promise(结算闭包陈旧防御校验用)。
|
||||
pub(crate) close_promise: JsValue,
|
||||
/// 悬挂的完成(Break/Continue/Return),结算后执行。
|
||||
pub(crate) completion: Completion,
|
||||
/// 剩余待关闭的异步迭代器(LIFO 序,前元素先关)。单层路径恒空,多层路径填充。
|
||||
pub(crate) remaining: Vec<JsValue>,
|
||||
}
|
||||
|
||||
/// 基于寄存器的 JS 虚拟机:持有执行状态、寄存器文件、调用栈与 session 内存。
|
||||
///
|
||||
/// 执行入口为 [`Vm::run`](见 `vm_runtime` 模块);内存模型为 epoch arena +
|
||||
@@ -235,6 +247,9 @@ pub struct Vm {
|
||||
pub(crate) pending_error_kind: Option<&'static str>,
|
||||
/// 控制流完成(break/continue/return)暂存,finally 执行后由 TRY_FINALLY_END 恢复。
|
||||
pub(crate) pending_completion: Option<Completion>,
|
||||
/// 逃出 for-await-of 的异步关闭在途状态:return() 的 promise 挂起等待结算,
|
||||
/// 结算闭包(微任务)恢复挂起帧后继续关闭剩余条目并执行完成。
|
||||
pub(crate) pending_async_escape: Option<PendingAsyncEscape>,
|
||||
pub(crate) root_reg_limit: u8,
|
||||
pub(crate) active_reg_limit: u8,
|
||||
pub(crate) native_call_depth: usize,
|
||||
|
||||
Reference in New Issue
Block a user