google / google/closure-compiler

Setter side effects not accounted for in prototype methods

Open
#2,632 4 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.