Rich Apodaca
Rich Apodaca

Reputation: 29014

Closure Compiler apparently replaces conditional with incorrect ternary expression

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

Answers (1)

Chad Killingsworth
Chad Killingsworth

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:

  1. Declare the array as type Array<number|undefined>
  2. Disable the type based optimizations with --use_types_for_optimization=false

See https://github.com/google/closure-compiler/issues/2136

Upvotes: 2

Related Questions