google / google/closure-compiler
Setter side effects not accounted for in prototype methods
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
If I'm only using my property setter internally, it can get eliminated as dead code. Example (formatted for [online compiler](https://closure-compiler.appspot.com/home)):
```
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @formatting pretty_print
// ==/ClosureCompiler==
/** @constructor */
foo = function() {
this.bar = 'assigned'
};
foo.prototype.__bar_ = 'initial'
foo.prototype.getBar = function() { return this.__bar_ }
foo.prototype.setBar = function(value) { this.__bar_ = value }
foo.prototype.printBar = function() { console.log(this.__bar_) }
Object.defineProperties(foo.prototype, {
bar: {
'get': foo.prototype.getBar,
'set': foo.prototype.setBar
}
})
var myFoo = new foo()
myFoo.printBar()
```
Compiles to:
```
foo = function() {
};
foo.prototype.a = "";
var a = new foo;
console.log(a.a);
```
The getter/setter has been eliminated, including the assignment. If I use the setter from outside of the class, it is not eliminated, and both the internal assignment and external assignment are preserved:
```
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @formatting pretty_print
// ==/ClosureCompiler==
/** @constructor */
foo = function() {
this.bar = 'assigned'
};
foo.prototype.__bar_ = 'initial'
foo.prototype.getBar = function() { return this.__bar_ }
foo.prototype.setBar = function(value) { this.__bar_ = value }
foo.prototype.printBar = function() { console.log(this.__bar_) }
Object.defineProperties(foo.prototype, {
bar: {
'get': foo.prototype.getBar,
'set': foo.prototype.setBar
}
})
var myFoo = new foo()
myFoo.bar = 'external'
myFoo.printBar()
```
Result:
```
foo = function() {
this.b = "assigned";
};
foo.prototype.a = "initial";
foo.prototype.c = function() {
return this.a;
};
foo.prototype.f = function(b) {
this.a = b;
};
Object.defineProperties(foo.prototype, {b:{get:foo.prototype.c, set:foo.prototype.f}});
var a = new foo;
a.b = "external";
console.log(a.a);
```
Is there a problem with the way I'm using getter/setters here? Or any workaround that would prevent these things from being eliminated?
Contributor guide
Assessment
This issue has not been assessed yet.