#1709·terser

join_vars folds an assignment into an object literal with a computed accessor key, skipping the setter

Author: sarathfrancis90Created Jul 18, 2026Updated Jul 18, 2026

Bug report or Feature request?

Bug report.

Version (complete output of terser -V or specific git commit)

terser 5.49.0 (also reproduces on master, 3433d00)

Complete CLI command or minify() options used

terser test.js -c — also happens with plain minify(code) defaults.

terser input

javascript
const k = "x";
const o = {
    set [k](v) { console.log("setter ran:", v); }
};
o.x = 1;

terser output or error

javascript
const k="x",o={set[k](v){console.log("setter ran:",v)},x:1};

Running that prints nothing at all — the setter is never invoked.

Expected result

setter ran: 1, which is what node prints for the input.


The getter form loses a value rather than a call:

javascript
const k = "x";
const o = { get [k]() { return 4; } };
o.x = 8;
console.log(o.x);   // node: 4, minified: 8

join_object_assignments in lib/compress/tighten-body.js folds o.x = 1 into the literal. Before doing so it checks that no existing property already defines x, but the check is node.key.name != prop, and key.name is only meaningful for a non-computed accessor, where key is an AST_SymbolMethod. With a computed key it reads .name off whatever expression sits in the brackets — here the AST_SymbolRef k, whose name is "k" — so the collision is never seen. A static set x(v) is handled correctly, which is why this only shows up with [k].

I have a patch that bails out unless every key is statically known (a string, or the AST_SymbolMethod of a non-computed accessor), so static accessors keep folding as they do today. Full compress + mocha suites pass with it, plus the ufuzz run from CI. Happy to send it as a PR if you want it.