fix: 调度标志经内联 state-swap 边界泄漏——C 侧无帧 accessor 调用继承属主调度上下文,构造帧弹出后误判提前交付、被调函数构造后字节码被跳过

根因:generator/async/construct 三个调度标志是 VM 全局字段,不经
InlineSyncState 在 state-swap 边界保存/恢复。C 侧路径(builtin 经
ordinary_get 无帧调用 accessor,走 call_bytecode_function_inline 状态
交换、不压边界帧)在生成器/异步属主 dispatch 上下文内运行时继承泄漏
标志;被调函数内 new 字节码构造器() 的构造帧是嵌套 dispatch 帧栈唯一
帧,构造器 RETURN 弹出后帧栈清空,do_return 的 frames.is_empty() &&
调度标志 误判为属主 dispatch,提前交付构造残留,被调函数构造点之后
的字节码整体不执行(getter 的 throw 被吞,属性读拿到 undefined)。
上层 FDI rest 绑定循环因此永不见 done,步数上限后初始化/恢复方把
异常折成通用错误。

修复:三标志纳入 InlineSyncState,新增 flag_zero 算子臂(save 快照
属主值并清零 VM 侧、restore 写回)——嵌套内联调用不继承外层调度
上下文。既有置位点全部在 save 之后、属主 dispatch 之前,语义不变;
do_return 交付条件注释同步更新。

回归钉:inline_dispatch_scoping_tests——C 侧 accessor 构造后 throw
穿透 instanceof Error、C 侧取值 42、字节码帧边界对照、顶层对照
(修复前两枚 C 侧钉失败)。
This commit is contained in:
2026-09-11 11:14:10 +00:00
parent 430231236d
commit 0302640056
4 changed files with 119 additions and 2 deletions
+3
View File
@@ -588,6 +588,9 @@ impl Vm {
}
}
// 生成器/异步/构造内嵌 dispatch:帧全部弹出后把结果交付恢复方,而非继续执行。
// 三个调度标志经 InlineSyncState 在 state-swap 边界清零(嵌套内联调用不继承
// 外层调度上下文),此处为真当且仅当本 dispatch 循环即标志的属主——嵌套
// 调用内的构造帧弹出只会清帧、不触发交付,被调函数剩余字节码照常执行。
if self.frames.is_empty() && (self.generator_dispatch || self.async_dispatch || self.construct_dispatch) {
// 构造内嵌:弹帧已把构造结果(非对象回退 this)写入 regs[0],直接交付。
let delivered = if self.construct_dispatch { self.regs[0] } else { result };