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:
@@ -124,6 +124,100 @@ fn derived_constructor_this_before_super_throws_reference_error() {
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_level_inheritance_super_chain_constructs_normally() {
|
||||
// 多层继承(≥3 层):中间 derived 帧由 SUPER_CALL 压入,合法 super() 不得误报
|
||||
// more-than-once,构造链须逐层完成。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"class A { constructor(){ this.v = 1; } } class B extends A { constructor(){ super(); this.w = 2; } } class C extends B { constructor(){ super(); this.u = 3; } } var c = new C(); c.v + c.w + c.u",
|
||||
)
|
||||
.unwrap();
|
||||
assert_num(result, 6.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intermediate_derived_returning_without_super_throws() {
|
||||
// 中间 derived 构造器未调 super 直接 return:须抛 ReferenceError(此前
|
||||
// regs[254] 值判定因 this 为外层构造对象而漏检)。
|
||||
let mut vm = Vm::new();
|
||||
let err = eval(
|
||||
&mut vm,
|
||||
"class A{} class B extends A{ constructor(){ return; } } class C extends B{} new C()",
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_returning_without_super_throws_reference_error() {
|
||||
let mut vm = Vm::new();
|
||||
let err = eval(&mut vm, "class A{} class B extends A{ constructor(){ return; } } new B()").unwrap_err();
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intermediate_derived_this_before_super_throws() {
|
||||
// 中间 derived 帧由 SUPER_CALL 压入后 super() 前读 this:须抛 ReferenceError。
|
||||
let mut vm = Vm::new();
|
||||
let err = eval(
|
||||
&mut vm,
|
||||
"class A{} class B extends A{ constructor(){ this.x = 1; super(); } } class C extends B{ constructor(){ super(); } } new C()",
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intermediate_derived_double_super_throws() {
|
||||
// 中间 derived 帧二次调用 super():须抛 more-than-once(字节码父构造器返回后
|
||||
// 置位 super_called 生效)。
|
||||
let mut vm = Vm::new();
|
||||
let err = eval(
|
||||
&mut vm,
|
||||
"class A{} class B extends A{ constructor(){ super(); super(); } } class C extends B{} new C()",
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_constructor_returning_primitive_without_super_throws() {
|
||||
// 规范 §9.2.2.2:derived 返回非对象值(42/null)且未调 super → ReferenceError,
|
||||
// 而非静默回退构造 this。
|
||||
let mut vm = Vm::new();
|
||||
let err = eval(&mut vm, "class A{} class B extends A{ constructor(){ return 42; } } new B()").unwrap_err();
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_constructor_returning_null_without_super_throws() {
|
||||
let mut vm = Vm::new();
|
||||
let err = eval(&mut vm, "class A{} class B extends A{ constructor(){ return null; } } new B()").unwrap_err();
|
||||
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_constructor_returning_object_overrides_instance() {
|
||||
// derived 返回对象值:直接作为构造结果,不校验 super。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "class A{} class B extends A{ constructor(){ return { x: 1 }; } } new B().x").unwrap();
|
||||
assert_eq!(result.as_int(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_constructor_primitive_return_after_super_preserves_this() {
|
||||
// derived 调过 super 后返回原始值:回退构造 this,实例字段保留。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"class A{ constructor(){ this.v = 5; } } class B extends A{ constructor(){ super(); return 42; } } new B().v",
|
||||
)
|
||||
.unwrap();
|
||||
assert_num(result, 5.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_method_super_call_uses_current_receiver() {
|
||||
let mut vm = Vm::new();
|
||||
|
||||
Reference in New Issue
Block a user