Closed
Description
TypeScript Version: Nightly
Search Terms: logical assignment side effect
Code
This code is from lgcl-nullish-assignment-operator-lhs-before-rhs.js, a test262 conformance test.
var assert = {
sameValue(a, b, error) {
if (a !== b) throw new Error(`${error}: ${a} !== ${b}`)
}
}
var count = 0;
var obj = {};
function incr() {
return ++count;
}
assert.sameValue(obj[incr()] ??= incr(), 2, "obj[incr()] ??= incr()");
assert.sameValue(obj[1], 2, "obj[1]");
assert.sameValue(count, 2, "count");
Expected behavior: This code should exit cleanly
Actual behavior: This code crashes with Uncaught Error: obj[incr()] ??= incr(): 3 !== 2
The problem is that TypeScript evaluates the property key in the property access twice instead of capturing the value and only evaluating it once.
TypeScript generates this (incorrect):
(_a = (_b = obj)[incr()]) !== null && _a !== void 0 ? _a : (_b[incr()] = incr());
Babel generates this (correct):
(_a = obj[_b = incr()]) !== null && _a !== void 0 ? _a : obj[_b] = incr();
Playground Link: link