google / google/closure-compiler
Compilation level BUNDLE includes polyfill code that doesn't work in modules
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
Compilation level `BUNDLE` appears to include a lot of polyfill code, even for things supported by the language setting. The real problem though is this code relies on top-level `this` to refer to the global object, and hence the produced script fails if loaded as a module (or any other strict mode environment). Files used for repro are below.
main.js:
```js
import * as Module from "./dep.js";
console.log(Module.GetMessage());
```
dep.js:
```js
export function GetMessage()
{
return "Hello world @ " + Date.now();
}
```
Command:
`java -jar ./compiler.jar --js main.js --js dep.js --dependency_mode PRUNE --entry_point main.js --compilation_level BUNDLE --language_in ECMASCRIPT_2021 --language_out ECMASCRIPT_2021 --formatting PRETTY_PRINT --js_output_file out.js`
Expected result:
If the compilation level is set to `SIMPLE`, the output looks like this (a reasonable result):
```js
function GetMessage$$module$dep() {
return "Hello world @ " + Date.now();
}
var module$dep = {};
module$dep.GetMessage = GetMessage$$module$dep;
console.log(GetMessage$$module$dep());
var module$main = {};
```
Observed result:
With the compilation level set to `BUNDLE`, there are about 700 lines of polyfill code added to the output. This appears to include things like a polyfill for map and set, which aren't necessary given the specified language in and out are ECMASCRIPT_2021. However the real problem is near the end, the polyfill code includes:
```js
this.CLOSURE_EVAL_PREFILTER = function(s) { return s; };
(function(thisValue){ /* ... contents omitted ... */)(this);
```
That code refers to top-level `this` in two places. In strict mode it will fail to run as top-level `this` is undefined. It is reasonable to expect the output to be run in strict mode, because the inputs were modules. This also looks like an oversight because earlier in the polyfill code it establishes the global object in `$jscomp.global`, so presumably that was meant to be used instead of `this`. But I'm not sure why the polyfill code is being included in the first place given the settings.
Contributor guide
Assessment
This issue has not been assessed yet.