feat: 支持 class extends 与 super 调用

This commit is contained in:
爱特每羊队
2026-06-09 09:51:34 +08:00
parent 85e78bd248
commit 5638638909
12 changed files with 478 additions and 32 deletions
+45
View File
@@ -9,6 +9,11 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
vm.run(&module)
}
fn assert_num(value: JsValue, expected: f64) {
let actual = if value.is_int() { value.as_int() as f64 } else { value.as_double() };
assert!((actual - expected).abs() < 0.0001, "expected {expected}, got {actual}");
}
#[test]
fn class_declaration_is_function_value() {
let mut vm = Vm::new();
@@ -68,3 +73,43 @@ fn class_constructor_primitive_return_preserves_instance() {
let result = eval(&mut vm, "class A { constructor() { this.x = 1; return 5; } } new A().x").unwrap();
assert_eq!(result.as_int(), 1);
}
#[test]
fn derived_constructor_super_initializes_parent_state() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"class A { constructor(){ this.x = 1 } } class B extends A { constructor(){ super(); this.y = 2 } } let b = new B(); b.x + b.y",
)
.unwrap();
assert_num(result, 3.0);
}
#[test]
fn derived_default_constructor_delegates_to_parent() {
let mut vm = Vm::new();
let result = eval(&mut vm, "class A { constructor(){ this.x = 1 } } class B extends A {} new B().x").unwrap();
assert_eq!(result.as_int(), 1);
}
#[test]
fn derived_constructor_this_before_super_throws_reference_error() {
let mut vm = Vm::new();
let err = eval(
&mut vm,
"class A { constructor(){ this.x = 1 } } class B extends A { constructor(){ this.x = 2; super(); } } new B()",
)
.unwrap_err();
assert!(err.contains("ReferenceError"), "expected ReferenceError, got: {err}");
}
#[test]
fn derived_method_super_call_uses_current_receiver() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"class A { m(){ return this.x } } class B extends A { constructor(){ super(); this.x = 2 } m(){ return super.m() + 1 } } new B().m()",
)
.unwrap();
assert_num(result, 3.0);
}
@@ -161,6 +161,15 @@ fn object_instanceof_object() {
assert_bool!(eval("({}) instanceof Object"), true, "({}) instanceof Object");
}
#[test]
fn derived_class_instanceof_parent() {
assert_bool!(
eval("class A {} class B extends A {} let b = new B(); b instanceof A"),
true,
"derived class instanceof parent"
);
}
// -- instanceof for native types should NOT respond to their own false positives --
#[test]
fn number_not_instanceof_array() {