#5456·boa

Register forwarding can reread a mutable left operand after right-side effects

Author: dev-willbird1936Created Jul 25, 2026Updated Jul 25, 2026

Describe the bug

Register forwarding in the bytecode compiler can violate JavaScript's left-to-right operand evaluation when the left operand is a mutable local and the right operand mutates that local. The generated binary operation rereads the mutated value instead of using the value captured before evaluating the right operand.

To Reproduce

Run this script:

javascript
let a = 1;
a = a + (a = 5);
a;

Current main evaluates the final expression to 10.

The same stale-value problem affects other forwarded binary operations, for example:

javascript
let a = 1;
a = a | (a = 4); // current result: 4, expected: 5

Expected behavior

The left operand must be evaluated and retained before the right operand is evaluated. The first example should therefore produce 6, not 10.

Build environment (please complete the following information):

  • OS: Windows 11
  • Boa commit: f54077467b4b01eb0fe221cfff470a8546ebe36c
  • Target triple: x86_64-pc-windows-gnu
  • Rust toolchain: 1.95.0-x86_64-pc-windows-gnu

Additional context

The regression begins in the register-forwarding path introduced by #4845. Immutable locals and cached constants can retain the fast path; mutable locals need to be snapshotted before compiling an operand that may have side effects.