Closed
Description
Given the following code:
// main.js
goog.module('_main');
const LocalConstant = {a: 5};
class Base {
constructor() {
console.log(LocalConstant);
}
}
exports.Base = Base;
console.log(LocalConstant);
// other.js
goog.module('_other');
const main_1 = goog.require('_main');
class Child extends main_1.Base {
constructor() {
super();
}
}
exports.Child = Child;
goog.global.sideeffect = new Child();
Compiling into ES2015
$ java -jar closure-compiler-v20201102.jar --language_out ECMASCRIPT_2015 --emit_use_strict false --compilation_level ADVANCED_OPTIMIZATIONS --formatting PRETTY_PRINT --js_output_file=mainout.js --chunk mainout:2 --chunk otherout:1:mainout ~/github/closure-library/closure/goog/base.js main.js other.js
Produces the following output:
mainout.js:
var a = this || self;
const c = {a:5};
console.log(c);
otherout.js:
var d = class {
constructor() {
console.log(c);
}
};
a.b = new class extends d {
constructor() {
super();
}
};
As you can see, the class Base
(d
) from main.js
has been moved to a different chunk, since it is unused in its own chunk.
Unfortunately the LocalConstant
(c
) is not available in the context of otherout.js
, because it is declared with const
in mainout.js
.
If main.js
is adjusted to include a exports.LocalConstant = LocalConstant;
then const c
becomes var c
and therefore is available in the other module.
Before ES2015 const
did not exist, so this worked without error.
There are 2 possible fixes, I am not sure which is preferred:
- Change the
CrossChunkCodeMotion
CompilerPass to not move theBase
class out of its chunk, because it is tied to the local variable, and therefore a part of the global cycle created by the side-effect of logging the constant. - Change some other (?which?) CompilerPass to synthesize the
exports.LocalConstant = LocalConstant;
I am going to start looking into the first of those as a contribution, mostly just because it seems easier.