feat: 支持 this 语法

This commit is contained in:
2026-06-07 23:07:50 +08:00
parent 7739c7a145
commit 74f4668e28
4 changed files with 65 additions and 0 deletions
+4
View File
@@ -440,6 +440,10 @@ impl Compiler {
Expression::ParenthesizedExpression(p) => {
self.count_expression(&p.expression, ctx);
}
Expression::ThisExpression(_) => {
ctx.alloc_reg();
ctx.projected_pc += 1; // LOAD_VAR from reg 254
}
Expression::UpdateExpression(update) => match &update.argument {
SimpleAssignmentTarget::AssignmentTargetIdentifier(_) => {
ctx.alloc_reg();
+5
View File
@@ -1036,6 +1036,11 @@ impl Compiler {
ctx.emit(opcode::encode(OpCode::LOAD_VAR, result_reg, 0, 0));
Ok(result_reg)
}
Expression::ThisExpression(_) => {
let r = ctx.alloc_reg();
ctx.emit(opcode::encode(OpCode::LOAD_VAR, r, 254, 0));
Ok(r)
}
_ => Err(format!("unsupported expression type: {:?}", expr)),
}
}
@@ -358,3 +358,21 @@ fn compile_compound_member_exp_ok() {
});
assert!(result.is_ok(), "obj.x**=2 should compile without error");
}
#[test]
fn compile_this_in_function_ok() {
let module = compile_source("function f() { return this; }");
assert!(!module.bytecode.is_empty());
}
#[test]
fn compile_this_member_assign_ok() {
let module = compile_source("function f() { this.x = 1; }");
assert!(!module.bytecode.is_empty());
}
#[test]
fn compile_this_member_read_ok() {
let module = compile_source("function f() { return this.x; }");
assert!(!module.bytecode.is_empty());
}
+38
View File
@@ -148,3 +148,41 @@ fn fd_returns_new_array() {
let result = eval(&mut vm, "function f() { return new Array(3); } f()").unwrap();
assert!(result.is_object());
}
// --- this expression ---
#[test]
fn this_in_function_reads_value() {
let mut vm = Vm::new();
let result = eval(&mut vm, "function f() { return this; } f()").unwrap();
assert!(
result.is_object(),
"expected object (function as this), got: {:?}",
result
);
}
#[test]
fn this_in_function_assign_member() {
let mut vm = Vm::new();
let result = eval(&mut vm, "function f(m) { this.message = m; } f('hello'); 1").unwrap();
assert_eq!(result.as_int(), 1);
}
#[test]
fn this_member_access() {
let mut vm = Vm::new();
let result = eval(&mut vm, "function f() { this.x = 42; return this.x; } f()").unwrap();
assert_eq!(result.as_int(), 42);
}
#[test]
fn this_in_constructor_sets_proto() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"function Ctor(m) { this.message = m; } Ctor.prototype = new Object(); 1",
)
.unwrap();
assert_eq!(result.as_int(), 1);
}