From 3358cf712eb7d0d18f68335e9d17411cd07275b8 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 15 Aug 2026 23:20:36 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=9D=9E=E5=B8=B8=E9=87=8F=E9=94=AE?= =?UTF-8?q?=E6=88=90=E5=91=98=20**=3D=20=E5=A4=8D=E5=90=88=E8=B5=8B?= =?UTF-8?q?=E5=80=BC=20rhs=20=E7=94=9F=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_emit/src/expr/assignment.rs | 4 +++- crates/oxide_vm/tests/object_tests.rs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/oxide_emit/src/expr/assignment.rs b/crates/oxide_emit/src/expr/assignment.rs index 8db3528..b6e1f6d 100644 --- a/crates/oxide_emit/src/expr/assignment.rs +++ b/crates/oxide_emit/src/expr/assignment.rs @@ -501,7 +501,9 @@ impl Emitter { AssignmentOperator::Multiplication => OpCode::MUL, AssignmentOperator::Division => OpCode::DIV, 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::BitwiseOR => OpCode::BIT_OR, AssignmentOperator::BitwiseXOR => OpCode::BIT_XOR, diff --git a/crates/oxide_vm/tests/object_tests.rs b/crates/oxide_vm/tests/object_tests.rs index 5b6f761..e8bb194 100644 --- a/crates/oxide_vm/tests/object_tests.rs +++ b/crates/oxide_vm/tests/object_tests.rs @@ -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"); } +#[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] fn eval_computed_compound_assign_getter_order() { // getter 场景:先触发 getter 读取,再求值 RHS。