mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
If the target is `es2021` or lower, `this.#x += k`, `this.#x ??= k`, and
`++this.#x` on a private accessor give the wrong value. They should give
the new value of `#x`, but they give the return value of the setter
instead. Most setters return nothing, so the value is usually
`undefined`.
```js
class Counter {
#n = 1;
get #count() { return this.#n; }
set #count(v) { this.#n = v; }
add(k) { return (this.#count += k); }
}
console.log(new Counter().add(2)); // 3
```
The transformed code prints `undefined`, because the result of the
expression is the setter call:
```js
// before
return _set_count.call(_assertClassBrand(_Counter_brand, this), _get_count.call(_assertClassBrand(_Counter_brand, this)) + k);
// after
return _toSetter(_set_count.bind(_assertClassBrand(_Counter_brand, this)))._ = _get_count.call(_assertClassBrand(_Counter_brand, this)) + k;
```
Plain `=` and postfix `x++` are already correct, and plain `=` already
uses `_toSetter`. This PR uses the same form if the value of the
expression is used. If the expression is a statement, the output does
not change.
I did not use a temp var, because a temp var in a default parameter is
shared between calls, and a recursive setter overwrites it.
The new fixture `oxc/private-accessor-assignment-value` covers instance
and static accessors, all the operators above, an object from a function
call, arrow function bodies, and the recursive case. Its `exec.js` fails
on main with `expected 'from setter' to be 3`.
---
AI assistance was used for this change. I reviewed and tested it.
---------
Co-authored-by: qing deng <dengqing0821@gmail.com>