test: 数值断言容忍 int 表示,类私有字段 for-in 用例补公有字段

This commit is contained in:
2026-08-14 06:14:38 +08:00
parent ace6bea2c4
commit 33db6dad9c
7 changed files with 28 additions and 16 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ fn arguments_frame_boundary_across_nested_calls() {
// 子调用返回后父函数的 arguments 实参区仍完好(帧恢复截断不越界)。 // 子调用返回后父函数的 arguments 实参区仍完好(帧恢复截断不越界)。
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function g(){return 1} function f(){return arguments.length + g()}; f(4,5,6)").unwrap(); let result = eval(&mut vm, "function g(){return 1} function f(){return arguments.length + g()}; f(4,5,6)").unwrap();
assert!((result.as_double() - 4.0).abs() < 0.0001); assert_eq!(result.as_int(), 4, "arguments.length 3 + g() 1 = 4");
} }
#[test] #[test]
@@ -58,7 +58,7 @@ fn array_push_preserves_slots_beyond_255() {
let obj = unsafe { &*result.as_js_object_ptr() }; let obj = unsafe { &*result.as_js_object_ptr() };
assert_eq!(obj.prop_count(), 257); assert_eq!(obj.prop_count(), 257);
let tail = obj.get_prop_at(256); let tail = obj.get_prop_at(256);
assert_eq!(tail.as_double(), 256.0); assert_eq!(tail.as_int(), 256, "push 循环末尾值保持 int 表示");
} }
#[test] #[test]
@@ -9,6 +9,12 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
vm.run(&module) vm.run(&module)
} }
/// 数值断言:整数运算保 int,容忍 int/double 两种表示。
fn assert_num(result: JsValue, expected: f64) {
let actual = if result.is_int() { result.as_int() as f64 } else { result.as_double() };
assert!((actual - expected).abs() < 0.0001, "expected {expected}, got {actual}");
}
#[test] #[test]
fn function_call_changes_this() { fn function_call_changes_this() {
let mut vm = Vm::new(); let mut vm = Vm::new();
@@ -53,21 +59,21 @@ fn function_call_bind_supports_uncurried_native_methods() {
fn function_call_invokes_bytecode_function() { fn function_call_invokes_bytecode_function() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function add(a, b) { return a + b; } add.call(null, 2, 3)").unwrap(); let result = eval(&mut vm, "function add(a, b) { return a + b; } add.call(null, 2, 3)").unwrap();
assert!((result.as_double() - 5.0).abs() < 0.0001); assert_num(result, 5.0);
} }
#[test] #[test]
fn function_apply_invokes_bytecode_function() { fn function_apply_invokes_bytecode_function() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function add(a, b) { return a + b; } add.apply(null, [2, 3])").unwrap(); let result = eval(&mut vm, "function add(a, b) { return a + b; } add.apply(null, [2, 3])").unwrap();
assert!((result.as_double() - 5.0).abs() < 0.0001); assert_num(result, 5.0);
} }
#[test] #[test]
fn function_bind_invokes_bytecode_function() { fn function_bind_invokes_bytecode_function() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function add1(a) { return a + 1; } var bound = add1.bind(null); bound(2)").unwrap(); let result = eval(&mut vm, "function add1(a) { return a + 1; } var bound = add1.bind(null); bound(2)").unwrap();
assert!((result.as_double() - 3.0).abs() < 0.0001); assert_num(result, 3.0);
} }
#[test] #[test]
@@ -107,7 +113,7 @@ fn function_call_returns_object_stays_valid() {
fn function_apply_returns_object_stays_valid() { fn function_apply_returns_object_stays_valid() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function f(a) { return {v: a + 1}; } f.apply(null, [9]).v").unwrap(); let result = eval(&mut vm, "function f(a) { return {v: a + 1}; } f.apply(null, [9]).v").unwrap();
assert!((result.as_double() - 10.0).abs() < 0.0001); assert_num(result, 10.0);
} }
#[test] #[test]
@@ -87,8 +87,8 @@ fn reflect_apply_calls_function() {
&mut vm, &mut vm,
"function add(a, b) { return this.base + a + b; } var receiver = {base: 10}; var args = [1, 2]; Reflect.apply(add, receiver, args)", "function add(a, b) { return this.base + a + b; } var receiver = {base: 10}; var args = [1, 2]; Reflect.apply(add, receiver, args)",
) )
.unwrap(); .unwrap();
assert_eq!(result.as_double(), 13.0); assert_eq!(result.as_int(), 13, "this.base 10 + 1 + 2 = 13");
} }
#[test] #[test]
+2 -1
View File
@@ -323,9 +323,10 @@ fn private_class_fields_are_hidden_from_reflection_and_string_access() {
#[test] #[test]
fn private_class_fields_are_hidden_from_for_in() { fn private_class_fields_are_hidden_from_for_in() {
let mut vm = Vm::new(); let mut vm = Vm::new();
// 公有字段 y 可枚举(计数 1),私有 #x 不可见:若 #x 泄漏则计数为 2。
let result = eval( let result = eval(
&mut vm, &mut vm,
"class C { #x = 1; } var o = new C(); var n = 0; for (var k in o) { n = n + 1; } n", "class C { #x = 1; y = 2; } var o = new C(); var n = 0; for (var k in o) { n = n + 1; } n",
) )
.unwrap(); .unwrap();
assert_num(result, 1.0); assert_num(result, 1.0);
+11 -6
View File
@@ -9,6 +9,12 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
vm.run(&module) vm.run(&module)
} }
/// 数值断言:整数运算保 int,容忍 int/double 两种表示。
fn assert_num(result: JsValue, expected: f64) {
let actual = if result.is_int() { result.as_int() as f64 } else { result.as_double() };
assert!((actual - expected).abs() < 0.0001, "expected {expected}, got {actual}");
}
// --- Function Declaration Basics --- // --- Function Declaration Basics ---
#[test] #[test]
@@ -36,7 +42,7 @@ fn fd_hoisting() {
fn fd_with_params() { fn fd_with_params() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function add(a,b) { return a + b; } add(2, 3)").unwrap(); let result = eval(&mut vm, "function add(a,b) { return a + b; } add(2, 3)").unwrap();
assert!((result.as_double() - 5.0).abs() < 0.0001); assert_num(result, 5.0);
} }
#[test] #[test]
@@ -68,15 +74,14 @@ fn fe_with_params() {
fn cross_func_call() { fn cross_func_call() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function a() { return 1; } function b() { return a() + 2; } b()").unwrap(); let result = eval(&mut vm, "function a() { return 1; } function b() { return a() + 2; } b()").unwrap();
assert!((result.as_double() - 3.0).abs() < 0.0001); assert_num(result, 3.0);
} }
#[test] #[test]
fn two_funcs_called_from_global() { fn two_funcs_called_from_global() {
let mut vm = Vm::new(); let mut vm = Vm::new();
let result = eval(&mut vm, "function a() { return 1; } function b() { return 2; } a() + b()").unwrap(); let result = eval(&mut vm, "function a() { return 1; } function b() { return 2; } a() + b()").unwrap();
assert!(result.is_double(), "expected double, got: {:?}", result); assert_num(result, 3.0);
assert!((result.as_double() - 3.0).abs() < 0.0001);
} }
#[test] #[test]
@@ -87,7 +92,7 @@ fn call_preserves_previous_call_result_register() {
"function g() { return 10; } function h() { return 20; } function f() { return g() + h(); } f()", "function g() { return 10; } function h() { return 20; } function f() { return g() + h(); } f()",
) )
.unwrap(); .unwrap();
assert!((result.as_double() - 30.0).abs() < 0.0001); assert_num(result, 30.0);
} }
#[test] #[test]
@@ -98,7 +103,7 @@ fn call_preserves_local_across_nested_bytecode_call() {
"function g() { return 10; } function h() { return 20; } function f() { var x = g(); return x + h(); } f()", "function g() { return 10; } function h() { return 20; } function f() { var x = g(); return x + h(); } f()",
) )
.unwrap(); .unwrap();
assert!((result.as_double() - 30.0).abs() < 0.0001); assert_num(result, 30.0);
} }
// --- Builtins inside functions --- // --- Builtins inside functions ---
+1 -1
View File
@@ -89,7 +89,7 @@ fn closure_write_upvalue() {
#[test] #[test]
fn closure_nested_expr_capture() { fn closure_nested_expr_capture() {
let result = eval("function outer(){ var x=1; return function(){return x+1}()} outer()").unwrap(); let result = eval("function outer(){ var x=1; return function(){return x+1}()} outer()").unwrap();
assert_eq!(result.as_double(), 2.0); assert_eq!(result.as_int(), 2);
} }
#[test] #[test]