fix: 构造帧 super 状态改显式标志修复多层继承与 return 语义

derived 构造器 super 状态改由 CallFrame.super_called 显式标志承载,
取代依赖 regs[254] 值判定:多层继承中间 derived 帧由 SUPER_CALL 压入
this=构造对象,值判定三重失效(未调 super 不报错 / this-before-super
失效 / 合法 super() 误判 more-than-once)。父构造器正常返回经
construct_result_reg==Some(254) 识别置位调用方帧(该 ABI 不变量仅
SUPER_CALL 压帧满足),抛错走 unwind 不置位。

do_return 检查放宽为非对象返回值(含 undefined/null/原始值)且未调
super 时抛 ReferenceError(规范 §9.2.2.2),调过 super 回退构造 this。

super 构造器改取当前帧 callee 原型而非 newTarget 原型:newTarget 跨
SUPER_CALL 压帧保持为最外层类,取其原型在中间 derived 层解析回同一
父类导致无限压帧。
This commit is contained in:
2026-08-16 01:23:52 +08:00
parent 3df08dddff
commit 8c4b766e70
7 changed files with 163 additions and 8 deletions
+15 -2
View File
@@ -423,12 +423,14 @@ impl Vm {
let construct_result_reg = frame.construct_result_reg;
let constructed_this = frame.constructed_this;
let is_derived_constructor = frame.is_derived_constructor;
let super_called = frame.super_called;
let continuation = frame.continuation;
let callee_this = self.regs[254];
vm_trace!("RETURN frame: continuation={:?}, derived={}", continuation, is_derived_constructor);
self.restore_frame(frame);
if let (Some(target_reg), Some(constructed_this)) = (construct_result_reg, constructed_this) {
if is_derived_constructor && result.is_undefined() && callee_this.is_undefined() {
// 规范 §9.2.2.2:derived 构造器返回非对象值(含 undefined/null/原始值)
// 且未调用 super() 时抛 ReferenceError;调过 super() 则回退构造 this。
if is_derived_constructor && !result.is_object() && !super_called {
self.raise_error_kind("ReferenceError", "derived constructor must call super()")?;
return Ok(None);
}
@@ -447,6 +449,17 @@ impl Vm {
}
}
}
// 父构造器正常返回:super() 调用完成,置位调用方 derived 帧的 super_called。
// 识别依据:construct_result_reg == Some(254) 仅 SUPER_CALL 压帧产生(emit
// 从寄存器 ≥1 分配,254 保留给 this);父构造器抛错走 unwind 弹帧不进
// 本函数,不置位——后续 this 访问 / 再调 super 仍按未初始化报错。
if construct_result_reg == Some(254) {
if let Some(caller) = self.frames.last_mut() {
if caller.is_derived_constructor {
caller.super_called = true;
}
}
}
// 生成器/异步/构造内嵌 dispatch:帧全部弹出后把结果交付恢复方,而非继续执行。
if self.frames.is_empty() && (self.generator_dispatch || self.async_dispatch || self.construct_dispatch) {
// 构造内嵌:弹帧已把构造结果(非对象回退 this)写入 regs[0],直接交付。