fix: 非常量键成员 **= 复合赋值 rhs 生效

This commit is contained in:
2026-08-15 23:20:36 +08:00
parent 2a447b17fe
commit 3358cf712e
2 changed files with 21 additions and 1 deletions
+3 -1
View File
@@ -501,7 +501,9 @@ impl Emitter {
AssignmentOperator::Multiplication => OpCode::MUL, AssignmentOperator::Multiplication => OpCode::MUL,
AssignmentOperator::Division => OpCode::DIV, AssignmentOperator::Division => OpCode::DIV,
AssignmentOperator::Remainder => OpCode::MOD, AssignmentOperator::Remainder => OpCode::MOD,
AssignmentOperator::Exponential => OpCode::COMPOUND_EXP, // 指数无 COMPOUND_* 对应(COMPOUND_EXP 只读 [Rd,A] 会忽略 rhs):
// 走三寄存器 EXP,旧值在 a 槽(val_reg 兼 rd/a)、rhs 在 b 槽。
AssignmentOperator::Exponential => OpCode::EXP,
AssignmentOperator::BitwiseAnd => OpCode::BIT_AND, AssignmentOperator::BitwiseAnd => OpCode::BIT_AND,
AssignmentOperator::BitwiseOR => OpCode::BIT_OR, AssignmentOperator::BitwiseOR => OpCode::BIT_OR,
AssignmentOperator::BitwiseXOR => OpCode::BIT_XOR, AssignmentOperator::BitwiseXOR => OpCode::BIT_XOR,
+18
View File
@@ -91,6 +91,24 @@ fn eval_computed_compound_assign_preserves_read_before_rhs() {
assert_eq!(eval("var o={a:5}; o.a += 1, o.a"), "6"); assert_eq!(eval("var o={a:5}; o.a += 1, o.a"), "6");
} }
#[test]
fn eval_dynamic_key_compound_exp_uses_rhs() {
// 非常量键走 DYNAMIC 路径:`**=` 的指数取 RHS(EXP 读 [A,B],旧值 a 槽、rhs b 槽)。
assert_eq!(eval("var o={a:5}; var k='a'; o[k]**=2, o.a"), "25");
assert_eq!(eval("var o={a:5}; var k='a'; o[k]**=2"), "25");
// 负 number 指数:5 ** -1 = 0.2。
assert_eq!(eval("var o={a:5}; var k='a'; o[k]**=-1, o.a"), "0.2");
// BigInt:结果保持 BigInt。
assert_eq!(eval("var o={a:5n}; var k='a'; o[k]**=3n, o.a"), "BigInt(125)");
// 负 BigInt 指数抛 RangeError;BigInt/Number 混合抛 TypeError。
let err = eval("var o={a:5n}; var k='a'; o[k]**=-1n");
assert!(err.contains("RangeError"), "expected RangeError, got: {err}");
let err2 = eval("var o={a:5}; var k='a'; o[k]**=2n");
assert!(err2.contains("TypeError"), "expected TypeError, got: {err2}");
// 求值序:先读旧值再求值 RHS——RHS 副作用改写属性不影响被求幂的旧值。
assert_eq!(eval("var o={a:5}; var k='a'; function f(){o.a=100; return 2;} o[k]**=f(), o.a"), "25");
}
#[test] #[test]
fn eval_computed_compound_assign_getter_order() { fn eval_computed_compound_assign_getter_order() {
// getter 场景:先触发 getter 读取,再求值 RHS。 // getter 场景:先触发 getter 读取,再求值 RHS。