feat: for-of 迭代器栈条目化:迭代器与最近 next 结果配对存放

单一 last_for_of_result 槽被嵌套迭代覆盖,CLOSE 判定本迭代器是否
自然 done 时误读他者结果,导致数组解构/spread/嵌套 for-of 提前退出
漏调或误调 return()。改为栈条目 (iterator, last_result) 配对:

- IterState.for_of_iters 元素改 ForOfEntry,删除 last_for_of_result
- INIT 压条目,DONE 写本条目,NEXT/CLOSE 读本条目结果判 done
- GC mark/rewrite、inline save/restore、挂起帧快照同步配对遍历
- for-await-of 数组解构提前 break 现正确触发 return()(任务 40 样例)
This commit is contained in:
2026-08-16 04:00:06 +08:00
parent 2fc5a28876
commit 2e16b63d9b
9 changed files with 166 additions and 65 deletions
+12 -12
View File
@@ -538,7 +538,6 @@ impl Vm {
match oxide_builtins::iterator::make_iterator_for_value(self, iterable) {
Ok(iterator) => {
self.iters.push_for_of(iterator);
self.iters.clear_last_for_of_result();
Ok(())
}
Err(err) => {
@@ -557,7 +556,6 @@ impl Vm {
match crate::async_from_sync::make_async_iterator(self, iterable) {
Ok(iterator) => {
self.iters.push_for_of(iterator);
self.iters.clear_last_for_of_result();
Ok(())
}
Err(err) => {
@@ -594,14 +592,14 @@ impl Vm {
}
/// for-await-of 步进完成检查:读取 `AWAIT` 恢复值(a 槽,即迭代器结果对象)的
/// `done`,写入 last_for_of_result 并把 `!done` 写 rd(供 JMP_IF_FALSE 分支)。
/// `done`,写入本迭代器条目结果并把 `!done` 写 rd(供 JMP_IF_FALSE 分支)。
pub(crate) fn dispatch_for_await_of_done(&mut self, rd: usize, a: usize) -> Result<(), String> {
vm_trace!("FOR_AWAIT_OF_DONE rd={} r{}={:?}", rd, a, self.regs[a]);
let result = self.regs[a];
if !result.is_object() {
return self.raise_type_error("iterator result is not an object");
}
self.iters.set_last_for_of_result(result);
self.iters.set_last_result(result);
let result_obj = unsafe { &*result.as_js_object_ptr() };
let done_si = self.kernel_core.perm_interner().intern("done").0;
let done_val = match self.ordinary_get(result_obj, done_si, result) {
@@ -616,10 +614,11 @@ impl Vm {
/// 调用 `return()`,其返回的 promise 经 await 挂起,恢复后继续循环后的指令。
pub(crate) fn dispatch_for_await_of_close(&mut self) -> Result<(), String> {
vm_trace!("FOR_AWAIT_OF_CLOSE");
let Some(iterator) = self.iters.pop_for_of() else {
let Some(entry) = self.iters.pop_for_of() else {
return Ok(());
};
let result = self.iters.last_for_of_result();
let iterator = entry.iterator;
let result = entry.last_result;
if result.is_object() {
let result_obj = unsafe { &*result.as_js_object_ptr() };
let done_si = self.kernel_core.perm_interner().intern("done").0;
@@ -678,7 +677,7 @@ impl Vm {
Err(e) => return self.throw_for_of_error(e),
};
let done = to_boolean(done_val);
self.iters.set_last_for_of_result(result);
self.iters.set_last_result(result);
self.regs[rd] = JsValue::bool(!done);
Ok(())
}
@@ -686,7 +685,7 @@ impl Vm {
pub(crate) fn dispatch_for_of_next(&mut self, rd: usize) -> Result<(), String> {
vm_trace!("FOR_OF_NEXT rd={}", rd);
self.last_uncaught_value = None;
let result = self.iters.last_for_of_result();
let result = self.iters.last_result();
if !result.is_object() {
self.regs[rd] = JsValue::undefined();
return Ok(());
@@ -716,12 +715,13 @@ impl Vm {
pub(crate) fn dispatch_for_of_close(&mut self) -> Result<(), String> {
vm_trace!("FOR_OF_CLOSE");
let Some(iterator) = self.iters.pop_for_of() else {
let Some(entry) = self.iters.pop_for_of() else {
return Ok(());
};
let iterator = entry.iterator;
let result = entry.last_result;
// 迭代已自然结束(最后一次 next 返回 done:true)时不调 return();
// 仅当元素耗尽但迭代器未 done(提前退出)才执行 IteratorClose。
let result = self.iters.last_for_of_result();
if result.is_object() {
let result_obj = unsafe { &*result.as_js_object_ptr() };
let done_si = self.kernel_core.perm_interner().intern("done").0;
@@ -789,10 +789,10 @@ impl Vm {
/// 路径(它已弹出自己的迭代器)。
pub(crate) fn close_for_of_above(&mut self, depth: usize) {
while self.iters.for_of_iters.len() > depth {
let Some(iterator) = self.iters.pop_for_of() else {
let Some(entry) = self.iters.pop_for_of() else {
break;
};
let _ = self.close_for_of_iterator(iterator, true);
let _ = self.close_for_of_iterator(entry.iterator, true);
}
}