Closure Compiler 显然用不正确的三元表达式替换了条件

Closure Compiler apparently replaces conditional with incorrect ternary expression

我有以下测试:

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());

使用默认优化和 运行 编译产生预期结果:

"last item does not match ZERO"

但是,使用 ADVANCED_OPTIMIZATIONS 和 运行 编译会产生意外结果:

"last item matches ZERO".

我已经将问题追溯到优化编译的输出:

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")}());

编译器似乎将条件替换为三元,但放弃了相等性检查。

这是预期的行为吗?如果是,我错过了什么?

我是 运行 通过版本 20170124.0.0 NPM 包提供的编译器和库。但是,我从 NPM 测试过的每个版本的编译器都给出了相同的结果。

我有一个旧版本的编译器 jarfile 不显示该行为。我的笔记表明这个版本是我在 2016 年 6 月上旬从源代码下载或编译的。

这是一个 type-based 优化。编译器可以检测到数组永远不会改变。超出数组边界的读取被认为是无效的。

您可以:

  1. 将数组声明为 Array<number|undefined>
  2. 类型
  3. 使用 --use_types_for_optimization=false
  4. 禁用基于类型的优化

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