Files
OxideJS-New/crates/oxide_vm/tests/arrow_tests.rs
T
pjh123 5611d90ad0 feat: with 语句、成员位/移位复合赋值、CALL_NATIVE 无目标修复
with 语句:新增 emit 支持,with 体内自由标识符动态解析(对象属性优先,
回退外层),支持读/写/复合赋值/自增自减/delete/var 初始化动态化,
TO_OBJECT opcode 处理原始值对象,顶层 this 绑定全局对象。

复合赋值:新增 6 个 COMPOUND_MEMBER_BIT_* opcode 支持成员位/移位复合赋值,
修复 computed member 复合赋值覆盖 bug,with 内标识符复合赋值动态化。

CALL_NATIVE:实现全局 isNaN/isFinite 并绑定,用户覆盖 builtin 名时
回退通用调用路径而非报错,局部遮蔽 builtin 名走普通 CALL。

test262: with 34 pass(基线 0),compound-assignment 320 pass(基线 223)
2026-08-09 07:22:46 +08:00

129 lines
3.3 KiB
Rust

use oxide_compiler::compiler::Compiler;
use oxide_parser::Allocator;
use oxide_types::value::JsValue;
use oxide_vm::vm::Vm;
fn eval(source: &str) -> String {
let allocator = Allocator::default();
let program = match oxide_parser::parse(&allocator, source) {
Ok(p) => p,
Err(e) => return format!("parse error: {}", e[0].message),
};
let module = match Compiler::new().compile(&program) {
Ok(m) => m,
Err(e) => return format!("compile error: {}", e),
};
let mut vm = Vm::new();
match vm.run(&module) {
Ok(result) => format!("{}", result),
Err(e) => format!("vm error: {}", e),
}
}
fn eval_val(source: &str) -> (Vm, Result<JsValue, String>) {
let allocator = Allocator::default();
let program = match oxide_parser::parse(&allocator, source) {
Ok(p) => p,
Err(e) => return (Vm::new(), Err(format!("parse error: {}", e[0].message))),
};
let module = match Compiler::new().compile(&program) {
Ok(m) => m,
Err(e) => return (Vm::new(), Err(format!("compile error: {}", e))),
};
let mut vm = Vm::new();
let result = vm.run(&module);
(vm, result)
}
fn to_str(vm: &Vm, val: JsValue) -> String {
if val.is_string() {
vm.lookup_str(val).unwrap_or_default()
} else {
format!("{}", val)
}
}
// -- Arrow function integration tests --
#[test]
fn arrow_expression_body_returns_value() {
assert_eq!(eval("(() => 42)()"), "42");
}
#[test]
fn arrow_block_body_returns_value() {
assert_eq!(eval("((a,b) => { return a+b; })(3,4)"), "7");
}
#[test]
fn arrow_single_param_no_parens() {
assert_eq!(eval("(x => x * 2)(5)"), "10");
}
#[test]
fn arrow_multiple_params_with_parens() {
assert_eq!(eval("((x, y) => x + y)(3, 7)"), "10");
}
#[test]
fn arrow_stored_in_variable_callable() {
assert_eq!(eval("var f = () => 99; f()"), "99");
}
#[test]
fn arrow_stored_in_variable_with_params() {
assert_eq!(eval("var add = (a,b) => a+b; add(10,20)"), "30");
}
#[test]
fn arrow_not_constructable_throws() {
let result = eval("new (() => {})");
assert!(
result.contains("TypeError") || result.contains("arrow"),
"Expected arrow constructor TypeError, got: {}",
result
);
}
#[test]
fn arrow_no_params_string_result() {
let (vm, result) = eval_val("(() => 'hello')()");
let s = to_str(&vm, result.unwrap());
assert_eq!(s, "hello");
}
#[test]
fn arrow_expression_body_implicit_return() {
assert_eq!(eval("(() => 1 + 2)()"), "3");
}
#[test]
fn arrow_block_body_needs_explicit_return() {
assert_eq!(eval("((a,b) => { a+b; })(3,4)"), "undefined");
}
#[test]
fn arrow_at_global_scope_this_is_global_object() {
assert_eq!(eval("(() => this === globalThis)()"), "true");
}
#[test]
fn multiple_arrows_in_same_scope() {
assert_eq!(eval("var a = () => 1, b = () => 2; a() + b()"), "3");
}
// 未支持:箭头函数从外围函数捕获词法 `this` 依赖嵌套函数调用(子模块展平),
// 是既有能力限制。以下测试待能力补齐后启用:
//
// fn arrow_captures_enclosing_this() {
// // const o = {x:10, f:function(){ return (() => this.x)(); }}; o.f()
// // Expected: 10
// }
// -- Closure capture diagnostics --
#[test]
fn closure_captures_outer_let() {
assert_eq!(eval("var f; { let x = 7; f = () => x; } f()"), "7");
}