Reputation: 29014
I have the following test:
goog.provide('testing.Test');
goog.require('goog.array');
/**
* @constructor
*/
testing.Test = function() {
/**
* @type {!Array.<number>}
* @private
*/
this.array_ = [];
};
/**
* @enum {number}
*/
testing.Test.Constant = {
ZERO: 0,
ONE: 1
};
testing.Test.prototype.run = function() {
if (goog.array.peek(this.array_) === testing.Test.Constant.ZERO) {
console.log('last item matches ZERO');
} else {
console.log('last item does not match ZERO');
}
};
var test = new testing.Test();
console.log(test.run());
Compiling with default optimizations and running yields the expected result:
"last item does not match ZERO"
However, compiling with ADVANCED_OPTIMIZATIONS and running yields the unexpected result:
"last item matches ZERO".
I've traced the problem to the output from the optimized compilation:
function b(){this.a=[]}console.log(function(){var a=(new b).a;a[a.length-1]?console.log("last item does not match ZERO"):console.log("last item matches ZERO")}());
The compiler appears to be replacing the conditional with a ternary, but dropping the equality check.
Is this expected behavior, and if so, what am I missing?
I am running the compiler and library available through the version 20170124.0.0 NPM packages. However every version of the compiler I've tested from NPM gives the same result.
I have an older version of the compiler jarfile that does not show the behavior. My notes suggest that this version was either downloaded or compiled by me from source in early June 2016.
Upvotes: 1
Views: 108
Reputation: 14411
This is a type-based optimization. The compiler can detect that the array never changes. Reading outside the bounds of an array is considered invalid.
You can either:
Array<number|undefined>
--use_types_for_optimization=false
See https://github.com/google/closure-compiler/issues/2136
Upvotes: 2