fix: for-of/for-in 提前退出时按规范顺序完成 IteratorClose

return/break/continue 逃出 for-of 时此前完全不执行 IteratorClose:
BREAK/CONTINUE/RETURN 指令现在经 ext 字携带词法逃出的迭代器层数
(for-of + for-in 各 16 位),运行时在全部 finally 穿越之后、真正
跳转/返回之前按 LIFO 关闭——与规范 §13.7.5.4(循环体完成值已含
内部 try-finally 处理,IteratorClose 在后)顺序一致。

- emit 词法:LabelCtx 增加 for-of/for-in 深度计数,loop/switch/label
  打开时快照,break/continue/return 按当前深度减目标深度计算逃出层数
  (switch 内 break 以 switch 打开点为基准,目标循环自身不计入)
- 指令编码:brk/cont/ret 三参构造,lower 跳转路径补发 ext 字
- 运行时:dispatch_break/continue/return 读取逃出计数,无 finally 时
  直接关闭后跳转/返回,有 finally 时随 Completion 悬挂由 TRY_FINALLY_END
  在穿越完成后消费;生成器 .return()/.throw() 注入经 complete_generator_return
  全关快照栈迭代器;return() 抛错经 unwind 替代完成值并关闭剩余迭代器
- 顺带:for-in 逃出残留(无 return() 语义,仅弹栈);for-await-of 的
  异步迭代器不做同步关闭(return() promise 须 await,走异步机制)
- 新增 15 项回归测试:return/labeled break/continue/switch/while/finally
  顺序/抛错优先/生成器注入/for-in/for-await-of 嵌套
This commit is contained in:
2026-08-16 09:31:39 +08:00
parent b885b672b9
commit a8378694be
23 changed files with 893 additions and 204 deletions
+7 -1
View File
@@ -127,6 +127,10 @@ pub(crate) struct ForOfEntry {
pub(crate) iterator: JsValue,
/// 本迭代器最近一次 DONE 返回的结果对象(CLOSE 判 done 用)。
pub(crate) last_result: JsValue,
/// 是否为 for-await-of 的异步迭代器:异步逃出关闭须 await return() 的
/// promise(独立异步机制),同步逃出路径(break/continue/return 计数关闭)
/// 不得同步调用其 return()。
pub(crate) is_async: bool,
}
/// for-in / for-of 的活跃迭代器状态。
@@ -154,10 +158,12 @@ impl IterState {
}
/// 压入新迭代器条目:`last_result` 初始为 undefined(尚未执行任何 next())。
pub(crate) fn push_for_of(&mut self, iterator: JsValue) {
/// `is_async` 标记 for-await-of 的异步迭代器(异步逃出关闭走独立机制)。
pub(crate) fn push_for_of(&mut self, iterator: JsValue, is_async: bool) {
self.for_of_iters.push(ForOfEntry {
iterator,
last_result: JsValue::undefined(),
is_async,
});
}