diff --git a/crates/oxide_vm/tests/arguments_tests.rs b/crates/oxide_vm/tests/arguments_tests.rs index bfbc893..2190045 100644 --- a/crates/oxide_vm/tests/arguments_tests.rs +++ b/crates/oxide_vm/tests/arguments_tests.rs @@ -89,7 +89,7 @@ fn arguments_frame_boundary_across_nested_calls() { // 子调用返回后父函数的 arguments 实参区仍完好(帧恢复截断不越界)。 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(); - assert!((result.as_double() - 4.0).abs() < 0.0001); + assert_eq!(result.as_int(), 4, "arguments.length 3 + g() 1 = 4"); } #[test] diff --git a/crates/oxide_vm/tests/builtins_array_tests.rs b/crates/oxide_vm/tests/builtins_array_tests.rs index a2dc619..2e9ae13 100644 --- a/crates/oxide_vm/tests/builtins_array_tests.rs +++ b/crates/oxide_vm/tests/builtins_array_tests.rs @@ -58,7 +58,7 @@ fn array_push_preserves_slots_beyond_255() { let obj = unsafe { &*result.as_js_object_ptr() }; assert_eq!(obj.prop_count(), 257); let tail = obj.get_prop_at(256); - assert_eq!(tail.as_double(), 256.0); + assert_eq!(tail.as_int(), 256, "push 循环末尾值保持 int 表示"); } #[test] diff --git a/crates/oxide_vm/tests/builtins_function_tests.rs b/crates/oxide_vm/tests/builtins_function_tests.rs index 3b18e2f..8bf2fdf 100644 --- a/crates/oxide_vm/tests/builtins_function_tests.rs +++ b/crates/oxide_vm/tests/builtins_function_tests.rs @@ -9,6 +9,12 @@ fn eval(vm: &mut Vm, source: &str) -> Result { 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] fn function_call_changes_this() { let mut vm = Vm::new(); @@ -53,21 +59,21 @@ fn function_call_bind_supports_uncurried_native_methods() { fn function_call_invokes_bytecode_function() { let mut vm = Vm::new(); 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] fn function_apply_invokes_bytecode_function() { let mut vm = Vm::new(); 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] fn function_bind_invokes_bytecode_function() { let mut vm = Vm::new(); 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] @@ -107,7 +113,7 @@ fn function_call_returns_object_stays_valid() { fn function_apply_returns_object_stays_valid() { let mut vm = Vm::new(); 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] diff --git a/crates/oxide_vm/tests/builtins_reflect_tests.rs b/crates/oxide_vm/tests/builtins_reflect_tests.rs index 7d95cec..a5ffe7c 100644 --- a/crates/oxide_vm/tests/builtins_reflect_tests.rs +++ b/crates/oxide_vm/tests/builtins_reflect_tests.rs @@ -87,8 +87,8 @@ fn reflect_apply_calls_function() { &mut vm, "function add(a, b) { return this.base + a + b; } var receiver = {base: 10}; var args = [1, 2]; Reflect.apply(add, receiver, args)", ) - .unwrap(); - assert_eq!(result.as_double(), 13.0); + .unwrap(); + assert_eq!(result.as_int(), 13, "this.base 10 + 1 + 2 = 13"); } #[test] diff --git a/crates/oxide_vm/tests/class_tests.rs b/crates/oxide_vm/tests/class_tests.rs index b465d92..dcc487f 100644 --- a/crates/oxide_vm/tests/class_tests.rs +++ b/crates/oxide_vm/tests/class_tests.rs @@ -323,9 +323,10 @@ fn private_class_fields_are_hidden_from_reflection_and_string_access() { #[test] fn private_class_fields_are_hidden_from_for_in() { let mut vm = Vm::new(); + // 公有字段 y 可枚举(计数 1),私有 #x 不可见:若 #x 泄漏则计数为 2。 let result = eval( &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(); assert_num(result, 1.0); diff --git a/crates/oxide_vm/tests/function_tests.rs b/crates/oxide_vm/tests/function_tests.rs index bf94f4f..922c63c 100644 --- a/crates/oxide_vm/tests/function_tests.rs +++ b/crates/oxide_vm/tests/function_tests.rs @@ -9,6 +9,12 @@ fn eval(vm: &mut Vm, source: &str) -> Result { 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 --- #[test] @@ -36,7 +42,7 @@ fn fd_hoisting() { fn fd_with_params() { let mut vm = Vm::new(); 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] @@ -68,15 +74,14 @@ fn fe_with_params() { fn cross_func_call() { let mut vm = Vm::new(); 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] fn two_funcs_called_from_global() { let mut vm = Vm::new(); 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!((result.as_double() - 3.0).abs() < 0.0001); + assert_num(result, 3.0); } #[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()", ) .unwrap(); - assert!((result.as_double() - 30.0).abs() < 0.0001); + assert_num(result, 30.0); } #[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()", ) .unwrap(); - assert!((result.as_double() - 30.0).abs() < 0.0001); + assert_num(result, 30.0); } // --- Builtins inside functions --- diff --git a/crates/oxide_vm/tests/scoping_tests.rs b/crates/oxide_vm/tests/scoping_tests.rs index 6b5d506..54218cd 100644 --- a/crates/oxide_vm/tests/scoping_tests.rs +++ b/crates/oxide_vm/tests/scoping_tests.rs @@ -89,7 +89,7 @@ fn closure_write_upvalue() { #[test] fn closure_nested_expr_capture() { 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]